예제 #1
0
 def __init__(self):
     self.__order_storage = OrderStorageImplementation()
     self.__sqs_sender = SqsSenderImplementation()
     self.__logger = Logger()
     self.__message_storage = MessageStorageImplementation()
     self.__customer_storage = CustomerStorageImplementation()
     self.__products_storage = ProductStorageImplementation()
예제 #2
0
 def __init__(self):
     # Need to be imported here, because orders storage depends from payment method class in this file.
     from chalicelib.libs.purchase.order.storage import OrderStorageImplementation
     from chalicelib.libs.purchase.product.storage import ProductStorageImplementation
     self.__order_storage = OrderStorageImplementation()
     self.__sqs_sender = SqsSenderImplementation()
     self.__logger = Logger()
     self.__message_storage = MessageStorageImplementation()
     self.__customer_storage = CustomerStorageImplementation()
     self.__products_storage = ProductStorageImplementation()
예제 #3
0
    def __cancellation_create_submit_before_payment(order: Order, items):
        orders_storage = OrderStorageImplementation()
        products_storage = ProductStorageImplementation()
        sqs_sender = SqsSenderImplementation()
        logger = Logger()

        def __log_flow(text: str):
            logger.log_simple(
                'Cancellation for Order #{} Before Payment: {}'.format(
                    order.number.value, text))

        __log_flow('Start - {}'.format([{
            'simple_sku': item['simple_sku'].value,
            'qty': item['qty'].value,
        } for item in items]))

        # updates
        products_to_update = {}
        for item in items:
            products_to_update[
                item['simple_sku'].value] = products_storage.load(
                    item['simple_sku'])
            products_to_update[item['simple_sku'].value].restore_qty(
                item['qty'])
            order.cancel_before_payment(item['simple_sku'], item['qty'])

        order_change_event = OrderChangeSqsSenderEvent(order)

        # save order
        __log_flow('Order Saving...')
        orders_storage.save(order)
        __log_flow('Order Saved!')

        # saving products
        __log_flow('Products Saving... {}'.format(
            tuple(products_to_update.keys())))
        for product in tuple(products_to_update.values()):
            __log_flow('Product {} Saving...'.format(product.simple_sku.value))
            products_storage.update(product)
            __log_flow('Product {} Saved!'.format(product.simple_sku.value))
        __log_flow('Products Saved!')

        # send order
        __log_flow('Order SQS Sending...')
        sqs_sender.send(order_change_event)
        __log_flow('Order SQS Sent!')

        __log_flow('End')
예제 #4
0
    def cancellation_create_get_initial_data(order_number):
        user = __get_user()
        orders_storage = OrderStorageImplementation()
        products_storage = ProductStorageImplementation()

        try:
            order_number = Order.Number(order_number)
        except BaseException:
            raise BadRequestError('Incorrect Input Data!')

        order = orders_storage.load(order_number)
        if not order:
            raise NotFoundError('Order #{} does not exist!'.format(
                order_number.value))
        elif order.customer_id.value != user.id:
            raise ForbiddenError('Order #{} is not your!'.format(
                order_number.value))
        elif not order.is_cancellable:
            raise UnprocessableEntityError(
                'Order #{} is not Cancellable!'.format(order.number.value))

        products_map: Dict[str, ProductInterface] = {}
        for item in order.items:
            product = products_map.get(
                item.simple_sku.value) or products_storage.load(
                    item.simple_sku)
            products_map[item.simple_sku.value] = product

        return {
            'items': [{
                'simple_sku':
                item.simple_sku.value,
                'product_name':
                products_map[item.simple_sku.value].name.value,
                'img_url':
                (products_map[item.simple_sku.value].image_urls[0]
                 if products_map[item.simple_sku.value].image_urls else None),
                'costs': [{
                    'qty': qty,
                    'cost': item.get_refund_cost(Qty(qty)).value
                } for qty in range(1, item.qty_processable.value + 1)],
                'qty_can_cancel':
                item.qty_processable.value,
            } for item in order.items],
            'refund_methods':
            __get_refund_methods_initial_data(order),
        }
