11import datetime as dt
22import logging
3+ from typing import Any
34
4- from mpt_extension_sdk .mpt_http .mpt import get_agreement , get_product_items_by_skus
5+ from mpt_extension_sdk .mpt_http .mpt import get_agreement , get_product_items_by_skus , update_order
56
67from adobe_vipm .adobe .client import get_adobe_client
78from adobe_vipm .adobe .constants import (
2627 ERR_ADOBE_MEMBERSHIP_NOT_FOUND ,
2728 ERR_ADOBE_MEMBERSHIP_PROCESSING ,
2829 ERR_ADOBE_RESSELLER_CHANGE_LINES ,
29- ERR_ADOBE_RESSELLER_CHANGE_PRODUCT_NOT_CONFIGURED ,
3030 ERR_ADOBE_UNEXPECTED_ERROR ,
3131 ERR_NO_SUBSCRIPTIONS_WITHOUT_DEPLOYMENT ,
3232 ERR_UPDATING_TRANSFER_ITEMS ,
3333 Param ,
3434)
3535from adobe_vipm .flows .context import Context
36- from adobe_vipm .flows .errors import GovernmentLGANotValidOrderError , GovernmentNotValidOrderError
36+ from adobe_vipm .flows .errors import (
37+ GovernmentLGANotValidOrderError ,
38+ GovernmentNotValidOrderError ,
39+ MPTError ,
40+ )
3741from adobe_vipm .flows .helpers import (
3842 FetchResellerChangeData ,
43+ UpdatePrices ,
3944 ValidateGovernmentTransfer ,
4045 ValidateResellerChange ,
4146)
4550 exclude_items_with_deployment_id ,
4651 exclude_subscriptions_with_deployment_id ,
4752 get_adobe_membership_id ,
53+ get_market_segment ,
4854 get_order_line_by_sku ,
4955 get_ordering_parameter ,
5056 get_transfer_item_sku_by_subscription ,
5359 is_transferring_item_expired ,
5460 set_order_error ,
5561 set_ordering_parameter_error ,
62+ split_downsizes_upsizes_new ,
5663)
5764from adobe_vipm .flows .utils .validation import validate_government_lga_data
65+ from adobe_vipm .flows .validation .shared import GetPreviewOrder
66+ from adobe_vipm .notifications import send_error
5867from adobe_vipm .utils import get_3yc_commitment , get_partial_sku
5968
6069logger = logging .getLogger (__name__ )
@@ -343,13 +352,16 @@ def __call__(self, mpt_client, context, next_step):
343352 context .order ["agreement" ] = get_agreement (mpt_client , context .order ["agreement" ]["id" ])
344353
345354 product_id = context .order ["agreement" ]["product" ]["id" ]
346- authorization_id = context .order ["authorization" ]["id" ]
355+ context .authorization_id = context .order ["authorization" ]["id" ]
356+ context .order_id = context .order ["id" ]
347357 context .membership_id = get_adobe_membership_id (context .order )
358+ context .product_id = context .order ["agreement" ]["product" ]["id" ]
359+ context .market_segment = get_market_segment (context .product_id )
348360
349361 if is_migrate_customer (context .order ):
350362 context .transfer = get_transfer_by_authorization_membership_or_customer (
351363 product_id ,
352- authorization_id ,
364+ context . authorization_id ,
353365 context .membership_id ,
354366 )
355367 next_step (mpt_client , context )
@@ -520,6 +532,8 @@ def validate_reseller_change(mpt_client, order):
520532 FetchResellerChangeData (is_validation = True ),
521533 ValidateResellerChange (is_validation = True ),
522534 AddResellerChangeLinesToOrder (),
535+ GetPreviewOrder (),
536+ UpdatePrices (),
523537 )
524538 context = Context (order = order )
525539 pipeline .run (mpt_client , context )
@@ -531,36 +545,105 @@ class AddResellerChangeLinesToOrder(Step):
531545
532546 def __call__ (self , mpt_client , context , next_step ):
533547 """Add lines from reseller change back to the MPT order."""
534- reseller_change_item = get_product_items_by_skus (
535- mpt_client , context .order ["agreement" ]["product" ]["id" ], ["adobe-reseller-transfer" ]
536- )
548+ order_lines_from_transfer = self ._get_order_lines_from_transfer (context , mpt_client )
549+
550+ if order_lines_from_transfer :
551+ if not context .order ["lines" ]:
552+ logger .info ("No existing order lines, proceeding with transfer lines" )
553+ context .order = update_order (
554+ mpt_client , context .order_id , lines = order_lines_from_transfer
555+ )
556+ context .validation_succeeded = True
557+ elif not self ._transfer_order_lines_match (
558+ context .order ["lines" ], order_lines_from_transfer
559+ ):
560+ logger .warning ("Order lines do not match transfer lines" )
561+ context .order = set_order_error (
562+ context .order , ERR_ADOBE_RESSELLER_CHANGE_LINES .to_dict ()
563+ )
564+ context .validation_succeeded = False
565+ return
566+ else :
567+ logger .info (
568+ "Order lines match transfer lines successfully (%d lines)" ,
569+ len (order_lines_from_transfer ),
570+ )
571+ context .validation_succeeded = True
572+ elif context .order ["lines" ]:
573+ logger .info (
574+ "No transfer lines but order has %d existing lines, processing new lines" ,
575+ len (context .order ["lines" ]),
576+ )
577+ downsize_lines , upsize_lines , new_lines = split_downsizes_upsizes_new (context .order )
578+ context .downsize_lines = downsize_lines
579+ context .upsize_lines = upsize_lines
580+ context .new_lines = new_lines
537581
538- if not reseller_change_item :
539- context .order = set_order_error (
540- context .order , ERR_ADOBE_RESSELLER_CHANGE_PRODUCT_NOT_CONFIGURED .to_dict ()
582+ context .validation_succeeded = True
583+ else :
584+ logger .error ("No transfer lines and no order lines, validation failed" )
585+ context .order = update_order (
586+ mpt_client , context .order_id , lines = order_lines_from_transfer
541587 )
542588 context .validation_succeeded = False
543589 return
544590
545- reseller_change_item = reseller_change_item [0 ]
546- context .validation_succeeded = True
591+ logger .info (
592+ "Proceeding to next step with validation_succeeded=%s" , context .validation_succeeded
593+ )
594+ next_step (mpt_client , context )
547595
548- lines = context .order ["lines" ]
549- if lines :
550- if len (lines ) == 1 and lines [0 ]["item" ]["id" ] == reseller_change_item ["id" ]:
551- next_step (mpt_client , context )
552- return
553- context .order = set_order_error (
554- context .order , ERR_ADOBE_RESSELLER_CHANGE_LINES .to_dict ()
555- )
556- context .validation_succeeded = False
557- new_line = [
558- {
559- "item" : reseller_change_item ,
560- "quantity" : 1 ,
561- "oldQuantity" : 0 ,
562- "price" : {"unitPP" : 0 },
563- }
596+ def _get_order_lines_from_transfer (self , context : Context , mpt_client ) -> list [Any ]:
597+ no_deployment_transfer_items = [
598+ item for item in context .adobe_transfer ["lineItems" ] if not item .get ("deploymentId" , "" )
564599 ]
565- context .order ["lines" ] = new_line
566- next_step (mpt_client , context )
600+ if not no_deployment_transfer_items :
601+ logger .info ("No transfer items without deployment ID" )
602+ return []
603+ logger .info (
604+ "Processing %d transfer items without deployment ID" , len (no_deployment_transfer_items )
605+ )
606+ reseller_items_map = {
607+ item ["externalIds" ]["vendor" ]: item
608+ for item in get_product_items_by_skus (
609+ mpt_client ,
610+ context .order ["agreement" ]["product" ]["id" ],
611+ [get_partial_sku (item ["offerId" ]) for item in no_deployment_transfer_items ],
612+ )
613+ }
614+ logger .debug (
615+ "Created reseller items map with %d items: %s" ,
616+ len (reseller_items_map ),
617+ list (reseller_items_map .keys ()),
618+ )
619+ order_lines_from_transfer = []
620+ for item in no_deployment_transfer_items : # TODO:filter out expired?
621+ partial_sku = get_partial_sku (item ["offerId" ])
622+ mapped_item = reseller_items_map .get (partial_sku )
623+ if mapped_item is None :
624+ error_msg = f"No reseller item found for partial SKU '{ partial_sku } '"
625+ logger .error (error_msg )
626+ send_error ("Transfer Validation - Missing reseller item" , error_msg )
627+ raise MPTError (error_msg )
628+ order_lines_from_transfer .append ({
629+ "item" : mapped_item ,
630+ "oldQuantity" : item ["quantity" ],
631+ "quantity" : item ["quantity" ],
632+ })
633+
634+ logger .info ("Created %d order lines from transfer items" , len (order_lines_from_transfer ))
635+ return order_lines_from_transfer
636+
637+ @staticmethod
638+ def _transfer_order_lines_match (order_lines : list [dict ], transfer_lines : list [dict ]) -> bool :
639+ """Compare order lines based on relevant fields only."""
640+ if len (order_lines ) != len (transfer_lines ):
641+ return False
642+
643+ order_lines_to_comp = {
644+ (line ["item" ]["externalIds" ]["vendor" ], line ["quantity" ]) for line in order_lines
645+ }
646+ transfer_lines_to_comp = {
647+ (line ["item" ]["externalIds" ]["vendor" ], line ["quantity" ]) for line in transfer_lines
648+ }
649+ return order_lines_to_comp == transfer_lines_to_comp
0 commit comments