Source code for lambdas.create_shell_account

import logging

from constants import DATADOG_CREATE_SHELL_AC_APP_NAME, OCEAN_SSM_KEY, DD_CHECK_EVENT_CREATE_SHELL_AC, \
    NHS_DISCOUNT_CONFIG, COLLEAGUE_DISCOUNT_CONFIG
from pymorri.api.morrisons.customer import Customer
from pymorri.util.application_dependencies import ApplicationDependencies
from pymorri.api.osp.customer import OSPGetCustomer, OSPCustomer
from pymorri.util import ResponseBuilder
from pymorri.util.aws_utils import publish_event_to_sns, get_event_from_sns
from pymorri.util.serverless_utils import get_or_exception
from pymorri.util.datadog_utils import post_datadog_event_to_sns
from pymorri.exceptions import MoriException
from pymorri.util.general_utils import build_response_or_throw

logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)

deps = None


def _prepare_deps():

    global deps

    if not deps:
        deps = ApplicationDependencies(
            config_file=COLLEAGUE_DISCOUNT_CONFIG,
            ssm_param_store_name=OCEAN_SSM_KEY,
        )

[docs]def prepare_osp_payload(customer_id, customer_detail): """ This function receives customer_id and customer details from Morrisons Customer v2 API and prepares a payload to be sent to OSP to create OSP customer Args: customer_id (str) - required: customerId customer_detail (dict) - required: customer details Example: .. code-block:: python "customerId": "343434", "customer_detail": { 'sourceSystemCustomerId': '039490436575890469032', 'salutation': 'Mrs', 'firstName': 'Lindsey', 'lastName': 'Bradford', 'email': 'lindsey.bradford@morrisonsplc.co.uk', 'birthDate': 'string', 'gender': 'string', 'phoneNumber': '+7777123456', 'mobilePhone': 'string', 'address1': 'string', 'address2': 'string', 'address3': 'string', 'postcode': None, 'city': 'string', 'country': 'string', 'county': 'string', 'billingAddress1': 'string', 'billingAddress2': 'string', 'billingAddress3': 'string', 'billingPostcode': 'string', 'billingCity': 'string', 'billingCountry': 'string', 'billingCounty': 'string', 'marketingOptIn': 'string', 'thirdPartyOptIn': 'string', 'onlineAccountStatus': 'string', 'householdSize': 'string', 'dietaryPreference': 'string', 'voucherChannelPreference': 'string', 'saveVouchers': 'string', 'emailOptIn': 'string', 'mailOptIn': 'string', 'phoneOptIn': 'string', 'smsOptIn': 'string', 'researchOptIn': 'string' } Returns: osp_customer_payload (dict): Example: .. code-block:: python osp_customer_payload = { "details": { "attributes": [ { "name": "firstName", "value": "John" }, { "name": "lastName", "value": "Doe" }, { "name": "title", "value": "Mr" }, ], "emailAddress": "arif@examole.com", "fullName": f"{first_name} {last_name}", "preferredLanguage": "en-gb", "preferredName": f"{first_name} {last_name}" }, "retailerBannerIds": [ "morrisons" ], "retailerCustomerId": customer_id } """ first_name = get_or_exception(customer_detail, "firstName") last_name = get_or_exception(customer_detail, "lastName") email_address = get_or_exception(customer_detail, "email") preferred_name = f"{first_name} {last_name}" attributes_1 = { "name": "firstName", "value": first_name} attributes_2 = { "name": "lastName", "value": last_name} attributes_list = list() attributes_list.append(attributes_1) attributes_list.append(attributes_2) salutation = customer_detail.get("salutation") if salutation: attributes_list.append({ "name": "title", "value": salutation}) osp_customer_payload = { "details": { "attributes": attributes_list, "emailAddress": email_address, "fullName": preferred_name, "preferredLanguage": "en-gb", "preferredName": preferred_name }, "retailerBannerIds": ["morrisons"], "retailerCustomerId": customer_id } return osp_customer_payload
[docs]def post_sns_event_for_add_customer_to_group(customer_id, group_id, club_id, club_name, bq_date): """ This function will post an event onto sns-euw1-<ENV>>-digital-storepick-events Topic with message attribute as addCustomerToGroup Args: customer_id (str) - required: customerId group_id (str) - required: group_id to add customer to club_id (str) - required: club_id to add customer to club_name (str) - required: club_name to add customer to Example: .. code-block:: python "customerId": "343434" Returns: True (bool): on successful posting of event onto sns-euw1-<ENV>>-digital-storepick-events Topic """ sns_event = { "config_file": NHS_DISCOUNT_CONFIG, "eventType": "addCustomerToGroup", "eventData": { "customerId": customer_id, "groupId": group_id }, "bq_date": bq_date, "club_id": club_id, "club_name": club_name, } event_type = "addCustomerToGroup" publish_event_to_sns(message=sns_event, message_attribute_value=event_type) return True
[docs]@get_event_from_sns @build_response_or_throw def lambda_handler(event, context): """ Lambda receives customerId. Then confirms if it is a Morrisons customer. Then proceed to create an OSP account for the customer. Before doing so it checks whether the customer already exist in OSP. If yes throws error or if no creates the same Args: event (dict) - required: customerId Example: .. code-block:: python event = { "customerId": "343434", } event = { "Records": [ { "EventVersion": "1.0", "EventSubscriptionArn": "arn:aws:sns:us-east-2:123456789012:sns-lambda:21be56ed-a058-49f5-8c98-aedd2564c486", "EventSource": "aws:sns", "Sns": { "SignatureVersion": "1", "Timestamp": "2019-01-02T12:45:07.000Z", "Signature": "tcc6faL2yUC6dgZdmrwh1Y4cGa/ebXEkAi6RibDsvpi+tE/1+82j...65r==", "SigningCertUrl": "https://sns.us-east-2.amazonaws.com/SimpleNotificationService-ac565b8b1a6c5d002d285f9598aa1d9b.pem", "MessageId": "95df01b4-ee98-5cb9-9903-4c221d41eb5e", "Message": "{ \"eventType\": \"addCustomerToOcean\", \"eventData\": { \"customerId\": \"1234567\", \"groupId\": \"1111-2222\" }, \"config_file\": \"storepick.json\", \"bq_date\": \"2020-11-03T16:58:53.265025\", \"club_id\": \"6\", \"club_name\": \"Colleague\" }", "MessageAttributes": { "eventType": { "Type": "String", "Value": "logRowToBq" } }, "Type": "Notification", "UnsubscribeUrl": "https://sns.us-east-2.amazonaws.com/?Action=Unsubscribe&amp;SubscriptionArn=arn:aws:sns:us-east-2:123456789012:test-lambda:21be56ed-a058-49f5-8c98-aedd2564c486", "TopicArn": "arn:aws:sns:us-east-2:123456789012:sns-lambda", "Subject": "TestInvoke" } } ] } Returns: event (dict): response from the lambda Example: .. code-block:: python event = { 'status': 200, 'message': 'Shell account creation completed successfully', 'results': {}, 'headers': {'content-type': 'application/json'} } .. code-block:: python event = { 'status': 404, 'message': 'HTTP 404 - Morrisons customer not found for id 1014860340', 'results': {}, 'headers': {'content-type': 'application/json'} } .. code-block:: python event = { 'status': 500, 'message': 'Error getting Morrisons customer record for id 1014860340', 'results': {}, 'headers': {'content-type': 'application/json'} } .. code-block:: python event = { 'status': 500, 'message': 'Customer id 1014860340 already exist in OSP', 'results': {}, 'headers': {'content-type': 'application/json'} } Raises: MoriException: MoriException thrown when customerId not found in Morrisons service MoriException: MoriException thrown when customerId trying to find customer in OSP MoriException: MoriException thrown when customerId already exist in OSP MoriException: MoriException thrown when customerId trying to create customer in OSP """ ################################################################################ # need to populate the global deps (which is cached deliberately outside this # main handler ################################################################################ _prepare_deps() global deps # update event in order this function could send STATUS data to DataDog API # from build_response_or_throw event.update({ "DATADOG_APP_NAME": DATADOG_CREATE_SHELL_AC_APP_NAME, "DD_CHECK_METRIC_NAME": DD_CHECK_EVENT_CREATE_SHELL_AC, }) event_data = get_or_exception(event, "eventData") customer_id = get_or_exception(event_data, "customerId") #below code is processed only for status_code == 404 customer = Customer(configuration=deps.get_config(), ssm=deps.get_ssm_params()) customer_response = customer.request(customer_id) is_osp_customer_exist = True try: osp_customer = OSPGetCustomer(configuration=deps.get_config(), ssm=deps.get_ssm_params()) _ = osp_customer.request(customer_id) except MoriException as exc: if exc.http_status_code == 404: is_osp_customer_exist = False else: raise exc if is_osp_customer_exist: logger.warning(f"not creating shell account in OSP for customer id: {customer_id} - customer already exists") post_datadog_event_to_sns(application_name=DATADOG_CREATE_SHELL_AC_APP_NAME, metric_type="count", metric_name="ocean_shell_account_existing_ospcustomer", metric_value="1") else: osp_customer_payload = prepare_osp_payload(customer_id, customer_response.get("payload")) try: #creating customer in OSP osp_customer = OSPCustomer(configuration=deps.get_config(), ssm=deps.get_ssm_params()) osp_customer.request(payload=osp_customer_payload) except MoriException as exc: post_datadog_event_to_sns(application_name=DATADOG_CREATE_SHELL_AC_APP_NAME, metric_type="count", metric_name="ocean_shell_account_create_fail", metric_value="1") raise exc post_datadog_event_to_sns(application_name=DATADOG_CREATE_SHELL_AC_APP_NAME, metric_type="count", metric_name="ocean_shell_account_create_success", metric_value="1") logger.info(f"successfully created shell account for customer id... {customer_id}") group_id = get_or_exception(event_data, "groupId") club_id = get_or_exception(event, "club_id") club_name = get_or_exception(event, "club_name") bq_date = get_or_exception(event, "bq_date") post_sns_event_for_add_customer_to_group(customer_id, group_id, club_id, club_name, bq_date) event['response_message'] = "Shell account creation completed successfully" return event
if __name__ == "__main__": #customerId for various scenarios #happy_ scenario => "customerId": "1023421151" #mori cust not found => "customerId": "123456789" #customer exist in OSP => "customerId": "1025974228" # this is the happy_ scenario event = { "Records": [ { "Sns": { "Message": "{ \"eventType\": \"addCustomerToOcean\", \"eventData\": { \"customerId\": \"1023421151\", \"groupId\": \"1234-1234\" }, \"config_file\": \"storepick.json\", \"bq_date\": \"2020-11-03T16:58:53.265025\", \"club_id\": \"6\", \"club_name\": \"Colleague\" }", } } ] } lambda_handler(event, None)