예제 #5
0
class OrderRefundSqsHandler(SqsHandlerInterface):
    def __init__(self) -> None:
        self.__messages_storage = MessageStorageImplementation()
        self.__order_storage = OrderStorageImplementation()
        self.__customer_storage = CustomerStorageImplementation()
        self.__product_storage = ProductStorageImplementation()
        self.__sqs_sender = SqsSenderImplementation()
        self.__logger = Logger()

    def handle(self, sqs_message: SqsMessage) -> None:
        def __log_flow(text: str) -> None:
            self.__logger.log_simple('{} : SQS Message #{} : {}'.format(
                self.__class__.__qualname__,
                sqs_message.id,
                text
            ))

        __log_flow('Start - {}'.format(sqs_message.message_data))

        order_number = Order.Number(sqs_message.message_data['order_number'])
        simple_sku = SimpleSku(sqs_message.message_data['simple_sku'])
        qty = Qty(sqs_message.message_data['qty'])

        __log_flow('Order Updating...')
        order = self.__order_storage.load(order_number)
        order.refund(simple_sku, qty)
        __log_flow('Order Updated!')

        __log_flow('Order Saving...')
        self.__order_storage.save(order)
        __log_flow('Order Saved!')

        __log_flow('Order SQS Sending...')
        self.__sqs_sender.send(OrderChangeSqsSenderEvent(order))
        __log_flow('Order SQS Sent!')

        # add message (silently)
        try:
            __log_flow('Notification popup: Adding...')
            customer = self.__customer_storage.get_by_id(order.customer_id)
            product = self.__product_storage.load(simple_sku)
            message = Message(
                str(uuid.uuid4()),
                customer.email.value,
                'Refund for Order #{}'.format(order.number.value),
                '"{}" has been Refunded in Qty {} for Order #{}'.format(
                    product.name.value,
                    qty.value,
                    order.number.value
                ),
            )
            self.__messages_storage.save(message)
            __log_flow('Notification popup: Added!')
        except BaseException as e:
            self.__logger.log_exception(e)
            __log_flow('Notification popup: Not Added because of Error : {}'.format(str(e)))

        __log_flow('End')
예제 #6
0
    def __get_cancellation_requests_response(requests: Tuple[CancelRequest]):
        products_storage = ProductStorageImplementation()

        products_map: Dict[str, ProductInterface] = {}
        for request in requests:
            for item in request.items:
                product = products_map.get(
                    item.simple_sku.value) or products_storage.load(
                        item.simple_sku)
                products_map[item.simple_sku.value] = product

        result = [{
            'request_number':
            request.number.value,
            'order_number':
            request.order_number.value,
            'items': [{
                'simple_sku':
                item.simple_sku.value,
                'qty':
                item.qty.value,
                'status': {
                    'value': item.status.value,
                    'label': item.status.label,
                },
                'product_name':
                products_map[item.simple_sku.value].name.value,
                'img_url':
                (products_map[item.simple_sku.value].image_urls[0]
                 if products_map[item.simple_sku.value].image_urls else None),
            } for item in request.items],
            'status': {
                'value': request.total_status.value,
                'label': request.total_status.label,
            },
            'refund_method': {
                'descriptor': request.refund_method.descriptor,
                'label': request.refund_method.label,
            },
            'additional_comment':
            request.additional_comment.value
            if request.additional_comment else None
        } for request in requests]

        return result
예제 #7
0
 def __init__(self):
     from chalicelib.libs.purchase.product.storage import ProductStorageImplementation
     from chalicelib.libs.purchase.checkout.storage import CheckoutStorageImplementation
     from chalicelib.libs.purchase.customer.storage import CustomerStorageImplementation
     from chalicelib.libs.purchase.order.dtd_calculator import DtdCalculatorImplementation
     from chalicelib.libs.purchase.order.storage import OrderStorageImplementation
     from chalicelib.libs.core.sqs_sender import SqsSenderImplementation
     from chalicelib.libs.core.mailer import MailerImplementation
     from chalicelib.libs.core.logger import Logger
     super().__init__(ProductStorageImplementation(),
                      CheckoutStorageImplementation(),
                      CustomerStorageImplementation(),
                      DtdCalculatorImplementation(),
                      OrderStorageImplementation(),
                      SqsSenderImplementation(), MailerImplementation(),
                      Logger())
