import os import boto3 import random import uuid import json from datetime import datetime class backend: def __init__(self): self.locale = "en-US" self.snsClient = boto3.client('sns') self.connectClient = boto3.client('connect') self.connectContactFlow = os.environ['CONNECT_CONTACT_FLOW_ID'] self.connectInstanceId = os.environ['CONNECT_INSTANCE_ID'] self.connectQueueId = os.environ['CONNECT_QUEUE_ID'] self.skill_name = os.environ['SKILL_NAME'] self.sns_topic_arn = os.environ['SNS_TOPIC_ARN'] self.currency_code = os.environ['CURRENCY_CODE'] self.enable_omnichannel_integration = bool(os.environ['ENABLE_OMNICHANNEL_INTEGRATION']) dynamodbClient = boto3.resource("dynamodb", region_name=os.environ['AWS_REGION']) self.tableCustomer = dynamodbClient.Table(os.environ['CUSTOMER_TABLE_NAME']) self.tableEvents = dynamodbClient.Table(os.environ['EVENT_TABLE_NAME']) self.tableOffices = dynamodbClient.Table(os.environ['OFFICE_TABLE_NAME']) self.tableLocalization = dynamodbClient.Table(os.environ['LOCALIZATION_TABLE_NAME']) def getLocalizedMessage(self, messageId): response = self.tableLocalization.get_item(Key={"messageId": messageId, "locale": self.locale}) return response["Item"]["message"] def generateRandomPin(self): return random.randrange(1000, 9999) def getOfficeData(self, officeName): response = self.tableOffices.get_item(Key={"name": officeName}) return response def removePin(self, customerId): responseDynamo = self.tableCustomer.update_item( Key={ 'Id': customerId }, UpdateExpression='REMOVE Pin' ) def getPin(self, customerId): pin = self.generateRandomPin() responseDynamo = self.tableCustomer.update_item( Key={ 'Id': customerId }, UpdateExpression='SET Pin=:p', ExpressionAttributeValues={ ':p': pin } ) responseSns = self.snsClient.publish( TopicArn = self.sns_topic_arn, Message = "Your " + self.skill_name + " PIN is: " + str(pin), Subject = "Your " + self.skill_name + " PIN" ) output = self.getLocalizedMessage("PIN_SENT") return output def isValidPin(self, customerId, pin): data = self.getCustomerData(customerId) if "Pin" not in data["Item"]: return False if str(data["Item"]["Pin"]) == pin: return True else: return False def welcomeMessage(self, customerId): data = self.getCustomerData(customerId) if data["Item"] is None: output = self.getLocalizedMessage("NOT_FOUND") else: name = str(data["Item"]["FirstName"]) output = self.getLocalizedMessage("WELCOME").format(name) + " " + self.getLocalizedMessage("HELP") + " " + self.getLocalizedMessage("PIN_PROMPT") return output def getSavingsAccount(self, customerId, pin): if self.isValidPin(customerId, pin) == True: data = self.getCustomerData(customerId) if data["Item"] is None: output = self.getLocalizedMessage("NOT_FOUD") else: balance = str(data["Item"]["Balance"]) output = self.getLocalizedMessage("SAVINGS_ACCT_BALANCE").format(self.currency_code, balance) else: output = self.getLocalizedMessage("INVALID_PIN") return output def getCustomerData(self, customerId): response = self.tableCustomer.get_item(Key={"Id": customerId}) return response def getCreditCard(self, customerId, pin): if self.isValidPin(customerId, pin) == True: data = self.getCustomerData(customerId) if data["Item"] is None: output = self.getLocalizedMessage("NOT_FOUD") else: balance = data["Item"]["BalanceCredit"] limit = data["Item"]["CreditLimit"] dueDate = data["Item"]["PaymentDueDate"] output = self.getLocalizedMessage("CREDIT_CARD_BALANCE").format(self.currency_code, str(balance), self.currency_code, str(limit - balance), dueDate) else: output = self.getLocalizedMessage("INVALID_PIN") return output def payCreditCard(self, customerId, pin, paymentAmount): if self.isValidPin(customerId, pin) == True: responseDynamo = self.tableCustomer.update_item( Key={ 'Id': customerId }, UpdateExpression="SET #Balance = #Balance - :amount, #BalanceCredit = #BalanceCredit - :amount", ExpressionAttributeNames={ "#Balance": "Balance", "#BalanceCredit": "BalanceCredit" }, ExpressionAttributeValues={ ":amount": paymentAmount }, ReturnValues="UPDATED_NEW" ) output = self.getLocalizedMessage("CREDIT_CARD_PAYMENT").format(self.currency_code, paymentAmount) else: output = self.getLocalizedMessage("INVALID_PIN") return output def makeCreditAdvance(self, customerId, pin, requestedAmount): if self.isValidPin(customerId, pin) == True: responseDynamo = self.tableCustomer.update_item( Key={ 'Id': customerId }, UpdateExpression="SET #Balance = #Balance + :amount, #BalanceCredit = #BalanceCredit + :amount", ExpressionAttributeNames={ "#Balance": "Balance", "#BalanceCredit": "BalanceCredit" }, ExpressionAttributeValues={ ":amount": requestedAmount }, ReturnValues="UPDATED_NEW" ) output = self.getLocalizedMessage("CREDIT_ADVANCE").format(self.currency_code, requestedAmount) else: output = self.getLocalizedMessage("INVALID_PIN") return output def getOfficeSchedule(self, officeName): data = self.getOfficeData(officeName) if not "Item" in data: output = self.getLocalizedMessage("NOT FOUND") else: output = self.getLocalizedMessage("OFFICE_SCHEDULE").format(officeName, str(data["Item"]["horario"])) return output def requestCall(self, customerId): if self.enable_omnichannel_integration == False: return "This feature is not enabled" data = self.getCustomerData(customerId) if data["Item"] is None: speech_output = NOT_FOUND_MESSAGE else: phone = data["Item"]["Phone"] response = self.connectClient.start_outbound_voice_contact( DestinationPhoneNumber=phone, ContactFlowId=self.connectContactFlow, InstanceId=self.connectInstanceId, QueueId=self.connectQueueId ) output = self.getLocalizedMessage("CALL_REQUESTED") return output def logInteraction(self, customerId, intentName, botResponse): if self.enable_omnichannel_integration == True: if customerId is None: customerId = "0000000000" response = self.tableEvents.put_item( Item={ 'customerId':customerId, 'interactionDateTime': datetime.now().isoformat(), 'interactionId': uuid.uuid1().hex, 'intentName': intentName, 'botName': self.skill_name, 'slots': intentName, 'message': intentName, 'botResponse': botResponse })