Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
lib-py-b2b / customer.py
Size: Mime:
import boto3
from boto3.dynamodb.conditions import Key
from botocore.exceptions import ClientError
from .errors import CustomerLookupError, CustomerNotFoundError, TechnicalError
from os import environ
import logging
from aws_xray_sdk.core import xray_recorder

log_level = logging.getLevelName(environ['LOG_LEVEL']) if 'LOG_LEVEL' in environ else logging.INFO
logging.basicConfig(format='%(asctime)s,%(msecs)d %(levelname)-8s [%(filename)s:%(lineno)d] %(message)s',
                    datefmt='%d-%m-%Y:%H:%M:%S',
                    level=log_level)
logger = logging.getLogger('lib-b2b-customer')
customer_table = environ['customer_table'] if 'customer_table' in environ else 'test.b2b.Customer'

# TODO: - Rename this to Account and create a real customer dataclass
class Customer:

    @staticmethod
    def for_(customer):
        """
        Convert to customer if parameter is an id, otherwise return the parameter as is.
        :param customer: string or Customer object
        :return: Customer
        """
        if isinstance(customer, str):
            _customer = Customer.fetch_by_edi_id(customer)
        else:
            _customer = customer
        return _customer

    @staticmethod
    @xray_recorder.capture()
    def fetch_all(customer_mode: str = 'PROD'):
        try:
            dynamodb = boto3.resource('dynamodb', region_name='us-east-1')
            table = dynamodb.Table(customer_table)
            response = table.scan(
                FilterExpression="#m = :m",
                ExpressionAttributeValues={
                    ':m': customer_mode
                },
                ExpressionAttributeNames={
                    '#m': 'mode'
                }
            )
            return response['Items']
        except ClientError as e:
            raise CustomerLookupError(e.response['Error']['Message'])

    @staticmethod
    @xray_recorder.capture()
    def fetch_by_shopify_domain(shopify_domain):
        try:
            dynamodb = boto3.resource('dynamodb', region_name='us-east-1')
            table = dynamodb.Table(customer_table)
            response = table.query(
                IndexName='shopify_domain-index',
                KeyConditionExpression=Key('shopify_domain').eq(shopify_domain)
            )
            items = response['Items']
            if items and len(items) > 0:
                if len(items) > 1:
                    logger.warning(f"Multiple customers found for shopify domain [{shopify_domain}], [{items}]")
                return items[0]
            else:
                raise CustomerNotFoundError(f"Unable to find customer for shopify domain [{shopify_domain}]. "
                                            f"This is likely a setup problem with the customer in b2b.")
        except ClientError as e:
            raise CustomerLookupError(e.response['Error']['Message'])

    @staticmethod
    @xray_recorder.capture()
    def fetch_by_edi_id(customer_edi_id):
        try:
            dynamodb = boto3.resource('dynamodb', region_name='us-east-1')
            table = dynamodb.Table(customer_table)
            response = table.get_item(
                Key={
                    'customer_edi_id': customer_edi_id
                }
            )
            item = None
            if 'Item' in response:
                item = response['Item']
            if item:
                return item
            else:
                raise CustomerNotFoundError(f"Customer not found in system for edi id [{customer_edi_id}]"
                                            f"This is likely a setup problem with the customer in b2b.")
        except ClientError as e:
            raise CustomerLookupError(e.response['Error']['Message'])

    @staticmethod
    @xray_recorder.capture()
    def fetch_by_apikey(api_key):
        try:
            dynamodb = boto3.resource('dynamodb', region_name='us-east-1')
            table = dynamodb.Table(customer_table)
            response = table.query(
                IndexName='api_key-index',
                KeyConditionExpression=Key('api_key').eq(api_key)
            )
            items = response['Items']
            if items and len(items) > 0:
                if len(items) > 1:
                    logger.warning(f"Multiple customers found for api_key [{api_key}], [{items}]")
                return items[0]
            else:
                raise CustomerNotFoundError(f"Unable to find customer for api_key [{api_key}]. "
                                            f"This may be a problem with the customer setup or the "
                                            f"request may have been made with an invalid api key.")
        except ClientError as e:
            raise CustomerLookupError(e.response['Error']['Message'])

    @staticmethod
    @xray_recorder.capture()
    def next_po(customer_edi_id):
        try:
            dynamodb = boto3.resource('dynamodb', region_name='us-east-1')
            table = dynamodb.Table(customer_table)
            response = table.get_item(
                Key={
                    'customer_edi_id': customer_edi_id
                }
            )
            item = response['Item']
            if item:
                next_po = item.get('last_generated_po', 1000) + 1
                item['last_generated_po'] = next_po
                Customer.save(item)
                return next_po
            else:
                raise CustomerNotFoundError(f"Customer not found in system for edi id [{customer_edi_id}]"
                                            f"This is likely a setup problem with the customer in b2b.")
        except ClientError as e:
            raise CustomerLookupError(e.response['Error']['Message'])

    @staticmethod
    @xray_recorder.capture()
    def save(customer):
        try:
            dynamodb = boto3.resource('dynamodb', region_name='us-east-1')
            table = dynamodb.Table(customer_table)
            response = table.put_item(Item=customer)
            return response
        except ClientError as e:
            raise TechnicalError(e.response['Error']['Message'])