예제 #8
0
    def __get_initial_data():
        orders_storage = OrderStorageImplementation()
        products_storage = ProductStorageImplementation()

        orders = []
        products_map = {}

        # "...credit-card should be allowed only when one of selected orders was paid by credit card,
        # but eft and credits should be available for all return-requests..."
        payment_refund_methods_map = {
            # @todo : payment methods descriptors
            'regular_eft': [{
                'key': refund_method.descriptor,
                'label': refund_method.label,
            } for refund_method in [
                StoreCreditRefundMethod(),
                EftRefundMethod('test', 'test', 'test')
            ]],
            'customer_credit': [{
                'key': refund_method.descriptor,
                'label': refund_method.label,
            } for refund_method in [
                StoreCreditRefundMethod(),
                EftRefundMethod('test', 'test', 'test')
            ]],
            'mobicred': [{
                'key': refund_method.descriptor,
                'label': refund_method.label,
            } for refund_method in [
                StoreCreditRefundMethod(),
                EftRefundMethod('test', 'test', 'test'),
                MobicredRefundMethod(),
            ]],
            'credit_card': [{
                'key': refund_method.descriptor,
                'label': refund_method.label,
            } for refund_method in [
                StoreCreditRefundMethod(),
                EftRefundMethod('test', 'test', 'test'),
                CreditCardRefundMethod()
            ]]
        }

        for order in orders_storage.get_all_for_customer(Id(__get_user().id)):
            if not order.is_returnable:
                continue

            items = []
            for item in order.items:
                product = products_map.get(
                    item.simple_sku.value) or products_storage.load(
                        item.simple_sku)
                products_map[item.simple_sku.value] = product

                items.append({
                    'simple_sku':
                    item.simple_sku.value,
                    'product_name':
                    product.name.value,
                    'img_url':
                    product.image_urls[0] if product.image_urls else None,
                    'costs': [{
                        'qty': qty,
                        'cost': item.get_refund_cost(Qty(qty)).value
                    } for qty in range(1, item.qty_processable.value + 1)],
                    'qty_can_return':
                    item.qty_processable.value,
                })

            orders.append({
                'order_number':
                order.number.value,
                'ordered_at':
                order.created_at.strftime('%Y-%m-%d %H:%M:%S'),
                'can_be_returned_till':
                order.is_returnable_till.strftime('%Y-%m-%d %H:%M:%S'),
                'items':
                items,
                'refund_methods':
                payment_refund_methods_map[order.payment_method.descriptor]
            })

        return {
            'reasons': [{
                'key': reason.descriptor,
                'label': reason.label,
            } for reason in [
                ReturnRequest.Item.Reason(ReturnRequest.Item.Reason.TOO_BIG),
                ReturnRequest.Item.Reason(ReturnRequest.Item.Reason.TOO_SMALL),
                ReturnRequest.Item.Reason(
                    ReturnRequest.Item.Reason.SELECTED_WRONG_SIZE),
                ReturnRequest.Item.Reason(
                    ReturnRequest.Item.Reason.DONT_LIKE_IT),
                ReturnRequest.Item.Reason(
                    ReturnRequest.Item.Reason.NOT_HAPPY_WITH_QTY),
                ReturnRequest.Item.Reason(
                    ReturnRequest.Item.Reason.RECEIVED_WRONG_SIZE),
                ReturnRequest.Item.Reason(
                    ReturnRequest.Item.Reason.RECEIVED_DAMAGED),
            ]],
            'delivery_methods': [{
                'key': delivery_method.descriptor,
                'label': delivery_method.label,
            } for delivery_method in [
                HandDeliveryMethod(),
                CourierOrPostOffice(),
                RunwaysaleToCollect()
            ]],
            'orders':
            orders,
        }
예제 #9
0
    def returns_view(return_number):
        customer_id = Id(__get_user().id)
        returns_storage = ReturnRequestStorageImplementation()
        orders_storage = OrderStorageImplementation()
        products_storage = ProductStorageImplementation()

        return_request = returns_storage.load(
            ReturnRequest.Number(return_number))
        if not return_request:
            raise NotFoundError(
                'Return Request #{} does not exist!'.format(return_number))
        elif return_request.customer_id != customer_id:
            raise ForbiddenError('It is not your Return Request!')

        response = {
            'request_number':
            return_request.number.value,
            'requested_at':
            return_request.requested_at.strftime('%Y-%m-%d %H:%M:%S'),
            'items': [],
            'delivery_method':
            return_request.delivery_method.label,
            'refund_method':
            return_request.refund_method.label,
            'status': {
                'value': return_request.total_status.value,
                'label': return_request.total_status.label,
            }
        }

        orders_map = {}
        products_map = {}
        for return_item in return_request.items:
            product = products_map.get(
                return_item.simple_sku.value) or products_storage.load(
                    return_item.simple_sku)
            products_map[return_item.simple_sku.value] = product

            order = orders_map.get(
                return_item.order_number.value) or orders_storage.load(
                    return_item.order_number)
            orders_map[return_item.order_number.value] = order

            response['items'].append({
                'order_number':
                return_item.order_number.value,
                'simple_sku':
                return_item.simple_sku.value,
                'product_name':
                product.name.value,
                'product_image_url':
                product.image_urls[0] if product.image_urls else None,
                'size_name':
                product.size_name.value,
                'ordered_at':
                order.created_at.strftime('%Y-%m-%d %H:%M:%S'),
                'cost':
                return_item.cost.value,
                'qty':
                return_item.qty.value,
                'status':
                return_item.status.label,
                'reason':
                return_item.reason.label,
                'attached_files': [{
                    'url': file.url
                } for file in return_item.attached_files],
                'additional_comment':
                return_item.additional_comment.value
                if return_item.additional_comment else None,
            })

        return response
