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 ,
33- TRANSFER_RESELLER_ITEM_SKU ,
3433 Param ,
3534)
3635from adobe_vipm .flows .context import Context
37- from adobe_vipm .flows .errors import GovernmentLGANotValidOrderError , GovernmentNotValidOrderError
36+ from adobe_vipm .flows .errors import (
37+ GovernmentLGANotValidOrderError ,
38+ GovernmentNotValidOrderError ,
39+ MPTError ,
40+ )
3841from adobe_vipm .flows .helpers import (
3942 FetchResellerChangeData ,
43+ UpdatePrices ,
4044 ValidateGovernmentTransfer ,
4145 ValidateResellerChange ,
4246)
4650 exclude_items_with_deployment_id ,
4751 exclude_subscriptions_with_deployment_id ,
4852 get_adobe_membership_id ,
53+ get_market_segment ,
4954 get_order_line_by_sku ,
5055 get_ordering_parameter ,
5156 get_transfer_item_sku_by_subscription ,
5459 is_transferring_item_expired ,
5560 set_order_error ,
5661 set_ordering_parameter_error ,
62+ split_downsizes_upsizes_new ,
5763)
5864from 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
5967from adobe_vipm .utils import get_3yc_commitment , get_partial_sku
6068
6169logger = logging .getLogger (__name__ )
@@ -344,13 +352,16 @@ def __call__(self, mpt_client, context, next_step):
344352 context .order ["agreement" ] = get_agreement (mpt_client , context .order ["agreement" ]["id" ])
345353
346354 product_id = context .order ["agreement" ]["product" ]["id" ]
347- authorization_id = context .order ["authorization" ]["id" ]
355+ context .authorization_id = context .order ["authorization" ]["id" ]
356+ context .order_id = context .order ["id" ]
348357 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 )
349360
350361 if is_migrate_customer (context .order ):
351362 context .transfer = get_transfer_by_authorization_membership_or_customer (
352363 product_id ,
353- authorization_id ,
364+ context . authorization_id ,
354365 context .membership_id ,
355366 )
356367 next_step (mpt_client , context )
@@ -521,6 +532,8 @@ def validate_reseller_change(mpt_client, order):
521532 FetchResellerChangeData (is_validation = True ),
522533 ValidateResellerChange (is_validation = True ),
523534 AddResellerChangeLinesToOrder (),
535+ GetPreviewOrder (),
536+ UpdatePrices (),
524537 )
525538 context = Context (order = order )
526539 pipeline .run (mpt_client , context )
@@ -532,36 +545,105 @@ class AddResellerChangeLinesToOrder(Step):
532545
533546 def __call__ (self , mpt_client , context , next_step ):
534547 """Add lines from reseller change back to the MPT order."""
535- reseller_change_item = get_product_items_by_skus (
536- mpt_client , context .order ["agreement" ]["product" ]["id" ], [TRANSFER_RESELLER_ITEM_SKU ]
537- )
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
538581
539- if not reseller_change_item :
540- context .order = set_order_error (
541- 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
542587 )
543588 context .validation_succeeded = False
544589 return
545590
546- reseller_change_item = reseller_change_item [0 ]
547- 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 )
548595
549- lines = context .order ["lines" ]
550- if lines :
551- if len (lines ) == 1 and lines [0 ]["item" ]["id" ] == reseller_change_item ["id" ]:
552- next_step (mpt_client , context )
553- return
554- context .order = set_order_error (
555- context .order , ERR_ADOBE_RESSELLER_CHANGE_LINES .to_dict ()
556- )
557- context .validation_succeeded = False
558- new_line = [
559- {
560- "item" : reseller_change_item ,
561- "quantity" : 1 ,
562- "oldQuantity" : 0 ,
563- "price" : {"unitPP" : 0 },
564- }
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" , "" )
565599 ]
566- context .order ["lines" ] = new_line
567- 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