Repository URL to install this package:
|
Version:
0.4.202 ▾
|
import abc
import logging
from datetime import datetime
from typing import Optional
from boto3.dynamodb.conditions import Attr, And
from dateutil.tz import UTC
from lib_b2b.change import ChangeRecord, ChangeDataProvider
from lib_b2b.errors import ChangeNotAllowed, VersionConflictError
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 OrderRevisionChangeDataProvider(ChangeDataProvider, metaclass=abc.ABCMeta):
@property
@abc.abstractmethod
def new_revision(self) -> Optional[int]:
raise NotImplementedError
@property
@abc.abstractmethod
def request(self) -> 'OrderRequest':
raise NotImplementedError
class OrderRevisionChangeRequest(OrderChangeRequest):
# TODO: - Move these policies to be data driven
_policy = Policy(
name='revision_change_policy',
subject=Policy.SUBJECT_ALL,
predicates=[
SimpleOrderPredicate(
lambda o: o.status < OrderStatus.ACCEPTED,
'A new revision can only be updated until the order is accepted.')
]
)
def __init__(self, on_behalf_of: str, change_data_provider: OrderRevisionChangeDataProvider):
super().__init__(on_behalf_of, OrderRevisionChangeRequest._policy)
self.change_data_provider = change_data_provider
def will_change(self, order: Order) -> bool:
if order.get('purchase_order_revision', None) is not None and self.change_data_provider.new_revision:
return order.get('purchase_order_revision') < self.change_data_provider.new_revision
return False
def apply(self, order: Order):
try:
self.changeable_object = order
if super().permitted(order):
if self.will_change(order):
from lib_b2b import profile as pf
profile = pf.Profile.profile_for(order.customer_edi_id)
if profile.integration_config.can_revise_orders:
old_revision = order.get('purchase_order_revision')
expressions = [
Attr('purchase_order_revision').exists(),
Attr('purchase_order_revision').lt(self.change_data_provider.new_revision)
]
conditions = And(*expressions)
from lib_b2b.order_builder import OrderBuilder
order_data = OrderBuilder.for_(self.change_data_provider.request).build()
order_data['history'] = order.get('history', [])
order_data['order_date'] = order.get('order_date', order_data.get('order_date'))
_order = Order.create(order_data,
conditions=conditions,
version=self.change_data_provider.version())
_order.record(ChangeRecord(before=old_revision, after=self.change_data_provider.new_revision,
description="Order revised", when=datetime.now().astimezone(UTC),
who=self.on_behalf_of)
)
else:
raise ChangeNotAllowed(f"Customer {order.customer_edi_id} has order "
f"revision capabilities disabled. Please check "
f"the 'can_revise_orders' setting on the customer account.")
except ValueError as ve:
raise VersionConflictError(str(ve))