예제 #10
0
class RegularEftPaymentSqsHandler(SqsHandlerInterface):
    def __init__(self):
        # Need to be imported here, because orders storage depends from payment method class in this file.
        from chalicelib.libs.purchase.order.storage import OrderStorageImplementation
        from chalicelib.libs.purchase.product.storage import ProductStorageImplementation
        self.__order_storage = OrderStorageImplementation()
        self.__sqs_sender = SqsSenderImplementation()
        self.__logger = Logger()
        self.__message_storage = MessageStorageImplementation()
        self.__customer_storage = CustomerStorageImplementation()
        self.__products_storage = ProductStorageImplementation()

    def handle(self, sqs_message: SqsMessage) -> None:
        def __log_flow(text: str) -> None:
            self.__logger.log_simple('{} : SQS Message #{} : {}'.format(
                self.__class__.__qualname__, sqs_message.id, text))

        __log_flow('Start')

        if sqs_message.message_type != 'regular_eft_proof_check_result':
            raise ValueError(
                '{} does not know how to handle {} sqs message! Message data: {}'
                .format(self.__class__.__qualname__, sqs_message.message_type,
                        sqs_message.message_data))

        order_number_value = sqs_message.message_data.get('order_number')
        is_proof_accepted = sqs_message.message_data.get('is_proof_accepted')

        __log_flow('Order #{} - Payment - {}'.format(
            order_number_value,
            'Accepted' if is_proof_accepted else 'Declined'))

        __log_flow('Updating...')
        order_number = Order.Number(order_number_value)
        order = self.__order_storage.load(order_number)
        if not order:
            raise ValueError(
                'Unable to handle {} sqs-message #{}: order does not exist. Message data: {}'
                .format(sqs_message.message_type, sqs_message.id,
                        sqs_message.message_data))

        if not isinstance(order.payment_method, RegularEftOrderPaymentMethod):
            raise ValueError(
                'Order #{} is not a Regular EFT payment order!'.format(
                    order.number.value))

        if is_proof_accepted:
            # accept order payment
            __log_flow('Order Updating...')
            order.status = Order.Status(Order.Status.PAYMENT_RECEIVED)
            self.__order_storage.save(order)
            __log_flow('Order Updated!')
        else:
            # Attention!
            # Order must be closed first to avoid multiple "restore-qty" actions!
            # @todo : refactoring ?

            # close order
            __log_flow('Order Closing...')
            order.status = Order.Status(Order.Status.CLOSED)
            self.__order_storage.save(order)
            __log_flow('Order Closed!')

            # restore products qty
            __log_flow('Product Qty Restoring - Start')
            for order_item in order.items:
                if order_item.qty_processable.value == 0:
                    __log_flow(
                        'Product Qty Restoring: {} skipped because of 0 qty'.
                        format(order_item.simple_sku.value))
                    continue

                try:
                    __log_flow('Product Qty Restoring {} / {} ...'.format(
                        order_item.simple_sku.value,
                        order_item.qty_processable.value))
                    product = self.__products_storage.load(
                        order_item.simple_sku)
                    product.restore_qty(order_item.qty_processable)
                    self.__products_storage.update(product)
                    __log_flow('Product Qty Restored {} / {}!'.format(
                        order_item.simple_sku.value,
                        order_item.qty_processable.value))
                except BaseException as e:
                    self.__logger.log_exception(e)
                    __log_flow(
                        'Product Qty NOT Restored {} / {} because of Error: '.
                        format(order_item.simple_sku.value,
                               order_item.qty_processable.value, str(e)))

            __log_flow('Product Qty Restoring - End')

        __log_flow('Updated!')

        # send to portal
        __log_flow('Order SQS: Sending...')
        self.__sqs_sender.send(OrderChangeSqsSenderEvent(order))
        __log_flow('Order SQS: Sent!')

        # silently add notification (silently)
        try:
            __log_flow('Notification popup: Adding...')
            customer = self.__customer_storage.get_by_id(order.customer_id)
            if not customer:
                raise ValueError(
                    '{} cant notify customer #{} about Regular-EFT payment updates for Order #{}'
                    .format(self.handle.__qualname__, order.customer_id.value,
                            order.number.value))

            self.__message_storage.save(
                Message(
                    str(uuid.uuid4()), customer.email.value,
                    'Regular EFT Payment has been checked!',
                    'Regular EFT Payment for Order #{} has been checked and {}!'
                    .format(order.number.value,
                            'Accepted' if is_proof_accepted else 'Declined')))
            __log_flow('Notification popup: Added!')
        except BaseException as e:
            self.__logger.log_exception(e)
            __log_flow(
                'Notification popup: Not Added because of Error : {}'.format(
                    str(e)))

        __log_flow('End')
