Skip to content

Commit

Permalink
feat: update line items state in single api call
Browse files Browse the repository at this point in the history
  • Loading branch information
syedsajjadkazmii committed Dec 20, 2024
1 parent 59ab5f8 commit dbbc3b7
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 10 deletions.
59 changes: 59 additions & 0 deletions commerce_coordinator/apps/commercetools/clients.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from commercetools.platform.models import CustomerSetCustomTypeAction as CTCustomerSetCustomTypeAction
from commercetools.platform.models import CustomerSetFirstNameAction, CustomerSetLastNameAction
from commercetools.platform.models import FieldContainer as CTFieldContainer
from commercetools.platform.models import LineItem as CTLineItem
from commercetools.platform.models import Money as CTMoney
from commercetools.platform.models import Order as CTOrder
from commercetools.platform.models import (
Expand Down Expand Up @@ -619,6 +620,64 @@ def update_line_item_transition_state_on_fulfillment(
handle_commercetools_error(err, f"Unable to update LineItemState of order {order_id}", True)
return None

def update_all_line_items_transition_state_on_fulfillment(
self,
order_id: str,
order_version: int,
line_items: List[CTLineItem],
from_state_id: str,
new_state_key: str,
) -> CTOrder:
"""
Update Commercetools order line item state for all items in one call.
Args:
order_id (str): Order ID (UUID)
order_version (int): Current version of order
line_items (List[object]): List of line item objects
from_state_id (str): ID of LineItemState to transition from
new_state_key (str): Key of LineItemState to transition to
Returns (CTOrder): Updated order object or
Returns (CTOrder): Current un-updated order
Raises Exception: Error if update was unsuccessful.
"""

from_state_key = self.get_state_by_id(from_state_id).key

logger.info(
f"[CommercetoolsAPIClient] - Transitioning all line item states for order with ID {order_id} "
f"from {from_state_key} to {new_state_key}"
)

try:
if new_state_key != from_state_key:
actions = [
OrderTransitionLineItemStateAction(
line_item_id=item.id,
quantity=item.quantity,
from_state=StateResourceIdentifier(key=from_state_key),
to_state=StateResourceIdentifier(key=new_state_key),
)
for item in line_items
]

updated_fulfillment_line_item_order = self.base_client.orders.update_by_id(
id=order_id,
version=order_version,
actions=actions,
)

return updated_fulfillment_line_item_order
else:
logger.info(
f"The line items already have the correct state {new_state_key}. "
"Not attempting to transition LineItemState"
)
return self.get_order_by_id(order_id)
except CommercetoolsError as err:
# Logs & ignores version conflict errors due to duplicate Commercetools messages
handle_commercetools_error(err, f"Unable to update LineItemState of order {order_id}", True)
return None

Check failure on line 679 in commerce_coordinator/apps/commercetools/clients.py

View workflow job for this annotation

GitHub Actions / tests (ubuntu-20.04, 3.12, django42)

Missing coverage

Missing coverage on lines 671-679

def retire_customer_anonymize_fields(
self,
customer_id: str,
Expand Down
23 changes: 13 additions & 10 deletions commerce_coordinator/apps/commercetools/sub_messages/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,19 +98,22 @@ def fulfill_order_placed_message_signal_task(
canvas_entry_properties = {"products": []}
canvas_entry_properties.update(extract_ct_order_information_for_braze_canvas(customer, order))

logger.info(
f"[CT-{tag}] Transitioning all line items for order {order.id} to {TwoUKeys.PROCESSING_FULFILMENT_STATE}"
)
updated_order = client.update_all_line_items_transition_state_on_fulfillment(
order_id=order.id,
order_version=order.version,
line_items=get_edx_items(order),
from_state_id=line_item_state_id,
new_state_key=TwoUKeys.PROCESSING_FULFILMENT_STATE
)
if not updated_order:
return True

Check failure on line 112 in commerce_coordinator/apps/commercetools/sub_messages/tasks.py

View workflow job for this annotation

GitHub Actions / tests (ubuntu-20.04, 3.12, django42)

Missing coverage

Missing coverage on line 112

for item in get_edx_items(order):
logger.debug(f'[CT-{tag}] processing edX order {order_id}, line item {item.variant.sku}, '
f'message id: {message_id}')
updated_order = client.update_line_item_transition_state_on_fulfillment(
order.id,
order.version,
item.id,
item.quantity,
line_item_state_id,
TwoUKeys.PROCESSING_FULFILMENT_STATE
)
if not updated_order:
return True

# from here we will always be transitioning from a 'Fulfillment Processing' state
line_item_state_id = client.get_state_by_key(TwoUKeys.PROCESSING_FULFILMENT_STATE).id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ def __init__(self, *args, **kwargs):
self.get_state_by_key = self.state_by_key_mock
self.get_payment_by_key = self.payment_mock
self.update_line_item_transition_state_on_fulfillment = self.updated_line_item_mock
self.update_all_line_items_transition_state_on_fulfillment = self.updated_line_item_mock
self.create_return_for_order = self.create_return_item_mock
self.create_return_payment_transaction = self.payment_mock
self.update_return_payment_state_after_successful_refund = self.order_mock
Expand Down
36 changes: 36 additions & 0 deletions commerce_coordinator/apps/commercetools/tests/test_clients.py
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,42 @@ def test_successful_order_line_item_state_update(self, mock_state_by_id):

self.assertEqual(result.line_items[0].state[0].state.id, mock_response_line_item_state.id)

@patch('commerce_coordinator.apps.commercetools.clients.CommercetoolsAPIClient.get_state_by_id')
def test_successful_order_all_line_items_state_update(self, mock_state_by_id):
base_url = self.client_set.get_base_url_from_client()

mock_order = gen_order("mock_order_id")
mock_order.version = "2"
mock_line_item_state = gen_line_item_state()
mock_line_item_state.key = TwoUKeys.PROCESSING_FULFILMENT_STATE
mock_order.line_items[0].state[0].state = mock_line_item_state

mock_state_by_id().return_value = mock_line_item_state

mock_response_order = gen_order("mock_order_id")
mock_response_order.version = 3
mock_response_line_item_state = gen_line_item_state()
mock_response_line_item_state.id = "mock_success_id"
mock_response_line_item_state.key = TwoUKeys.SUCCESS_FULFILMENT_STATE
mock_response_order.line_items[0].state[0].state = mock_response_line_item_state

with requests_mock.Mocker(real_http=True, case_sensitive=False) as mocker:
mocker.post(
f"{base_url}orders/{mock_response_order.id}",
json=mock_response_order.serialize(),
status_code=200
)

result = self.client_set.client.update_all_line_items_transition_state_on_fulfillment(
mock_order.id,
mock_order.version,
mock_order.line_items,
TwoUKeys.PENDING_FULFILMENT_STATE,
TwoUKeys.SUCCESS_FULFILMENT_STATE
)

self.assertEqual(result.line_items[0].state[0].state.id, mock_response_line_item_state.id)

@patch('commerce_coordinator.apps.commercetools.clients.CommercetoolsAPIClient.get_state_by_id')
def test_update_line_item_state_exception(self, mock_state_by_id):
base_url = self.client_set.get_base_url_from_client()
Expand Down

0 comments on commit dbbc3b7

Please sign in to comment.