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 / order_change / paid.py
Size: Mime:
import abc
import logging
from datetime import datetime, timezone

from lib_b2b.change import ChangeRecord, ChangeDataProvider
from lib_b2b.errors import VersionConflictError
from lib_b2b.financial_status import FinancialStatus
from lib_b2b.order import Order
from lib_b2b.order_change import OrderChangeRequest, SimpleOrderPredicate
from lib_b2b.order_status import OrderStatus
from lib_b2b.policy import Policy

logger = logging.getLogger(__name__)


class OrderFinancialStatusChangeDataProvider(ChangeDataProvider, metaclass=abc.ABCMeta):
    @property
    @abc.abstractmethod
    def financial_status(self) -> FinancialStatus:
        raise NotImplementedError


class OrderFinancialStatusChangeRequest(OrderChangeRequest):
    # TODO: - Move these policies to be data driven
    _policy = Policy(
        name='financial_status_change_policy',
        subject=Policy.SUBJECT_ALL,
        predicates=[
            SimpleOrderPredicate(
                lambda o: o.status < OrderStatus.SHIPPED,
                'Paid status can only be changed prior to shipping.')
        ]
    )

    def __init__(self, on_behalf_of: str, change_data_provider: OrderFinancialStatusChangeDataProvider):
        super().__init__(on_behalf_of, OrderFinancialStatusChangeRequest._policy)
        self.change_data_provider = change_data_provider

    def will_change(self, order: Order) -> bool:
        return self.change_data_provider.financial_status > order.financial_status

    def apply(self, order: Order):
        try:
            self.changeable_object = order
            if super().permitted(order):
                if self.will_change(order):
                    before_status = order.financial_status
                    before_order_status = order.status
                    order.set_financial_status(self.change_data_provider.financial_status,
                                               version=self.change_data_provider.version())
                    if order.financial_status is FinancialStatus.PAID \
                            and order.status in (OrderStatus.UNPAID, OrderStatus.VALID):
                        order.status = OrderStatus.READY
                    order.record(ChangeRecord(
                        before={'financial_status': before_status.value, 'order_status': before_order_status.value},
                        after={'financial_status': order.financial_status.value, 'order_status': order.status.value},
                        description=f"Financial status was updated to {self.change_data_provider.financial_status.value}",
                        when=datetime.now(tz=timezone.utc), who=self.on_behalf_of)
                                 )
        except ValueError as ve:
            raise VersionConflictError(str(ve))