예제 #11
0
class OrderPaymentOhHoldHandler(SqsHandlerInterface):
    def __init__(self):
        self.__order_storage = OrderStorageImplementation()
        self.__sqs_sender = SqsSenderImplementation()
        self.__logger = Logger()
        self.__message_storage = MessageStorageImplementation()
        self.__customer_storage = CustomerStorageImplementation()
        self.__products_storage = ProductStorageImplementation()

    def handle(self, sqs_message: SqsMessage) -> None:
        def __log_flow(text: str) -> None:
            self.__logger.log_simple('{} : SQS Message #{} : {}'.format(
                self.__class__.__qualname__,
                sqs_message.id,
                text
            ))

        __log_flow('Start : {}'.format(sqs_message.message_data))

        if sqs_message.message_type != 'fixel_order_on_hold_by_portal':
            raise ValueError('{} does not know how to handle {} sqs message! Message data: {}'.format(
                self.__class__.__qualname__,
                sqs_message.message_type,
                sqs_message.message_data
            ))

        order_number_value = sqs_message.message_data.get('order_number')
        on_hold_status = sqs_message.message_data.get('status')

        order_number = Order.Number(order_number_value)
        order = self.__order_storage.load(order_number)

        if on_hold_status == Order.Status.CLOSED:
            self.__close_order_on_hold(order, __log_flow)
        else:
            self.__on_hold_not_closed_status(order, on_hold_status, __log_flow)

        self.__send_order_change_to_portal(order, __log_flow)
        self.__notify_about_order_status_change_silently(order, __log_flow)

        __log_flow('End')

    def __on_hold_not_closed_status(self, order: Order, on_hold_status: str, __log_flow) -> None:
        __log_flow('Order Updating...')
        order.status = Order.Status(on_hold_status)
        __log_flow('Order Updated!')

        __log_flow('Order Saving...')
        self.__order_storage.save(order)
        __log_flow('Order Saved!')

    def __close_order_on_hold(self, order: Order, __log_flow) -> None:
        __log_flow('Updating...')

        # close order
        __log_flow('Order Updating...')
        order.status = Order.Status(Order.Status.CLOSED)
        __log_flow('Order Updated!')

        # restore products qty
        __log_flow('Product Qty Updating - Start')
        products_to_save = []
        for order_item in order.items:
            if order_item.qty_processable.value == 0:
                __log_flow('Product Qty Updating: {} skipped because of 0 qty'.format(order_item.simple_sku.value))
                continue

            __log_flow('Product Qty Updating {} / {} ...'.format(
                order_item.simple_sku.value,
                order_item.qty_processable.value
            ))

            product = self.__products_storage.load(order_item.simple_sku)
            product.restore_qty(order_item.qty_processable)
            products_to_save.append(product)

            __log_flow('Product Qty Updated {} / {}!'.format(
                order_item.simple_sku.value,
                order_item.qty_processable.value
            ))

        __log_flow('Product Qty Updating - End')

        __log_flow('Updated!')

        __log_flow('Saving...')

        __log_flow('Order Saving...')
        self.__order_storage.save(order)
        __log_flow('Order Saved!')

        __log_flow('Products Saving...')
        for product in products_to_save:
            __log_flow('Product {} Saving...'.format(product.simple_sku.value))
            self.__products_storage.update(product)
            __log_flow('Product {} Saved!'.format(product.simple_sku.value))
        __log_flow('Products Saved!')

        __log_flow('Saved!')

    def __send_order_change_to_portal(self, order: Order, __log_flow) -> None:
        __log_flow('Order SQS: Sending...')
        self.__sqs_sender.send(OrderChangeSqsSenderEvent(order))
        __log_flow('Order SQS: Sent!')

    def __notify_about_order_status_change_silently(self, order: Order, __log_flow) -> None:
        try:
            __log_flow('Notification popup: Adding...')
            customer = self.__customer_storage.get_by_id(order.customer_id)
            self.__message_storage.save(Message(
                str(uuid.uuid4()),
                customer.email.value,
                'Order #{} status is changed!',
                'Order #{} has been turned to "{}" status!'.format(order.number.value, order.status.label)
            ))
            __log_flow('Notification popup: Added!')
        except BaseException as e:
            self.__logger.log_exception(e)
            __log_flow('Notification popup: Not Added because of Error : {}'.format(str(e)))
