Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions connect/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from .company import Company, User
from .connection import Connection
from .contact import Contact, ContactInfo, PhoneNumber
from .conversation import Conversation, ConversationMessage
from .event import EventInfo, Events
from .fulfillment import Fulfillment
from .hub import Hub, HubInstance, ExtIdHub, HubStats
Expand All @@ -34,6 +35,8 @@
'Contact',
'ContactInfo',
'Contract',
'Conversation',
'ConversationMessage',
'CustomerUiSettings',
'Document',
'DownloadLink',
Expand Down
70 changes: 70 additions & 0 deletions connect/models/conversation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# -*- coding: utf-8 -*-

# This file is part of the Ingram Micro Cloud Blue Connect SDK.
# Copyright (c) 2019 Ingram Micro. All Rights Reserved.

import datetime

from typing import List

from .base import BaseModel
from .company import User
from connect.models.schemas import ConversationMessageSchema, ConversationSchema


class ConversationMessage(BaseModel):
""" Message in a :py:class:`.Conversation`. """

_schema = ConversationMessageSchema()

conversation = None # type: str
""" (str) Primary ID of Conversation object. """

created = None # type: datetime.datetime
""" (datetime.datetime) Date of the Message creation. """

creator = None # type: User
""" (:py:class:`.User`) :py:class:`.User` that created the message. """

text = None # type: str
""" (str) Actual message. """


class Conversation(BaseModel):
""" Conversation. """

_schema = ConversationSchema()

instance_id = None # type: str
""" (str) The id of object based on which discussion is made, e.g. listing request.
It can be any object.
"""

created = None # type: datetime.datetime
""" (datetime.datetime) Date of the Conversation creation. """

topic = None # type: str
""" (str) Conversation topic. """

messages = None # type: List[ConversationMessage]
""" (List[:py:class:`.ConversationMessage`]) List of :py:class:`.ConversationMessage`
objects.
"""

creator = None # type: User
""" (:py:class:`.User`) Creator of the conversation. """

def add_message(self, message, config=None):
""" Adds a message to the conversation.

:param str message: Message to add.
:param Config config: Configuration, or ``None`` to use the environment config (default).
:return: The added message.
:rtype: ConversationMessage
:raises TypeError: Raised if the message cannot be deserialized.
"""

from connect.resources.base import ApiClient
response, _ = ApiClient(config, base_path='conversations/' + self.id + '/messages')\
.post(json={'text': message})
return ConversationMessage.deserialize(response)
21 changes: 21 additions & 0 deletions connect/models/fulfillment.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

from .asset import Asset
from .base import BaseModel
from .conversation import Conversation
from .marketplace import Contract, Marketplace
from connect.models.schemas import FulfillmentSchema

Expand Down Expand Up @@ -113,3 +114,23 @@ def needs_migration(self, migration_key='migration_info'):
:rtype: bool
"""
return self.asset.get_param_by_id(migration_key) is not None

def get_conversation(self, config=None):
"""
:param Config config: Configuration, or ``None`` to use the environment config (default).
:return: The conversation for this request, or ``None`` if there is none.
:rtype: Conversation|None
"""
from connect.resources.base import ApiClient

client = ApiClient(config, base_path='conversations')
response, _ = client.get(params={'instance_id': self.id})
try:
conversations = Conversation.deserialize(response)
if conversations and conversations[0].id:
response, _ = client.get(conversations[0].id)
return Conversation.deserialize(response)
else:
return None
except ValueError:
return None
25 changes: 25 additions & 0 deletions connect/models/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -567,3 +567,28 @@ class UsageRecordSchema(BaseSchema):
def make_object(self, data):
from connect.models import UsageRecord
return UsageRecord(**data)


class ConversationMessageSchema(BaseSchema):
conversation = fields.Str()
created = fields.DateTime()
creator = fields.Nested(UserSchema)
text = fields.Str()

@post_load
def make_object(self, data):
from connect.models import ConversationMessage
return ConversationMessage(**data)


class ConversationSchema(BaseSchema):
instance_id = fields.Str()
created = fields.DateTime()
topic = fields.Str()
messages = fields.Nested(ConversationMessageSchema, many=True)
creator = fields.Nested(UserSchema)

@post_load
def make_object(self, data):
from connect.models import Conversation
return Conversation(**data)
58 changes: 46 additions & 12 deletions connect/resources/fulfillment_automation.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,35 +50,69 @@ def filters(self, status='pending', **kwargs):

def dispatch(self, request):
# type: (Fulfillment) -> str

conversation = request.get_conversation(self.config)

try:
if self.config.products \
and request.asset.product.id not in self.config.products:
return 'Invalid product'

logger.info('Start request process / ID request - {}'.format(request.id))
result = self.process_request(request)
process_result = self.process_request(request)

if not result:
if not process_result:
logger.info('Method `process_request` did not return result')
return ''

params = {}
if isinstance(result, ActivationTileResponse):
params = {'activation_tile': result.tile}
elif isinstance(result, ActivationTemplateResponse):
params = {'template_id': result.template_id}

return self.approve(request.id, params)
if isinstance(process_result, ActivationTileResponse):
message = 'Activated using custom activation tile.'
approved = self.approve(request.id, {'activation_tile': process_result.tile})
elif isinstance(process_result, ActivationTemplateResponse):
message = 'Activated using template {}.'.format(process_result.template_id)
approved = self.approve(request.id, {'template_id': process_result.template_id})
else:
# We should not get here
message = ''
approved = ''

if conversation:
try:
conversation.add_message(message)
except TypeError as ex:
logger.error('Error updating conversation for request {}: {}'
.format(request.id, ex))
return approved

except InquireRequest as inquire:
self.update_parameters(request.id, inquire.params)
return self.inquire(request.id)
inquired = self.inquire(request.id)
try:
conversation.add_message(str(inquire))
except TypeError as ex:
logger.error('Error updating conversation for request {}: {}'
.format(request.id, ex))
return inquired

except FailRequest as fail:
return self.fail(request.id, reason=str(fail))
# PyCharm incorrectly detects unreachable code here, so disable
# noinspection PyUnreachableCode
failed = self.fail(request.id, reason=str(fail))
try:
conversation.add_message(str(fail))
except TypeError as ex:
logger.error('Error updating conversation for request {}: {}'
.format(request.id, ex))
return failed

except SkipRequest as skip:
return skip.code
skipped = skip.code
try:
conversation.add_message(str(skip))
except TypeError as ex:
logger.error('Error updating conversation for request {}: {}'
.format(request.id, ex))
return skipped

@deprecated(deprecated_in='16.0', details='Use ``TierConfig.get`` instead.')
def get_tier_config(self, tier_id, product_id):
Expand Down
10 changes: 10 additions & 0 deletions tests/data/add_message_response.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"id": "ME-000-000-000",
"conversation": "CO-000-000-000",
"created": "2018-12-18T13:03:30+00:00",
"creator": {
"id": "UR-000-000-000",
"name": "Some User"
},
"text": "Hi, please see my listing request"
}
22 changes: 22 additions & 0 deletions tests/data/conversation.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"id": "CO-750-033-356",
"instance_id": "LST-038-662-242",
"created": "2018-12-18T12:49:34+00:00",
"topic": "Topic",
"messages": [
{
"id": "ME-506-258-087",
"conversation": "CO-750-033-356",
"created": "2018-12-18T13:03:30+00:00",
"creator": {
"id": "UR-922-977-649",
"name": "Some User"
},
"text": "Hi, check out"
}
],
"creator": {
"id": "UR-922-977-649",
"name": "Some User"
}
}
Loading