예제 #12
0
class CancelledOrderOnPortalSideSqsHandle(SqsHandlerInterface):
    def __init__(self):
        self.__orders_storage = OrderStorageImplementation()
        self.__products_storage = ProductStorageImplementation()
        self.__cancel_request_storage = CancelRequestStorageImplementation()
        self.__customer_storage = CustomerStorageImplementation()
        self.__messages_storage = MessageStorageImplementation()
        self.__sqs_sender = SqsSenderImplementation()
        self.__logger = Logger()

    def handle(self, sqs_message: SqsMessage) -> None:
        def __log_flow(text: str) -> None:
            self.__logger.log_simple('{} : {} : {}'.format(
                self.__class__.__qualname__,
                sqs_message.id,
                text
            ))

        __log_flow('Start - {}'.format(sqs_message.message_data))

        order_number = Order.Number(sqs_message.message_data['order_number'])
        simple_sku = SimpleSku(sqs_message.message_data['simple_sku'])
        qty = Qty(sqs_message.message_data['qty'])

        order = self.__orders_storage.load(order_number)
        product = self.__products_storage.load(simple_sku)

        if order.was_paid:
            order.request_cancellation_after_payment(simple_sku, qty)
            order.approve_cancellation_after_payment(simple_sku, qty)
        else:
            order.cancel_before_payment(simple_sku, qty)

        product.restore_qty(qty)
        order_change_event = OrderChangeSqsSenderEvent(order)

        __log_flow('Order Saving...')
        self.__orders_storage.save(order)
        __log_flow('Order Saved!')

        __log_flow('Product Saving...')
        self.__products_storage.update(product)
        __log_flow('Product Saved!')

        __log_flow('Order SQS Sending...')
        self.__sqs_sender.send(order_change_event)
        __log_flow('Order SQS Sent!')

        try:
            __log_flow('Notification popup: Adding...')
            customer = self.__customer_storage.get_by_id(order.customer_id)
            message = Message(
                str(uuid.uuid4()),
                customer.email.value,
                'Order #{} has been Updated!'.format(order.number.value),
                'Product "{}" for Order #{} has been Cancelled in Qty {}!'.format(
                    product.name.value,
                    order.number.value,
                    qty.value
                ),
            )
            self.__messages_storage.save(message)
            __log_flow('Notification popup: Added!')
        except BaseException as e:
            self.__logger.log_exception(e)
            __log_flow('Notification popup: Not Added because of Error : {}'.format(str(e)))

        __log_flow('End')
예제 #13
0
class ReturnRequestChangeSqsHandler(SqsHandlerInterface):
    def __init__(self):
        self.__returns_storage = ReturnRequestStorageImplementation()
        self.__order_storage = OrderStorageImplementation()
        self.__customer_storage = CustomerStorageImplementation()
        self.__product_storage = ProductStorageImplementation()
        self.__messages_storage = MessageStorageImplementation()
        self.__sqs_sender = SqsSenderImplementation()
        self.__logger = Logger()

    def handle(self, sqs_message: SqsMessage) -> None:
        def __log_flow(text: str) -> None:
            self.__logger.log_simple('{} : {} : {}'.format(
                self.__class__.__qualname__,
                sqs_message.id,
                text
            ))

        __log_flow('Start - {}'.format(sqs_message.message_data))

        request_number = sqs_message.message_data.get('return_request_number')
        order_number = sqs_message.message_data.get('order_number')
        simple_sku = sqs_message.message_data.get('simple_sku')
        status = sqs_message.message_data.get('status')

        __log_flow('Updating...')
        return_request = self.__returns_storage.load(ReturnRequest.Number(request_number))
        if not return_request:
            raise ValueError('{} can\'t handle SQS message {}:{}! Return Request does not exist!'.format(
                self.handle.__qualname__,
                sqs_message.message_type,
                sqs_message.message_data
            ))

        actions_map = {
            'approved': self.__approve,
            'cancelled': self.__decline,
            'closed': self.__close,
        }

        action = actions_map.get(status)
        if not action:
            raise Exception('{} can\'t handle SQS message {}:{}! Status is unknown!'.format(
                self.handle.__qualname__,
                sqs_message.message_type,
                sqs_message.message_data
            ))

        action(return_request, OrderNumber(order_number), SimpleSku(simple_sku), __log_flow)
        __log_flow('Updated!')

        __log_flow('End')

    def __approve(
        self,
        return_request: ReturnRequest,
        order_number: OrderNumber,
        simple_sku: SimpleSku,
        __log_flow
    ) -> None:
        __log_flow('Approving...')

        return_request.make_item_approved(order_number, simple_sku)

        __log_flow('Return Request Saving...')
        self.__returns_storage.save(return_request)
        __log_flow('Return Request Saved!')

        try:
            __log_flow('Notification popup: Adding...')
            self.__add_notification_message(return_request, order_number, simple_sku, 'Approved')
            __log_flow('Notification popup: Added!')
        except BaseException as e:
            self.__logger.log_exception(e)
            __log_flow('Notification popup: Not Added because of Error : {}'.format(str(e)))

        __log_flow('Approved!')

    def __decline(
        self,
        return_request: ReturnRequest,
        order_number: OrderNumber,
        simple_sku: SimpleSku,
        __log_flow
    ) -> None:
        __log_flow('Declining...')

        qty = return_request.get_item_qty(order_number, simple_sku)
        order = self.__order_storage.load(order_number)

        # updating
        return_request.make_item_declined(order_number, simple_sku)
        order.decline_return(simple_sku, qty)

        # saving
        __log_flow('Declining: Return Request Saving...')
        self.__returns_storage.save(return_request)
        __log_flow('Declining: Return Request Saved!')

        __log_flow('Declining: Order Saving...')
        self.__order_storage.save(order)
        __log_flow('Declining: Order Saved!')

        # add notification silently
        try:
            __log_flow('Notification popup: Adding...')
            self.__add_notification_message(return_request, order_number, simple_sku, 'Declined')
            __log_flow('Notification popup: Added!')
        except BaseException as e:
            self.__logger.log_exception(e)
            __log_flow('Notification popup: Not Added because of Error : {}'.format(str(e)))

        __log_flow('Declined!')

    def __close(
        self,
        return_request: ReturnRequest,
        order_number: OrderNumber,
        simple_sku: SimpleSku,
        __log_flow
    ) -> None:
        __log_flow('Closing...')

        qty = return_request.get_item_qty(order_number, simple_sku)
        product = self.__product_storage.load(simple_sku)
        order = self.__order_storage.load(order_number)

        product.restore_qty(qty)
        order.close_return(simple_sku, qty)
        return_request.make_item_closed(order_number, simple_sku)

        # update product
        __log_flow('Closing: Product Qty: Restoring...')
        self.__product_storage.update(product)
        __log_flow('Closing: Product Qty: Restored!')

        # update order
        __log_flow('Closing: Order Qty: Returning...')
        self.__order_storage.save(order)
        __log_flow('Closing: Order Qty: Returned!')

        # update request
        __log_flow('Closing: Return Request: Updating...')
        self.__returns_storage.save(return_request)
        __log_flow('Closing: Return Request: Updated!')

        __log_flow('Closing: Order SQS: Sending...')
        self.__sqs_sender.send(OrderChangeSqsSenderEvent(order))
        __log_flow('Closing: Order SQS: Sent!')

        # add notification silently
        try:
            __log_flow('Notification popup: Adding...')
            self.__add_notification_message(return_request, order_number, simple_sku, 'Closed')
            __log_flow('Notification popup: Added!')
        except BaseException as e:
            self.__logger.log_exception(e)
            __log_flow('Notification popup: Not Added because of Error : {}'.format(str(e)))

        __log_flow('Closed!')

    def __add_notification_message(
        self,
        return_request: ReturnRequest,
        order_number: OrderNumber,
        simple_sku: SimpleSku,
        status_label: str
    ) -> None:
        order = self.__order_storage.load(order_number)
        customer = self.__customer_storage.get_by_id(order.customer_id)
        product = self.__product_storage.load(simple_sku)
        message = Message(
            str(uuid.uuid4()),
            customer.email.value,
            'Return Request #{} has been Updated!'.format(return_request.number.value),
            'Return Request for Product "{}" for Order #{} has been {}!'.format(
                product.name.value,
                order_number.value,
                status_label
            ),
        )
        self.__messages_storage.save(message)
예제 #14
0
 def __init__(self):
     self.__storage = _CartDynamoDbStorage(ProductStorageImplementation())
예제 #15
0
class CancelRequestPaidOrderAnswerSqsHandler(SqsHandlerInterface):
    def __init__(self):
        self.__orders_storage = OrderStorageImplementation()
        self.__products_storage = ProductStorageImplementation()
        self.__cancel_request_storage = CancelRequestStorageImplementation()
        self.__customer_storage = CustomerStorageImplementation()
        self.__messages_storage = MessageStorageImplementation()
        self.__sqs_sender = SqsSenderImplementation()
        self.__logger = Logger()

    def handle(self, sqs_message: SqsMessage) -> None:
        def __log_flow(text: str) -> None:
            self.__logger.log_simple('{} : {} : {}'.format(
                self.__class__.__qualname__,
                sqs_message.id,
                text
            ))

        __log_flow('Start - {}'.format(sqs_message.message_data))

        request_number = CancelRequest.Number(sqs_message.message_data['request_number'])
        order_number = Order.Number(sqs_message.message_data['order_number'])
        simple_sku = SimpleSku(sqs_message.message_data['simple_sku'])
        qty = Qty(sqs_message.message_data['qty'])
        status = sqs_message.message_data['status']

        actions_map = {
            'approved': self.__approve,
            'declined': self.__decline,
        }

        action = actions_map.get(status)
        if not action:
            raise Exception('{} can\'t handle SQS message {}:{}! Status is unknown!'.format(
                self.handle.__qualname__,
                sqs_message.message_type,
                sqs_message.message_data
            ))

        action(request_number, order_number, simple_sku, qty, __log_flow)

        __log_flow('End')

    def __approve(
        self,
        request_number: CancelRequest.Number,
        order_number: Order.Number,
        simple_sku: SimpleSku,
        qty: Qty,
        __log_flow
    ) -> None:
        __log_flow('Approving...')

        cancel_request = self.__cancel_request_storage.get_by_number(request_number)
        order = self.__orders_storage.load(order_number)
        product = self.__products_storage.load(simple_sku)

        cancel_request.approve_item(simple_sku)
        order.approve_cancellation_after_payment(simple_sku, qty)
        product.restore_qty(qty)
        order_change_event = OrderChangeSqsSenderEvent(order)

        __log_flow('Cancel Request Saving...')
        self.__cancel_request_storage.save(cancel_request)
        __log_flow('Cancel Request Saved!')

        __log_flow('Order Saving...')
        self.__orders_storage.save(order)
        __log_flow('Order Saved!')

        __log_flow('Product Saving...')
        self.__products_storage.update(product)
        __log_flow('Product Saved!')

        __log_flow('Order SQS Sending...')
        self.__sqs_sender.send(order_change_event)
        __log_flow('Order SQS Sent!')

        try:
            __log_flow('Notification popup: Adding...')
            self.__add_notification_message(cancel_request, order, product, 'Approved')
            __log_flow('Notification popup: Added!')
        except BaseException as e:
            self.__logger.log_exception(e)
            __log_flow('Notification popup: Not Added because of Error : {}'.format(str(e)))

        __log_flow('Approved!')

    def __decline(
        self,
        request_number: CancelRequest.Number,
        order_number: Order.Number,
        simple_sku: SimpleSku,
        qty: Qty,
        __log_flow
    ) -> None:
        __log_flow('Declining...')

        cancel_request = self.__cancel_request_storage.get_by_number(request_number)
        order = self.__orders_storage.load(order_number)
        product = self.__products_storage.load(simple_sku)

        cancel_request.decline_item(simple_sku)
        order.decline_cancellation_after_payment(simple_sku, qty)
        order_change_event = OrderChangeSqsSenderEvent(order)

        __log_flow('Cancel Request Saving...')
        self.__cancel_request_storage.save(cancel_request)
        __log_flow('Cancel Request Saved!')

        __log_flow('Order Saving...')
        self.__orders_storage.save(order)
        __log_flow('Order Saved!')

        __log_flow('Order SQS Sending...')
        self.__sqs_sender.send(order_change_event)
        __log_flow('Order SQS Sent!')

        try:
            __log_flow('Notification popup: Adding...')
            self.__add_notification_message(cancel_request, order, product, 'Declined')
            __log_flow('Notification popup: Added!')
        except BaseException as e:
            self.__logger.log_exception(e)
            __log_flow('Notification popup: Not Added because of Error : {}'.format(str(e)))

        __log_flow('Declined!')

    def __add_notification_message(
        self,
        cancel_request: CancelRequest,
        order: Order,
        product: ProductInterface,
        status_label: str
    ) -> None:
        customer = self.__customer_storage.get_by_id(order.customer_id)
        message = Message(
            str(uuid.uuid4()),
            customer.email.value,
            'Cancellation Request #{} has been Updated!'.format(cancel_request.number.value),
            'Cancellation Request for Product "{}" for Order #{} has been {}!'.format(
                product.name.value,
                order.number.value,
                status_label
            ),
        )
        self.__messages_storage.save(message)
예제 #16
0
 def __init__(self):
     from chalicelib.libs.purchase.customer.storage import CustomerStorageImplementation
     from chalicelib.libs.purchase.product.storage import ProductStorageImplementation
     self.__storage = _CheckoutDynamoDbStorage(
         CustomerStorageImplementation(), ProductStorageImplementation())
예제 #17
0
 def __init__(self):
     self.__service = _CartAppService(
         ProductStorageImplementation(),
         CartStorageImplementation(),
         Percentage(PurchaseSettings().vat)
     )