Advertisement
Guest User

DlaKK

a guest
Apr 5th, 2017
947
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 180.61 KB | None | 0 0
  1. /************************************************************************
  2. Description : CPQ_PRD04_SoldServiceMappingHlpr class
  3. Created by : Bartosz Walczak (bartosz.walczak@enxoo.com)
  4. Date created : 2016-03-23
  5.  
  6. Revision :
  7.  2016-03-23     Bartosz Walczak (bartosz.walczak@enxoo.com)     Class created
  8.  2017-02-06     Maciej Simm (maciej.simm@enxoo.com)             Adding logic for custom Colocation Reference handling (locations)
  9.  2017-03-07     Mateusz Osiak (mateusz.osiak@enxoo.com)         Adding logic for automation of delivery comm templates.
  10.  2017-03-20     Tomasz Bogdanski (tomasz.bogdanski@enxoo.com)   SUN-1191 Adding batch support for createSoldServices method for huge opportunities.
  11.  2017-03-22     Maciej Simm (maciej.simm@enxoo.com)             SUN-726 Professional Solutions - removing Colo Ref logic & adding A/B End Handling
  12.  
  13. ************************************************************************/
  14.  
  15. public without sharing class CPQ_PRD04_SoldServiceMappingHlpr {
  16.  
  17.     public static final String RT_QUITEM_PRODUCT = 'Product';
  18.     public static final String RT_QUITEM_COMPONENT = 'Component';
  19.  
  20.     public static final String RT_SSERVICE_COMMERCIAL = 'TC CommercialProduct v1';
  21.     public static final String RT_SSERVICE_OPERATIONAL_DI = 'TC OperationalProduct D&I v1';
  22.     public static final String RT_SSERVICE_OPERATIONAL_VM = 'TC OperationalProduct V&M v1';
  23.     public static final String RT_SSERVICE_INTERNAL = 'TC InternalProduct v1';
  24.  
  25.     public static final String PROD_TYPE_COMMERCIAL = 'CommercialProduct';
  26.     public static final String PROD_TYPE_OPERATIONAL = 'OperationalProduct';
  27.     public static final String PROD_TYPE_INTERNAL = 'InternalProduct';
  28.    
  29.     public static final String ACTION_ADD = 'Add';
  30.     public static final String ACTION_CHANGE = 'Change';
  31.     public static final String ACTION_DISMANTLE = 'Dismantle';
  32.     public static final String ACTION_RENEWAL = 'Renewal';
  33.     public static final String ACTION_CEASE = 'Cease & Reprovide';
  34.     public static final String ACTION_NO_ACTION = 'No Action';
  35.    
  36.     public static final String STAGE_NEW = '10. Review & Plan';
  37.     public static final String STAGE_RENEWAL = '29. Renewal in Waiting';
  38.     public static final String STAGE_DISMANTLE = '95. Pending Dismantle';
  39.     public static final String STAGE_REPLACEMENT = '80. Pending Replacement';
  40.    
  41.     public static final String TPS_STATUS_REPLACED = '29 Renewal in Waiting';
  42.     public static final String TPS_STATUS_DISMANTLE = '90 Pending Dismantle';
  43.     public static final String TPI_STATUS_QUOTE_REQ = '2. Quote Required';
  44.    
  45.     public static final String TPS_PRIMARY_PROD_SITE = 'Site & Facility';
  46.  
  47.     public static final String ATTRIBUTE_PORTS_GRID = 'ATR_IPPORTS_';
  48.     public static final String ATTRIBUTE_DATE_OF_CHANGE = 'ATR_DATEOFCHANGE_';
  49.     public static final String ATTRIBUTE_BILLING_COMM = 'ATR_BILLINGCOMENCEMENTDATE_';
  50.     public static final String ATTRIBUTE_CONTRACT_LENGTH = 'ATR_LENGTHOFCONTRACTMONTHS_';
  51.     public static final String ATTRIBUTE_DUALLINK_PREFIX = 'ATR_DUALLINK';
  52.    
  53.     public static final String PORT_PREFIX = 'requested';
  54.    
  55.     public static final String DISMANTLE_TXT = 'Dismantle as part of renewal';
  56.     public static final String CEASEANDREPROVIDE_TXT = 'From Cease & Reprovide';
  57.  
  58.     public static final String CEASE_HOT_CUT = 'Hot Cut';
  59.     public static final String CEASE_PARALLEL_BUILD = 'Parallel Build';
  60.  
  61.     public static final String TPI_ORDER_TYPE_DISMANTLE = 'Dismantle';
  62.  
  63.     public static final Integer QUANTITY_SUM_TRESHOLD = Integer.valueOf(System.Label.CPQ_Opportunity_Quote_Quantity_Batch_Treshold);
  64.     public static final Integer BATCH_SIZE = Integer.valueOf(System.Label.CPQ_Opportunity_Close_Batch_Size);
  65.     public static       Set<Id> batchOpportunities = new Set<Id>();
  66.  
  67.     public static final String createQuoteItemsQuery = 'select ' + CPQ_Utils01_SObjectHelperCls.getFieldListForSOQL('CPQ_QuoteItem__c', null, null) + ', RecordType.Name, Product_Definition__r.Product_Group__c, Product_Definition__r.Product_Type__c, Opportunity__r.CloseDate, Opportunity__r.Commercial_Contact__c, Opportunity__r.Commercial_Contact__r.Name, ' +
  68.                     'Product_Definition__r.Name, Component_Definition__r.Name, Existing_Object_ID__r.Name, Existing_Object_ID__r.RecordTypeId, Existing_Object_ID__r.Item_Type__c, Existing_Object_ID__r.Renewed_To__c, Existing_Object_ID__r.Renewed_To__r.Status__c, ' +
  69.                     'A_Port__r.Port_Type__c, A_Port__r.Homing_Gateway__c, A_Port__r.Homing_Gateway__r.Continent__c, B_Port__r.Port_Type__c, B_Port__r.Homing_Gateway__c, B_Port__r.Homing_Gateway__r.Continent__c, A_Site__r.Name, B_Site__r.Name, ' +
  70.                     '(select ' + CPQ_Utils01_SObjectHelperCls.getFieldListForSOQL('CPQ_QuoteItemAttribute__c', null, null) + ', Value_Attribute__r.Name, Value_Attribute__r.TECH_Value_ID__c from QuoteItemAttributes__r), ' +
  71.                     '(select ' + CPQ_Utils01_SObjectHelperCls.getFieldListForSOQL('Port_Change_Request__c', null, null) + ' from Port_Change_Requests__r), ' +
  72.                     '(select ' + CPQ_Utils01_SObjectHelperCls.getFieldListForSOQL('X3rd_Party_Item__c', null, null) + ', Parent__r.Upsert_Key__c from X3rd_Party_Items__r) ' +
  73.                     'from CPQ_QuoteItem__c where Opportunity__c = :opportunityId and Primary__c = true order by Order__c';
  74.    
  75.     private static Map<String,Id> contactIdByRole = new Map<String,Id>();
  76.  
  77.     public static void createSoldServices(Id opportunityId) {
  78.  
  79.         System.debug('@@ START CLASS: CPQ_PRD04_SoldServiceMappingHlpr METHOD: createSoldServices');
  80.         /* loading selected Quote Items with Attributes to create Sold Services */
  81.        
  82.         List<CPQ_QuoteItem__c> quoteItemsList = Database.query(createQuoteItemsQuery);
  83.         Decimal itemsQuantitySum = 0;
  84.         for(CPQ_QuoteItem__c qi : quoteItemsList) {
  85.             if(qi.Quantity__c != null) {
  86.                 itemsQuantitySum+=qi.Quantity__c;
  87.             }
  88.         }
  89.  
  90.         if(itemsQuantitySum < 100) {
  91.             createSoldServices(quoteItemsList, opportunityId, new Map<String,Id>());  
  92.         } else {              
  93.             List<CPQ_OpportunityQuoteItem__c> quantityHelperList = new List<CPQ_OpportunityQuoteItem__c>();
  94.            
  95.             for(CPQ_QuoteItem__c qi : quoteItemsList) {
  96.                 if(qi.Quantity__c != null) {
  97.                     for(Integer i=1; i<=qi.Quantity__c; i++) {
  98.                         CPQ_OpportunityQuoteItem__c newQuantityHelper = new CPQ_OpportunityQuoteItem__c(Opportunity__c = opportunityId, Quote_Item__c = qi.Id);
  99.                         quantityHelperList.add(newQuantityHelper);
  100.                     }
  101.                 }        
  102.             }
  103.  
  104.             insert quantityHelperList;
  105.  
  106.             CPQ_PRD08_CreateSoldServiceBatchHlpr batch = new CPQ_PRD08_CreateSoldServiceBatchHlpr(opportunityId);
  107.             Database.executeBatch(batch, BATCH_SIZE);
  108.             batchOpportunities.add(opportunityId);
  109.  
  110.  
  111.         }
  112.     }
  113.  
  114.     public static createSoldServicesResult createSoldServices(List<CPQ_QuoteItem__c> quoteItemsList, Id opportunityId, Map<String, Id> quoteItemToSoldService) {
  115.  
  116.         createSoldServicesResult result = new createSoldServicesResult();
  117.         Map<Id, OpportunityLineItem> oppLineItems = new Map<Id, OpportunityLineItem>([select Id, Product2.Name from OpportunityLineItem where OpportunityId = :opportunityId]);
  118.        
  119.         List<CPQ_QuoteItem__c> products = new List<CPQ_QuoteItem__c>();
  120.         Map<Id, List<CPQ_QuoteItem__c>> components = new Map<Id, List<CPQ_QuoteItem__c>>();
  121.         Set<Id> productIds = new Set<Id>();
  122.         Set<Id> soldServiceIds = new Set<Id>();
  123.         Set<Id> portsToCloneIds = new Set<Id>();
  124.        
  125.         for(CPQ_QuoteItem__c qItem : quoteItemsList) {
  126.             if(qItem.RecordType.Name == RT_QUITEM_PRODUCT) {
  127.                 products.add(qItem);
  128.                 productIds.add(qItem.Product_Definition__c);
  129.             } else if(qItem.RecordType.Name == RT_QUITEM_COMPONENT) {
  130.                 List<CPQ_QuoteItem__c> componentsList = components.get(qItem.Parent_Item__c);
  131.                 if(componentsList == null) {
  132.                     componentsList = new List<CPQ_QuoteItem__c>();
  133.                     components.put(qItem.Parent_Item__c, componentsList);
  134.                 }
  135.                 componentsList.add(qItem);
  136.             }
  137.            
  138.             if(qItem.Existing_Object_ID__c != null) {
  139.                 soldServiceIds.add(qItem.Existing_Object_ID__c);
  140.             }
  141.            
  142.             if(qItem.Quantity__c != null && qItem.Quantity__c > 1) {
  143.                 if(qItem.A_Port__c != null && qItem.A_Port_Option__c == 'New Port') {
  144.                     portsToCloneIds.add(qItem.A_Port__c);
  145.                 }
  146.                 if(qItem.B_Port__c != null && qItem.B_Port_Option__c == 'New Port') {
  147.                     portsToCloneIds.add(qItem.B_Port__c);
  148.                 }
  149.             }
  150.         }
  151.        
  152.         Map<Id, Port__c> portsToClone = new Map<Id, Port__c>();
  153.         if(!portsToCloneIds.isEmpty()) {
  154.             String portsToCloneQuery = 'select ' + CPQ_Utils01_SObjectHelperCls.getFieldListForSOQL('Port__c', null, null) + ' from Port__c where Id in :portsToCloneIds';
  155.             portsToClone = new Map<Id, Port__c>((List<Port__c>)Database.query(portsToCloneQuery));
  156.         }
  157.        
  158.         /* loading mapping configuration */
  159.         Map<Id, Map<Id, List<CPQ_Sold_Service_Mapping__c>>> soldServiceMappings_Attributes = new Map<Id, Map<Id, List<CPQ_Sold_Service_Mapping__c>>>();
  160.         Map<Id, Map<Id, List<CPQ_Sold_Service_Mapping__c>>> soldServiceMappings_Fields = new Map<Id, Map<Id, List<CPQ_Sold_Service_Mapping__c>>>();
  161.         Map<Id, Map<Id, List<CPQ_Sold_Service_Mapping__c>>> soldServiceMappings_Constants = new Map<Id, Map<Id, List<CPQ_Sold_Service_Mapping__c>>>();
  162.         Map<Id, Map<Id, List<CPQ_Sold_Service_Mapping__c>>> soldServiceMappings_Numbers = new Map<Id, Map<Id, List<CPQ_Sold_Service_Mapping__c>>>();
  163.  
  164.         Map<String, String> typeOfServiceToproductCode = new Map<String, String>();
  165.         /* loading product codes from Custom Setting */
  166.         for(CPQ_Mapping__c m : CPQ_Mapping__c.getall().values()) {
  167.             if(m.Setting__c == CPQ_Utils.CPQ_MAPPING_PRODUCT_CODE) {
  168.                 typeOfServiceToproductCode.put(m.Col1__c, m.Col2__c);
  169.             }
  170.         }
  171.                
  172.         for(CPQ_Sold_Service_Mapping__c mapping : [select Id, Attribute__c, Attribute__r.TECH_Definition_ID__c, Attribute__r.Grid_Layout__c, Attribute__r.Type__c, Component__c, Data_Type__c, Generate_ICB_Number__c, Generate_ICC_Number__c, Generate_IC_Number__c, Product__c, Update_on_Change__c,
  173.                         Source_Constant_Value__c, Source_Field_Name__c, Target_Field_OLI__c, Target_Field_Sold_Service__c from CPQ_Sold_Service_Mapping__c where Product__c in :productIds]){
  174.            
  175.             Map<Id, List<CPQ_Sold_Service_Mapping__c>> componentMappings = new Map<Id, List<CPQ_Sold_Service_Mapping__c>>();
  176.            
  177.             if(mapping.Data_Type__c == CPQ_PRD03_SoldServiceMappingDesignCtrl.TYPE_ATTRIBUTE_MAPPING) {
  178.                 componentMappings = soldServiceMappings_Attributes.get(mapping.Product__c);
  179.                 if(componentMappings == null){
  180.                     componentMappings = new Map<Id, List<CPQ_Sold_Service_Mapping__c>>();
  181.                     soldServiceMappings_Attributes.put(mapping.Product__c, componentMappings);
  182.                 }
  183.             } else if(mapping.Data_Type__c == CPQ_PRD03_SoldServiceMappingDesignCtrl.TYPE_FIELD_MAPPING) {
  184.                 componentMappings = soldServiceMappings_Fields.get(mapping.Product__c);
  185.                 if(componentMappings == null){
  186.                     componentMappings = new Map<Id, List<CPQ_Sold_Service_Mapping__c>>();
  187.                     soldServiceMappings_Fields.put(mapping.Product__c, componentMappings);
  188.                 }
  189.             } else if(mapping.Data_Type__c == CPQ_PRD03_SoldServiceMappingDesignCtrl.TYPE_CONSTANT_MAPPING) {
  190.                 componentMappings = soldServiceMappings_Constants.get(mapping.Product__c);
  191.                 if(componentMappings == null){
  192.                     componentMappings = new Map<Id, List<CPQ_Sold_Service_Mapping__c>>();
  193.                     soldServiceMappings_Constants.put(mapping.Product__c, componentMappings);
  194.                 }
  195.             } else if(mapping.Data_Type__c == CPQ_PRD03_SoldServiceMappingDesignCtrl.TYPE_NUMBER_MAPPING) {
  196.                 componentMappings = soldServiceMappings_Numbers.get(mapping.Product__c);
  197.                 if(componentMappings == null){
  198.                     componentMappings = new Map<Id, List<CPQ_Sold_Service_Mapping__c>>();
  199.                     soldServiceMappings_Numbers.put(mapping.Product__c, componentMappings);
  200.                 }
  201.             }
  202.            
  203.             List<CPQ_Sold_Service_Mapping__c> mappings = componentMappings.get(mapping.Component__c);
  204.             if(mappings == null) {
  205.                 mappings = new List<CPQ_Sold_Service_Mapping__c>();
  206.                 componentMappings.put(mapping.Component__c, mappings);
  207.             }
  208.            
  209.             mappings.add(mapping);
  210.         }
  211.        
  212.         /* initializing codes generator */
  213.         DynamicValuesWrapper codes = new DynamicValuesWrapper(ApplicationConstant.IC_PREFIX);
  214.         Map<String, Schema.SObjectType> globalDescribe = Schema.getGlobalDescribe();
  215.        
  216.         /* initializing fields for TPI -> TPS mapping */
  217.         Map<String,String> tpsFieldMap = SoldServiceUtility.buildFieldMapping(ApplicationConstant.FIELD_MAPPING_THIRDPARTY);
  218.         Id tpiReadOnlyRecordType = RecordTypeUtility.getRecordTypeId(X3rd_Party_Item__c.SObjectType, ApplicationConstant.RT_X3RDPARTYITEM_DEFAULT_READONLY_V1, 'X3rd_Party_Item__c');
  219.        
  220.         /* processing Quote Items */
  221.         List<Sold_Service__c> soldServiceProductsToUpsert = new List<Sold_Service__c>();
  222.         List<Sold_Service__c> soldServiceComponentsToUpsert = new List<Sold_Service__c>();
  223.         List<X3rd_Party_Services__c> thirdPartyServicesToUpsert = new List<X3rd_Party_Services__c>();
  224.         Map<Id, X3rd_Party_Services__c> thirdPartyServicesToUpsert2 = new Map<Id, X3rd_Party_Services__c>();
  225.         List<X3rd_Party_Services__c> thirdPartyServicesToUpsertParent = new List<X3rd_Party_Services__c>();
  226.         List<X3rd_Party_Item__c> thirdPartyItemsToUpdate = new List<X3rd_Party_Item__c>();
  227.         List<CPQ_Charge__c> chargesToUpsert = new List<CPQ_Charge__c>();
  228.         List<CPQ_Charge__c> chargesToDelete = new List<CPQ_Charge__c>();
  229.         List<Port__c> portsToCreate = new List<Port__c>();
  230.         Map<Id, Port_Change_Request__c> portCRsToUpsert = new Map<Id, Port_Change_Request__c>();
  231.         Set<Id> tpisAlreadyAdded = new Set<Id>();
  232.         Set<Id> portIds = new Set<Id>();
  233.         Set<String> portExternalIds = new Set<String>();
  234.        
  235.         /* map of Quote Item ID to Upsert Key of created Sold Service */
  236.         Map<Id, String> quoteItemId2SoldServiceExternalId = new Map<Id, String>();
  237.         /* map of Sold Service Upsert Key to Quote Item ID corresponding to related Dual Link service */
  238.         Map<String, Id> soldServiceDualLinkReference = new Map<String, Id>();
  239.         /* map of Sold Service Upsert Key to Sold Service field where dual link relation should be stored */
  240.         Map<String, String> soldServiceDualLinkField = new Map<String, String>();
  241.         /* map of Sold Service Upsert Key to Quote Item ID corresponding to related A End and B End service */
  242.         Map<String, String> soldServiceAEndReference = new Map<String, String>();
  243.         Map<String, String> soldServiceBEndReference = new Map<String, String>();
  244.  
  245.         for(CPQ_QuoteItem__c product : products) {
  246.  
  247.             for(Integer i = 1; i <= product.Quantity__c; i++) {
  248.                 Sold_Service__c newSoldService;
  249.                 Boolean existingProductRecordUpdate = false;
  250.                
  251.                 if(soldServiceMappings_Numbers.get(product.Product_Definition__c) == null || soldServiceMappings_Numbers.get(product.Product_Definition__c).get(null) == null ||
  252.                     (soldServiceMappings_Numbers.get(product.Product_Definition__c).get(null)[0].Generate_ICC_Number__c == false &&
  253.                     soldServiceMappings_Numbers.get(product.Product_Definition__c).get(null)[0].Generate_IC_Number__c == false &&
  254.                     soldServiceMappings_Numbers.get(product.Product_Definition__c).get(null)[0].Generate_ICB_Number__c == false)) {
  255.                     continue;
  256.                 } else if(soldServiceMappings_Numbers.get(product.Product_Definition__c) != null && soldServiceMappings_Numbers.get(product.Product_Definition__c).get(null) != null &&
  257.                     soldServiceMappings_Numbers.get(product.Product_Definition__c).get(null)[0].Update_on_Change__c && product.Existing_Object_ID__c != null) {
  258.                     newSoldService = new Sold_Service__c(Id = product.Existing_Object_ID__c);
  259.                     existingProductRecordUpdate = true;
  260.                 } else if(product.Item_Action__c == ACTION_NO_ACTION) {
  261.                     if(product.Existing_Object_ID__c != null && product.Existing_Object_ID__r.Renewed_To__c != null && product.Existing_Object_ID__r.Renewed_To__r.Status__c != null && product.Existing_Object_ID__r.Renewed_To__r.Status__c == 'Active') {
  262.                         newSoldService = new Sold_Service__c(Id = product.Existing_Object_ID__r.Renewed_To__c);
  263.                         existingProductRecordUpdate = true;
  264.                     } else {
  265.                         newSoldService = new Sold_Service__c(Id = product.Existing_Object_ID__c);
  266.                         existingProductRecordUpdate = true;
  267.                     }
  268.                 } else {
  269.                     newSoldService = new Sold_Service__c();
  270.                 }
  271.                 //newSoldService.RecordType = new RecordType(Name = RT_SSERVICE_PRODUCT);
  272.                 newSoldService.Item_Action__c = product.Item_Action__c;
  273.                
  274.                 if(product.Item_Action__c != ACTION_NO_ACTION) {
  275.                     newSoldService.Service_Description__c = product.Description__c;
  276.                     newSoldService.Configuration_Description__c = product.Configuration_Description__c;
  277.                     if(!existingProductRecordUpdate) {
  278.                         newSoldService.Stage__c = STAGE_NEW;
  279.                     }
  280.                 }
  281.                
  282.                 /* keeping sold service number for modifications */
  283.                 if(product.Item_Action__c == ACTION_ADD) {
  284.                     CPQ_Sold_Service_Mapping__c whatCode;
  285.                     if(soldServiceMappings_Numbers.get(product.Product_Definition__c) != null && soldServiceMappings_Numbers.get(product.Product_Definition__c).get(null) != null) {
  286.                         whatCode = soldServiceMappings_Numbers.get(product.Product_Definition__c).get(null)[0];
  287.                     }
  288.                    
  289.                     if(whatCode != null && whatCode.Generate_ICC_Number__c){
  290.                         newSoldService.Name = codes.generateCode(system.label.CRM_COM_PRODUCT);
  291.                     } else if(whatCode != null && whatCode.Generate_IC_Number__c) {
  292.                         newSoldService.Name = codes.generateCode(system.label.CRM_OPR_PRODUCT);
  293.                     } else if(whatCode != null && whatCode.Generate_ICB_Number__c) {
  294.                         newSoldService.Name = codes.generateCode(system.label.CRM_INTERNAL_PRODUCT);
  295.                     }
  296.                    
  297.                     /* assigning appropriate record type */
  298.                     if(product.Product_Definition__c != null && product.Product_Definition__r.Product_Type__c == PROD_TYPE_COMMERCIAL) {
  299.                         newSoldService.RecordType = new RecordType(Name = RT_SSERVICE_COMMERCIAL);
  300.                         newSoldService.Item_Type__c = system.label.CRM_COM_PRODUCT;
  301.                     } else if(product.Product_Definition__c != null && product.Product_Definition__r.Product_Type__c == PROD_TYPE_OPERATIONAL) {
  302.                         if(product.Product_Definition__r.Product_Group__c == 'Voice' || product.Product_Definition__r.Product_Group__c == 'Roaming & Messaging') {
  303.                             newSoldService.RecordType = new RecordType(Name = RT_SSERVICE_OPERATIONAL_VM);
  304.                         } else {
  305.                             newSoldService.RecordType = new RecordType(Name = RT_SSERVICE_OPERATIONAL_DI);
  306.                         }
  307.                         newSoldService.Item_Type__c = system.label.CRM_OPR_PRODUCT;
  308.                     } else if(product.Product_Definition__c != null && product.Product_Definition__r.Product_Type__c == PROD_TYPE_INTERNAL) {
  309.                         newSoldService.RecordType = new RecordType(Name = RT_SSERVICE_INTERNAL);
  310.                         newSoldService.Item_Type__c = system.label.CRM_INTERNAL_PRODUCT;
  311.                     }
  312.                 } else if(product.Item_Action__c == ACTION_CHANGE) {
  313.                     newSoldService.Name = product.Existing_Object_ID__r.Name;
  314.                    
  315.                     if(!existingProductRecordUpdate) {
  316.                         newSoldService.Renewed_From__c = product.Existing_Object_ID__c;
  317.                         newSoldService.RecordTypeId = product.Existing_Object_ID__r.RecordTypeId;
  318.                         newSoldService.Item_Type__c = product.Existing_Object_ID__r.Item_Type__c;
  319.                        
  320.                         Sold_Service__c changedService = new Sold_Service__c(Id = product.Existing_Object_ID__c);
  321.                         changedService.Stage__c = STAGE_REPLACEMENT;
  322.                         soldServiceProductsToUpsert.add(changedService);
  323.                     }
  324.                 } else if(product.Item_Action__c == ACTION_RENEWAL) {
  325.                     newSoldService.Name = product.Existing_Object_ID__r.Name;
  326.                     newSoldService.Estimated_Delivery_Date__c = null;
  327.                    
  328.                     if(!existingProductRecordUpdate) {
  329.                         newSoldService.Renewed_From__c = product.Existing_Object_ID__c;
  330.                         newSoldService.RecordTypeId = product.Existing_Object_ID__r.RecordTypeId;
  331.                         newSoldService.Item_Type__c = product.Existing_Object_ID__r.Item_Type__c;
  332.                        
  333.                         Sold_Service__c changedService = new Sold_Service__c(Id = product.Existing_Object_ID__c);
  334.                         changedService.Stage__c = STAGE_REPLACEMENT;
  335.                         soldServiceProductsToUpsert.add(changedService);
  336.                     }
  337.                 } else if(product.Item_Action__c == ACTION_CEASE) {
  338.                     newSoldService.Name = product.Existing_Object_ID__r.Name;
  339.                    
  340.                     if(!existingProductRecordUpdate) {
  341.                         newSoldService.Stage__c = STAGE_NEW;
  342.                         newSoldService.Renewed_From__c = product.Existing_Object_ID__c;
  343.                         newSoldService.RecordTypeId = product.Existing_Object_ID__r.RecordTypeId;
  344.                         newSoldService.Item_Type__c = product.Existing_Object_ID__r.Item_Type__c;
  345.                        
  346.                         Sold_Service__c changedService = new Sold_Service__c(Id = product.Existing_Object_ID__c);
  347.                         changedService.Stage__c = STAGE_REPLACEMENT;
  348.                         if(product.Cease_and_Reprovide_Type__c != null && product.Cease_and_Reprovide_Type__c == CEASE_PARALLEL_BUILD) {
  349.                             if(product.Opportunity__c != null) {
  350.                                 changedService.Specification_Received_Date__c = product.Opportunity__r.CloseDate;
  351.                                 if(product.Opportunity__r.Commercial_Contact__c != null) {
  352.                                     changedService.Person_requesting_the_dismantle__c = product.Opportunity__r.Commercial_Contact__r.Name;
  353.                                 }
  354.                             }
  355.                             changedService.Dismantle_Notes__c = CEASEANDREPROVIDE_TXT;
  356.                         }
  357.                         soldServiceProductsToUpsert.add(changedService);
  358.                     }
  359.                 } else if(product.Item_Action__c == ACTION_DISMANTLE) {
  360.                     Sold_Service__c dismantledService = new Sold_Service__c(Id = product.Existing_Object_ID__c);
  361.                     dismantledService.Previous_MRC__c = product.MRC_Previous__c;
  362.                     dismantledService.MRC__c = 0;
  363.                     dismantledService.Stage__c = STAGE_DISMANTLE;
  364.                     dismantledService.Date_for_Dismantle__c = product.Date_Expected_Delivery__c;
  365.                     dismantledService.Dismantle_Notes__c = DISMANTLE_TXT;
  366.                     if(product.Opportunity__c != null) {
  367.                         dismantledService.Specification_Received_Date__c = product.Opportunity__r.CloseDate;
  368.                         if(product.Opportunity__r.Commercial_Contact__c != null) {
  369.                             dismantledService.Person_requesting_the_dismantle__c = product.Opportunity__r.Commercial_Contact__r.Name;
  370.                         }
  371.                     }
  372.                     dismantledService.Dismantle_Related_Services__c = 'No';
  373.                     soldServiceProductsToUpsert.add(dismantledService);
  374.                    
  375.                     if(product.X3rd_Party_Items__r != null) {
  376.                         for(X3rd_Party_Item__c tpi : product.X3rd_Party_Items__r) {
  377.                             if(tpi.Existing_X3rd_Party_Service__c != null) {
  378.                                 X3rd_Party_Services__c oldTPS = new X3rd_Party_Services__c(Id = tpi.Existing_X3rd_Party_Service__c);
  379.                                 oldTPS.Status__c = '90 Pending Dismantle';
  380.                                 thirdPartyServicesToUpsert2.put(oldTPS.id, oldTPS);
  381.                             }
  382.                         }
  383.                     }
  384.                 }
  385.                
  386.                 if(product.Item_Action__c != ACTION_DISMANTLE && product.Item_Action__c != ACTION_NO_ACTION) {
  387.                     /* generate a new IC/ICC number if the option was selected */
  388.                     if(product.Assign_New_IC_ICC_Number__c && !existingProductRecordUpdate) {
  389.                         CPQ_Sold_Service_Mapping__c whatCode;
  390.                         if(soldServiceMappings_Numbers.get(product.Product_Definition__c) != null && soldServiceMappings_Numbers.get(product.Product_Definition__c).get(null) != null) {
  391.                             whatCode = soldServiceMappings_Numbers.get(product.Product_Definition__c).get(null)[0];
  392.                         }
  393.                        
  394.                         if(whatCode != null && whatCode.Generate_ICC_Number__c){
  395.                             newSoldService.Name = codes.generateCode(system.label.CRM_COM_PRODUCT);
  396.                         } else if(whatCode != null && whatCode.Generate_IC_Number__c) {
  397.                             newSoldService.Name = codes.generateCode(system.label.CRM_OPR_PRODUCT);
  398.                         } else if(whatCode != null && whatCode.Generate_ICB_Number__c) {
  399.                             newSoldService.Name = codes.generateCode(system.label.CRM_INTERNAL_PRODUCT);
  400.                         }  
  401.                     }
  402.                    
  403.                     if(product.Item_Action__c == ACTION_RENEWAL && !existingProductRecordUpdate) {
  404.                         newSoldService.Stage__c = STAGE_RENEWAL;
  405.                     }
  406.  
  407.                     newSoldService.CurrencyIsoCode = product.CurrencyIsoCode;
  408.                      
  409.                     newSoldService.Opp_Link__c = product.Opportunity__c;
  410.                     newSoldService.CRM_Account__c = product.Account__c;
  411.                     newSoldService.Instance_ID__c = newSoldService.Name;
  412.                     newSoldService.CPQ_Product__c = product.Product_Definition__c;
  413.                     newSoldService.Item_Name__c = product.Product_Definition__r.Name;
  414.                     if(product.Product_Definition__c != null && product.Product_Definition__r.Name == 'Colocation' && product.A_Site__c != null){
  415.                         newSoldService.Site_ID__c = product.A_Site__r.Name;
  416.                     }
  417.                     newSoldService.OLI_Link_ID__c = product.OpportunityLineItem_ID__c;
  418.                     newSoldService.OLI_Link_Name__c = oppLineItems.get(product.OpportunityLineItem_ID__c) == null ? product.Name : oppLineItems.get(product.OpportunityLineItem_ID__c).Product2.Name;
  419.                     newSoldService.Item_Action_Description__c = product.Item_Action_Description__c;
  420.                     newSoldService.Days_of_Parallel_Running__c = product.Parallel_build_period__c;
  421.  
  422.                     newSoldService.List_OTC__c = product.OTC_List__c;
  423.                     newSoldService.OTC__c = product.OTC__c;
  424.                     newSoldService.OTC_Rolled__c = product.OTC_Rolled__c == null ? 0 : product.OTC_Rolled__c;
  425.                     newSoldService.List_MRC__c = product.MRC_List__c;
  426.                     newSoldService.MRC__c = product.MRC__c;
  427.                     newSoldService.MRC_Rolled__c = product.MRC_Rolled__c == null ? 0 : product.MRC_Rolled__c;
  428.                     newSoldService.Previous_MRC__c = product.MRC_Previous__c;
  429.  
  430.                     newSoldService.dMRC__c = (
  431.                         (newSoldService.MRC__c == null ? 0 : newSoldService.MRC__c) +
  432.                         (newSoldService.MRC_Rolled__c == null ? 0 : newSoldService.MRC_Rolled__c)
  433.                         ) - (product.MRC_Previous__c == null ? 0 : product.MRC_Previous__c);
  434.                        
  435.                     newSoldService.Recommended_Base_Unit_Price__c = product.Unit_Price__c;
  436.                     newSoldService.Recommended_Burst_Price__c = product.Unit_Burst_Price__c;
  437.                    
  438.                     newSoldService.Capex__c = product.TPI_Capex__c;
  439.                     newSoldService.OTE__c = product.OTE__c;
  440.                     newSoldService.Budget_OTE__c = product.OTE__c;
  441.                     newSoldService.MRE__c = product.MRE__c;
  442.                     newSoldService.Budget_MRE__c = product.MRE__c;
  443.                    
  444.                     newSoldService.Anticipated_month_one_impact__c = product.Anticipated_month_one_impact__c;
  445.                    
  446.                     newSoldService.A_Location__c = product.A_Location__c;
  447.                     if(i == 1 || product.A_Port_Option__c != 'New Port') {
  448.                         newSoldService.A_Port__c = product.A_Port__c;
  449.                     } else if(product.A_Port__c != null && portsToClone.get(product.A_Port__c) != null) {
  450.                         Port__c newPort = portsToClone.get(product.A_Port__c).clone(false, true);
  451.                         String p1 = EncodingUtil.ConvertTohex(Crypto.GenerateAESKey(128));
  452.                         String portUpsertKey = p1.substring(0,8)+ '-' + p1.substring(8,12) + '-' + p1.substring(12,16) + '-' + p1.substring(16,20) + '-' + p1.substring(20);
  453.                         newPort.TECH_External_ID__c = portUpsertKey;
  454.                         portsToCreate.add(newPort);
  455.                         newSoldService.A_Port__r = new Port__c(TECH_External_ID__c = portUpsertKey);
  456.                         portExternalIds.add(portUpsertKey);
  457.                     }
  458.                     newSoldService.A_Port_Option__c = product.A_Port_Option__c;
  459.                     newSoldService.A_Port_Type__c = product.A_Port_Type__c;
  460.                     newSoldService.A_Connector__c = product.A_Port_Connector__c;
  461.                     newSoldService.A_Interface__c = product.A_Port_Interface__c;
  462.                     newSoldService.A_Site__c = product.A_Site__c;
  463.                     newSoldService.A_Demarc_Site__c = product.A_Demarc_Site__c;
  464.                     newSoldService.A_Demarc_Type__c = product.A_Demarc_Type__c;
  465.                     newSoldService.A_Demarc_Comments__c = product.A_Demarc_Comments__c;
  466.                     newSoldService.A_Floor__c = product.A_Floor__c;
  467.                     newSoldService.A_Room__c = product.A_Room__c;
  468.                     newSoldService.A_Rack_Cabinet__c = product.A_Rack_Cabinet__c;
  469.                     newSoldService.A_Homing_Gateway_Location__c = product.A_Homing_Gateway_Location__c;
  470.  
  471.                     newSoldService.B_Location__c = product.B_Location__c;
  472.                     if(i == 1 || product.B_Port_Option__c != 'New Port') {
  473.                         newSoldService.B_Port__c = product.B_Port__c;
  474.                     } else if(product.B_Port__c != null && portsToClone.get(product.B_Port__c) != null) {
  475.                         Port__c newPort = portsToClone.get(product.B_Port__c).clone(false, true);
  476.                         String p1 = EncodingUtil.ConvertTohex(Crypto.GenerateAESKey(128));
  477.                         String portUpsertKey = p1.substring(0,8)+ '-' + p1.substring(8,12) + '-' + p1.substring(12,16) + '-' + p1.substring(16,20) + '-' + p1.substring(20);
  478.                         newPort.TECH_External_ID__c = portUpsertKey;
  479.                         portsToCreate.add(newPort);
  480.                         newSoldService.B_Port__r = new Port__c(TECH_External_ID__c = portUpsertKey);
  481.                         portExternalIds.add(portUpsertKey);
  482.                     }
  483.                     newSoldService.B_Port_Option__c = product.B_Port_Option__c;
  484.                     newSoldService.B_Port_Type__c = product.B_Port_Type__c;
  485.                     newSoldService.B_Connector__c = product.B_Port_Connector__c;
  486.                     newSoldService.B_Interface__c = product.B_Port_Interface__c;
  487.                     newSoldService.B_Site__c = product.B_Site__c;
  488.                     newSoldService.B_Demarc_Site__c = product.B_Demarc_Site__c;
  489.                     newSoldService.B_Demarc_Type__c = product.B_Demarc_Type__c;
  490.                     newSoldService.B_Demarc_Comments__c = product.B_Demarc_Comments__c;
  491.                     newSoldService.B_Floor__c = product.B_Floor__c;
  492.                     newSoldService.B_Room__c = product.B_Room__c;
  493.                     newSoldService.B_Rack_Cabinet__c = product.B_Rack_Cabinet__c;
  494.                     newSoldService.B_Homing_Gateway_Location__c = product.B_Homing_Gateway_Location__c;
  495.                    
  496.                     newSoldService.Product_Type__c = 'Product';
  497.                     newSoldService.Product_Group__c = product.Product_Definition__c != null ? product.Product_Definition__r.Product_Group__c : '';
  498.                     newSoldService.Item_Main_Category__c = newSoldService.Product_Group__c;
  499.                     newSoldService.Product_Code__c = typeOfServiceToproductCode.get(product.Type_of_Service__c);
  500.                    
  501.                     /* assigning attribute values */
  502.                     Id dualLinkReference = null;
  503.                     String dualLinkField = null;
  504.                     Map<String, String> coloRefMap = new Map<String, String>();
  505.                    
  506.                     if(soldServiceMappings_Attributes.get(product.Product_Definition__c) != null && soldServiceMappings_Attributes.get(product.Product_Definition__c).get(null) != null) {
  507.                         for(CPQ_Sold_Service_Mapping__c mapping : soldServiceMappings_Attributes.get(product.Product_Definition__c).get(null)) {
  508.                             if(String.isNotEmpty(mapping.Target_Field_Sold_Service__c)) {
  509.                                 for(CPQ_QuoteItemAttribute__c attr : product.QuoteItemAttributes__r) {
  510.                                     if(mapping.Attribute__c == attr.Attribute__c) {
  511.                                         String attrValue = '';
  512.                                         if(mapping.Attribute__r.Type__c == CPQ_ATR01_Manager.ATR_TYPE_SERVICE_REFERENCE && mapping.Attribute__r.TECH_Definition_ID__c.contains(ATTRIBUTE_DUALLINK_PREFIX)) {
  513.                                             if(attr.Value_Quote_Item__c != null) {
  514.                                                 dualLinkReference = attr.Value_Quote_Item__c;
  515.                                                 dualLinkField = mapping.Target_Field_Sold_Service__c;
  516.                                                 break;
  517.                                             } else {
  518.                                                 attrValue = attr.Value_Sold_Service__c;
  519.                                             }
  520.                                         } else if(mapping.Attribute__r.TECH_Definition_ID__c == ATTRIBUTE_PORTS_GRID) {
  521.                                             attrValue = CalculateGridValueForPorts(mapping.Attribute__r.Grid_Layout__c, components.get(product.Id), null);
  522.                                         } else {
  523.                                             attrValue = CPQ_PRI01_Manager.getAttributeValueAsString(attr, true);
  524.                                         }
  525.                                         CPQ_PRI01_Manager.setFieldValueFromString(newSoldService, mapping.Target_Field_Sold_Service__c, attrValue, globalDescribe);
  526.                                         break;                                      
  527.                                     }
  528.                                 }
  529.                             }
  530.                         }
  531.                     }
  532.                    
  533.                     /* assigning field values */
  534.                     if(soldServiceMappings_Fields.get(product.Product_Definition__c) != null && soldServiceMappings_Fields.get(product.Product_Definition__c).get(null) != null) {
  535.                         for(CPQ_Sold_Service_Mapping__c mapping : soldServiceMappings_Fields.get(product.Product_Definition__c).get(null)) {
  536.                             if(String.isNotEmpty(mapping.Target_Field_Sold_Service__c)) {
  537.                                 String fieldValue = String.valueOf(product.get(mapping.Source_Field_Name__c));
  538.                                 CPQ_PRI01_Manager.setFieldValueFromString(newSoldService, mapping.Target_Field_Sold_Service__c, fieldValue, globalDescribe);
  539.                             }
  540.                         }
  541.                     }
  542.                    
  543.                     /* assigning constant values */
  544.                     if(soldServiceMappings_Constants.get(product.Product_Definition__c) != null && soldServiceMappings_Constants.get(product.Product_Definition__c).get(null) != null) {
  545.                         for(CPQ_Sold_Service_Mapping__c mapping : soldServiceMappings_Constants.get(product.Product_Definition__c).get(null)) {
  546.                             if(String.isNotEmpty(mapping.Target_Field_Sold_Service__c)) {
  547.                                 CPQ_PRI01_Manager.setFieldValueFromString(newSoldService, mapping.Target_Field_Sold_Service__c, mapping.Source_Constant_Value__c, globalDescribe);
  548.                             }
  549.                         }
  550.                     }
  551.                    
  552.                     if(product.Opportunity__c != null && product.Opportunity__r.CloseDate != null && newSoldService.Estimated_Delivery_Date__c == null) {
  553.                         Decimal leadTime = product.Lead_Time__c == null ? 0 : product.Lead_Time__c;
  554.                         newSoldService.Estimated_Delivery_Date__c = product.Opportunity__r.CloseDate.addDays(leadTime.intValue());
  555.                     }
  556.                    
  557.                     if(product.Item_Action__c == ACTION_CHANGE) {
  558.                         newSoldService.Billing_Commence_Date__c = null;
  559.                     }
  560.                    
  561.                     /* generating upsert key */
  562.                     String h1 = EncodingUtil.ConvertTohex(Crypto.GenerateAESKey(128));
  563.                     String productUpsertKey = h1.substring(0,8)+ '-' + h1.substring(8,12) + '-' + h1.substring(12,16) + '-' + h1.substring(16,20) + '-' + h1.substring(20);
  564.                    
  565.                     newSoldService.Upsert_Key__c = productUpsertKey;
  566.                     quoteItemId2SoldServiceExternalId.put(product.Id, newSoldService.Upsert_Key__c);
  567.                    
  568.                     /* handling dual link data */
  569.                     if(String.isNotBlank(dualLinkReference) && String.isNotBlank(dualLinkField)) {
  570.                         soldServiceDualLinkReference.put(newSoldService.Upsert_Key__c, dualLinkReference);
  571.                         soldServiceDualLinkField.put(newSoldService.Upsert_Key__c, dualLinkField);
  572.                     }
  573.  
  574.                     /* handling A / B end data */
  575.                     if (!String.isBlank(product.A_End_ID__c)) {
  576.                         soldServiceAEndReference.put(productUpsertKey, product.A_End_ID__c);
  577.                     }
  578.  
  579.                     if (!String.isBlank(product.B_End_ID__c)) {
  580.                         soldServiceBEndReference.put(productUpsertKey, product.B_End_ID__c);
  581.                     }
  582.                    
  583.                     if(newSoldService.A_Port__c != null && product.A_Port_Option__c == 'New Port'){
  584.                         portIds.add(newSoldService.A_Port__c);
  585.                     }
  586.                     if(newSoldService.B_Port__c != null && product.B_Port_Option__c == 'New Port'){
  587.                         portIds.add(newSoldService.B_Port__c);
  588.                     }
  589.                
  590.                     if(quoteItemToSoldService == null || !quoteItemToSoldService.keySet().contains(key(i,product.Id))) {
  591.                         soldServiceProductsToUpsert.add(newSoldService);
  592.                         result.upsertKeyToQuoteItem.put(newSoldService.Upsert_Key__c, key(i,product.Id));
  593.                     }
  594.                    
  595.                     Date maxTPSDate;
  596.                    
  597.                     if(product.X3rd_Party_Items__r != null) {
  598.                        
  599.                         Map<Id, Id> tpiToParent = new Map<Id, Id>();
  600.                         Map<Id, String> tpiIdToTPSExternalId = new Map<Id, String>();
  601.                         List<X3rd_Party_Services__c> tpsToParentUpdate = new List<X3rd_Party_Services__c>();
  602.                        
  603.                         for(X3rd_Party_Item__c tpi : product.X3rd_Party_Items__r){
  604.                             if(tpi.Chosen__c){
  605.                                 X3rd_Party_Services__c tps;
  606.                                 if(tpi.TPI_Order_Type__c == TPI_ORDER_TYPE_DISMANTLE && tpi.Existing_X3rd_Party_Service__c != null) {
  607.                                     tps = new X3rd_Party_Services__c(Id = tpi.Existing_X3rd_Party_Service__c);
  608.                                     tps.Status__c = TPS_STATUS_DISMANTLE;
  609.                                     tps.Date_for_Dismantle__c = product.Date_Expected_Delivery__c;
  610.                                     tps.Dismantle_Request_Received__c = product.Opportunity__r.CloseDate;
  611.                                     thirdPartyServicesToUpsert2.put(tps.Id, tps);
  612.                                 } else if(tpi.TPI_Order_Type__c != TPI_ORDER_TYPE_DISMANTLE) {
  613.                                     tps = new X3rd_Party_Services__c();
  614.                                     tps.Status__c = ApplicationConstant.TPS_STATUS_POREQUIRED;
  615.                                     newSoldService.Minimum_Status_TPS__c = tps.Status__c;
  616.                                     if(ApplicationConstant.TPI_PRIMARY_GENERIC_SUPPLIER_PRODUCT_TSIC_BACKHAUL.equalsIgnoreCase(tpi.Primary_Generic_Supplier_Product__c)
  617.                                     && String.isNotBlank(tpi.Supplier_Account_Name__c) && tpi.Supplier_Account_Name__c.containsIgnoreCase(ApplicationConstant.COMPANY_NAME)){
  618.                                         tps.Status__c = ApplicationConstant.TPS_STATUS_LIVE;
  619.                                         tps.Supplier_Service_Reference__c = ApplicationConstant.COMPANY_NAME;
  620.                                     }
  621.                                    
  622.                                     //tps.Name = 'TPS';
  623.                                     tps.Name = codes.generateCode(system.label.CRM_THIRD_PARTY_SERVICE);
  624.                                     tps.Sold_Service__r = new Sold_Service__c(Upsert_Key__c = newSoldService.Upsert_Key__c);
  625.                                     tps.Supporting_Sold_Service__c  = tpi.Supporting_Sold_Service__c;
  626.                                     tps.Source_TPI_No__c = tpi.Id;
  627.                                     tps.Port__c = tpi.Port__c;
  628.                                
  629.                                     for (String f : tpsFieldMap.keySet()) {
  630.                                         tps.put(tpsFieldMap.get(f), tpi.get(f));
  631.                                     }
  632.                                    
  633.                                     String h3 = EncodingUtil.ConvertTohex(Crypto.GenerateAESKey(128));
  634.                                     String tpsUpsertKey = h3.substring(0,8)+ '-' + h3.substring(8,12) + '-' + h3.substring(12,16) + '-' + h3.substring(16,20) + '-' + h3.substring(20);
  635.                                     tps.x3ParSerUID__c = tpsUpsertKey;
  636.                                            
  637.                                     if(tpi.Existing_X3rd_Party_Service__c != null) {
  638.                                         tps.Replaced_TPS__c = tpi.Existing_X3rd_Party_Service__c;
  639.                                         X3rd_Party_Services__c oldTPS = new X3rd_Party_Services__c(Id = tpi.Existing_X3rd_Party_Service__c);
  640.                                         oldTPS.TPS_replaced_by__r = new X3rd_Party_Services__c(x3ParSerUID__c = tpsUpsertKey);
  641.                                         oldTPS.Status__c = TPS_STATUS_REPLACED;
  642.                                         if(product.Item_Action__c == ACTION_RENEWAL) {
  643.                                             /* moving TOS under new sold service for renewal */
  644.                                             oldTPS.Sold_Service__r = new Sold_Service__c(Upsert_Key__c = newSoldService.Upsert_Key__c);
  645.                                         }
  646.                                         thirdPartyServicesToUpsert2.put(oldTPS.Id, oldTPS);
  647.                                     }
  648.                                
  649.                                     Date maxDate;
  650.                                    
  651.                                     if(tps.Forecasted_Delivery_Date__c != null){
  652.                                         maxDate = tps.Forecasted_Delivery_Date__c.date();
  653.                                     }
  654.                        
  655.                                     if(tps.Committed_Delivery_Date__c != null){
  656.                                         maxDate = tps.Committed_Delivery_Date__c.date();
  657.                                     }
  658.                        
  659.                                     if(tps.Revised_Delivery_Date__c != null){
  660.                                         maxDate = tps.Revised_Delivery_Date__c.date();
  661.                                     }
  662.                                    
  663.                                     if(maxDate != null) {
  664.                                         if(maxTPSDate == null || maxTPSDate < maxDate) {
  665.                                             maxTPSDate = maxDate;
  666.                                         }
  667.                                     }
  668.                                
  669.                                     thirdPartyServicesToUpsert.add(tps);
  670.    
  671.                                     if(tpi.Parent__c != null && String.isNotEmpty(tpi.Parent__r.Upsert_Key__c)) {
  672.                                         tpiToParent.put(tpi.Id, tpi.Parent__c);
  673.                                         tpsToParentUpdate.add(tps);
  674.                                     }
  675.                                     tpiIdToTPSExternalId.put(tpi.Id, tps.x3ParSerUID__c);
  676.                                    
  677.                                    
  678.                                     if(!tpisAlreadyAdded.contains(tpi.Id)) {
  679.                                         tpi.RecordTypeId = tpiReadOnlyRecordType;
  680.                                         thirdPartyItemsToUpdate.add(tpi);
  681.                                         tpisAlreadyAdded.add(tpi.Id);
  682.                                     }
  683.    
  684.                                     if (tpi.Secondary_Supplier_Product__c == 'NNI') {
  685.                                         newSoldService.NNI_Used__c = true;
  686.                                     }
  687.    
  688.                                     if (tpi.Secondary_Supplier_Product__c == 'CPE' || tpi.Secondary_Supplier_Product__c == 'NID') {
  689.                                         newSoldService.Includes_CPE__c = true;
  690.                                     }
  691.                                 }
  692.                             }
  693.                         }
  694.                        
  695.                         for(X3rd_Party_Services__c tps : tpsToParentUpdate) {
  696.                             if(tpiToParent.keySet().contains(tps.Source_TPI_No__c)) {
  697.                                 if(tpiIdToTPSExternalId.get(tpiToParent.get(tps.Source_TPI_No__c)) != null) {
  698.                                     X3rd_Party_Services__c tpsParent = new X3rd_Party_Services__c(x3ParSerUID__c = tps.x3ParSerUID__c);
  699.                                     tpsParent.Parent__r = new X3rd_Party_Services__c(x3ParSerUID__c = tpiIdToTPSExternalId.get(tpiToParent.get(tps.Source_TPI_No__c)));
  700.                                     thirdPartyServicesToUpsertParent.add(tpsParent);
  701.                                 }
  702.                             }
  703.                         }
  704.                     }
  705.                    
  706.                     if(maxTPSDate != null) newSoldService.Maximum_RFS_Date_TPS__c = maxTPSDate;
  707.                    
  708.                     /* adding charges if appropriate attribute type found */
  709.                     for(CPQ_QuoteItemAttribute__c attr : product.QuoteItemAttributes__r) {
  710.                         if(attr.Type__c == CPQ_ATR01_Manager.ATR_TYPE_CHARGE) {
  711.                             if(String.isNotEmpty(attr.Value_Text_Long__c)){
  712.                                 List<CPQ_Charge__c> deserializedCharges = (List<CPQ_Charge__c>)JSON.deserialize(attr.Value_Text_Long__c, List<CPQ_Charge__c>.class);
  713.                                 for(CPQ_Charge__c charge : deserializedCharges){
  714.                                     CPQ_Charge__c newCharge;
  715.                                     if(charge.Id != null) {
  716.                                          newCharge = new CPQ_Charge__c(Id = charge.Id);
  717.                                     } else {
  718.                                         newCharge = new CPQ_Charge__c();
  719.                                     }
  720.                                     cloneObject(charge, newCharge, 'CPQ_Charge__c');
  721.                                     newCharge.Attribute__c = attr.Attribute__c;
  722.                                     newCharge.Quote__c = product.Quote__c;
  723.                                     newCharge.Quote_Item__c = product.Id;
  724.                                     newCharge.Sold_Service__r = new Sold_Service__c(Upsert_Key__c = newSoldService.Upsert_Key__c);
  725.                                     chargesToUpsert.add(newCharge);
  726.                                 }
  727.                             }
  728.                         }
  729.                     }
  730.                    
  731.                     /* Handling port change requests if applicable */
  732.                     if(product.Port_Change_Requests__r != null) {
  733.                         for(Port_Change_Request__c pcr : product.Port_Change_Requests__r) {
  734.                             if(pcr.Port__c == product.A_Port__c && product.A_Port_Option__c == 'Existing Port') {
  735.                                 newSoldService.A_Port_in_Change__c = true;
  736.                             }
  737.                             if(pcr.Port__c == product.B_Port__c && product.B_Port_Option__c == 'Existing Port') {
  738.                                 newSoldService.B_Port_in_Change__c = true;
  739.                             }
  740.                            
  741.                             Port_Change_Request__c pcrToUpsert = new Port_Change_Request__c(Id = pcr.Id);
  742.                             pcrToUpsert.Sold_Service__r = new Sold_Service__c(Upsert_Key__c = newSoldService.Upsert_Key__c);
  743.                             pcrToUpsert.Stage__c = STAGE_NEW;
  744.                             portCRsToUpsert.put(pcr.Id, pcrToUpsert);
  745.                         }
  746.                     }
  747.                 }
  748.                                
  749.                 if(components.get(product.Id) != null) {
  750.                     for(CPQ_QuoteItem__c component : components.get(product.Id)) {
  751.                         for(Integer j = 1; j <= component.Quantity__c; j++) {
  752.                             Sold_Service__c newSoldServiceComponent;
  753.                             Boolean existingComponentRecordUpdate = false;
  754.                            
  755.                             if(soldServiceMappings_Numbers.get(product.Product_Definition__c) == null || soldServiceMappings_Numbers.get(product.Product_Definition__c).get(component.Component_Definition__c) == null ||
  756.                             (soldServiceMappings_Numbers.get(product.Product_Definition__c).get(component.Component_Definition__c)[0].Generate_ICC_Number__c == false &&
  757.                             soldServiceMappings_Numbers.get(product.Product_Definition__c).get(component.Component_Definition__c)[0].Generate_IC_Number__c == false &&
  758.                             soldServiceMappings_Numbers.get(product.Product_Definition__c).get(component.Component_Definition__c)[0].Generate_ICB_Number__c == false)) {
  759.                                 continue;
  760.                             } else if(soldServiceMappings_Numbers.get(product.Product_Definition__c) != null && soldServiceMappings_Numbers.get(product.Product_Definition__c).get(component.Component_Definition__c) != null &&
  761.                                 soldServiceMappings_Numbers.get(product.Product_Definition__c).get(component.Component_Definition__c)[0].Update_on_Change__c && component.Existing_Object_ID__c != null) {
  762.                                 newSoldServiceComponent = new Sold_Service__c(Id = component.Existing_Object_ID__c);
  763.                                 existingComponentRecordUpdate = true;
  764.                             } else {
  765.                                 newSoldServiceComponent = new Sold_Service__c();
  766.                             }
  767.    
  768.                             newSoldServiceComponent.Item_Action__c = component.Item_Action__c;
  769.                             newSoldServiceComponent.Service_Description__c = component.Description__c;
  770.                             newSoldServiceComponent.Configuration_Description__c = component.Configuration_Description__c;
  771.                            
  772.                             if(quoteItemToSoldService.get(key(i,product.Id)) != null) {
  773.                                 newSoldServiceComponent.CRM_Parent_Sold_Service__c = quoteItemToSoldService.get(key(i,product.Id));
  774.                                 newSoldServiceComponent.CRM_Main_Sold_Service__c = quoteItemToSoldService.get(key(i,product.Id));
  775.                             }else if(newSoldService.Id != null) {
  776.                                 newSoldServiceComponent.CRM_Parent_Sold_Service__c = newSoldService.Id;
  777.                                 newSoldServiceComponent.CRM_Main_Sold_Service__c = newSoldService.Id;
  778.                             } else {
  779.                                 newSoldServiceComponent.CRM_Parent_Sold_Service__r = new Sold_Service__c(Upsert_Key__c = newSoldService.Upsert_Key__c);
  780.                                 newSoldServiceComponent.CRM_Main_Sold_Service__r = new Sold_Service__c(Upsert_Key__c = newSoldService.Upsert_Key__c);
  781.                             }
  782.                            
  783.                             if(!existingComponentRecordUpdate) {
  784.                                 newSoldServiceComponent.Stage__c = STAGE_NEW;
  785.                             }
  786.                            
  787.                             if(product.Product_Definition__r.Product_Group__c == 'Voice' || product.Product_Definition__r.Product_Group__c == 'Roaming & Messaging') {
  788.                                 newSoldServiceComponent.RecordType = new RecordType(Name = RT_SSERVICE_OPERATIONAL_VM);
  789.                             } else {
  790.                                 newSoldServiceComponent.RecordType = new RecordType(Name = RT_SSERVICE_OPERATIONAL_DI);
  791.                             }
  792.                            
  793.                             /* keeping sold service number for modifications */
  794.                             if(component.Item_Action__c == ACTION_ADD) {
  795.                                 CPQ_Sold_Service_Mapping__c whatCode;
  796.                                 if(soldServiceMappings_Numbers.get(product.Product_Definition__c) != null && soldServiceMappings_Numbers.get(product.Product_Definition__c).get(component.Component_Definition__c) != null) {
  797.                                     whatCode = soldServiceMappings_Numbers.get(product.Product_Definition__c).get(component.Component_Definition__c)[0];
  798.                                 }
  799.                                
  800.                                 if(whatCode != null && whatCode.Generate_ICC_Number__c){
  801.                                     newSoldServiceComponent.Name = codes.generateCode(system.label.CRM_COM_PRODUCT);
  802.                                 } else if(whatCode != null && whatCode.Generate_IC_Number__c) {
  803.                                     newSoldServiceComponent.Name = codes.generateCode(system.label.CRM_OPR_PRODUCT);
  804.                                 } else if(whatCode != null && whatCode.Generate_ICB_Number__c) {
  805.                                     newSoldServiceComponent.Name = codes.generateCode(system.label.CRM_INTERNAL_PRODUCT);
  806.                                 }
  807.                             } else if(component.Item_Action__c == ACTION_CHANGE) {
  808.                                 newSoldServiceComponent.Name = component.Existing_Object_ID__r.Name;
  809.                                
  810.                                 if(!existingComponentRecordUpdate) {
  811.                                     newSoldServiceComponent.Renewed_From__c = component.Existing_Object_ID__c;
  812.                                    
  813.                                     Sold_Service__c changedService = new Sold_Service__c(Id = component.Existing_Object_ID__c);
  814.                                     changedService.Stage__c = STAGE_REPLACEMENT;
  815.                                     soldServiceComponentsToUpsert.add(changedService);
  816.                                 }
  817.                             } else if(component.Item_Action__c == ACTION_RENEWAL) {
  818.                                 newSoldServiceComponent.Name = component.Existing_Object_ID__r.Name;
  819.                                 newSoldServiceComponent.Estimated_Delivery_Date__c = null;
  820.                                
  821.                                 if(!existingComponentRecordUpdate) {
  822.                                     newSoldServiceComponent.Renewed_From__c = component.Existing_Object_ID__c;
  823.                                    
  824.                                     Sold_Service__c changedService = new Sold_Service__c(Id = component.Existing_Object_ID__c);
  825.                                     changedService.Stage__c = STAGE_REPLACEMENT;
  826.                                     soldServiceComponentsToUpsert.add(changedService);
  827.                                 }
  828.                             } else if(component.Item_Action__c == ACTION_CEASE) {
  829.                                 newSoldServiceComponent.Name = component.Existing_Object_ID__r.Name;
  830.                                
  831.                                 if(!existingComponentRecordUpdate) {
  832.                                     newSoldServiceComponent.Renewed_From__c = component.Existing_Object_ID__c;
  833.                                    
  834.                                     Sold_Service__c changedService = new Sold_Service__c(Id = component.Existing_Object_ID__c);
  835.                                     changedService.Stage__c = STAGE_REPLACEMENT;
  836.                                     if(component.Cease_and_Reprovide_Type__c != null && component.Cease_and_Reprovide_Type__c == CEASE_PARALLEL_BUILD) {
  837.                                         if(component.Opportunity__c != null) {
  838.                                             changedService.Specification_Received_Date__c = component.Opportunity__r.CloseDate;
  839.                                             if(component.Opportunity__r.Commercial_Contact__c != null) {
  840.                                                 changedService.Person_requesting_the_dismantle__c = component.Opportunity__r.Commercial_Contact__r.Name;
  841.                                             }
  842.                                         }
  843.                                         changedService.Dismantle_Notes__c = CEASEANDREPROVIDE_TXT;
  844.                                     }
  845.                                     soldServiceComponentsToUpsert.add(changedService);
  846.                                 }
  847.                             } else if(component.Item_Action__c == ACTION_DISMANTLE) {
  848.                                 Sold_Service__c dismantledService = new Sold_Service__c(Id = component.Existing_Object_ID__c);
  849.                                 dismantledService.Previous_MRC__c = component.MRC_Previous__c;
  850.                                 dismantledService.MRC__c = 0;
  851.                                 dismantledService.Stage__c = STAGE_DISMANTLE;
  852.                                 dismantledService.Date_for_Dismantle__c = product.Date_Expected_Delivery__c == null ? component.Date_Expected_Delivery__c : product.Date_Expected_Delivery__c;
  853.                                 dismantledService.Dismantle_Notes__c = DISMANTLE_TXT;
  854.                                 if(component.Opportunity__c != null) {
  855.                                     dismantledService.Specification_Received_Date__c = component.Opportunity__r.CloseDate;
  856.                                     if(component.Opportunity__r.Commercial_Contact__c != null) {
  857.                                         dismantledService.Person_requesting_the_dismantle__c = component.Opportunity__r.Commercial_Contact__r.Name;
  858.                                     }
  859.                                 }
  860.                                
  861.                                 soldServiceComponentsToUpsert.add(dismantledService);
  862.                                
  863.                                 if(component.X3rd_Party_Items__r != null) {
  864.                                     for(X3rd_Party_Item__c tpi : component.X3rd_Party_Items__r) {
  865.                                         if(tpi.Existing_X3rd_Party_Service__c != null) {
  866.                                             X3rd_Party_Services__c oldTPS = new X3rd_Party_Services__c(Id = tpi.Existing_X3rd_Party_Service__c);
  867.                                             oldTPS.Status__c = '90 Pending Dismantle';
  868.                                             thirdPartyServicesToUpsert2.put(oldTPS.Id, oldTPS);
  869.                                         }
  870.                                     }
  871.                                 }
  872.                             }
  873.                            
  874.                             if(component.Item_Action__c != ACTION_DISMANTLE) {
  875.                                 /* generate a new IC/ICC number if the option was selected */
  876.                                 if(component.Assign_New_IC_ICC_Number__c && !existingComponentRecordUpdate) {
  877.                                     CPQ_Sold_Service_Mapping__c whatCode;
  878.                                     if(soldServiceMappings_Numbers.get(product.Product_Definition__c) != null && soldServiceMappings_Numbers.get(product.Product_Definition__c).get(component.Component_Definition__c) != null) {
  879.                                         whatCode = soldServiceMappings_Numbers.get(product.Product_Definition__c).get(component.Component_Definition__c)[0];
  880.                                     }
  881.                                    
  882.                                     if(whatCode != null && whatCode.Generate_ICC_Number__c){
  883.                                         newSoldServiceComponent.Name = codes.generateCode(system.label.CRM_COM_PRODUCT);
  884.                                     } else if(whatCode != null && whatCode.Generate_IC_Number__c) {
  885.                                         newSoldServiceComponent.Name = codes.generateCode(system.label.CRM_OPR_PRODUCT);
  886.                                     } else if(whatCode != null && whatCode.Generate_ICB_Number__c) {
  887.                                         newSoldServiceComponent.Name = codes.generateCode(system.label.CRM_INTERNAL_PRODUCT);
  888.                                     }
  889.                                 }
  890.                                
  891.                                 if(component.Item_Action__c == ACTION_RENEWAL && !existingComponentRecordUpdate) {
  892.                                     newSoldServiceComponent.Stage__c = STAGE_RENEWAL;
  893.                                 }
  894.                                
  895.                                 newSoldServiceComponent.CurrencyIsoCode = component.CurrencyIsoCode;
  896.                                
  897.                                 newSoldServiceComponent.Opp_Link__c = product.Opportunity__c;
  898.                                 newSoldServiceComponent.CRM_Account__c = product.Account__c;
  899.                                 newSoldServiceComponent.Instance_ID__c = newSoldServiceComponent.Name;
  900.                                 newSoldServiceComponent.CPQ_Component__c = component.Component_Definition__c;
  901.                                 newSoldServiceComponent.Item_Name__c = component.Component_Definition__r.Name;
  902.                                 newSoldServiceComponent.Item_Type__c = system.label.CRM_OPR_PRODUCT;
  903.                                 newSoldServiceComponent.OLI_Link_ID__c = component.OpportunityLineItem_ID__c;
  904.                                 newSoldServiceComponent.OLI_Link_Name__c = oppLineItems.get(component.OpportunityLineItem_ID__c) == null ? component.Name : oppLineItems.get(component.OpportunityLineItem_ID__c).Product2.Name;
  905.                                 newSoldServiceComponent.Item_Action_Description__c = component.Item_Action_Description__c;
  906.                                 newSoldServiceComponent.Days_of_Parallel_Running__c = component.Parallel_build_period__c;
  907.                                
  908.                                 newSoldServiceComponent.List_OTC__c = component.OTC_List__c;
  909.                                 newSoldServiceComponent.OTC__c = component.OTC__c;
  910.                                 newSoldServiceComponent.OTC_Rolled__c = component.OTC_Rolled__c == null ? 0 : component.OTC_Rolled__c;
  911.                                 newSoldServiceComponent.List_MRC__c = component.MRC_List__c;
  912.                                 newSoldServiceComponent.MRC__c = component.MRC__c;
  913.                                 newSoldServiceComponent.MRC_Rolled__c = component.MRC_Rolled__c == null ? 0 : component.MRC_Rolled__c;
  914.                                 newSoldServiceComponent.Previous_MRC__c = component.MRC_Previous__c;
  915.    
  916.                                 newSoldServiceComponent.dMRC__c = (
  917.                                     (newSoldServiceComponent.MRC__c == null ? 0 : newSoldServiceComponent.MRC__c) +
  918.                                     (newSoldServiceComponent.MRC_Rolled__c == null ? 0 : newSoldServiceComponent.MRC_Rolled__c)
  919.                                     ) - (component.MRC_Previous__c == null ? 0 : component.MRC_Previous__c);
  920.                            
  921.                                 newSoldServiceComponent.Recommended_Base_Unit_Price__c = component.Unit_Price__c;
  922.                                 newSoldServiceComponent.Recommended_Burst_Price__c = component.Unit_Burst_Price__c;
  923.                        
  924.                                 newSoldServiceComponent.Capex__c = component.TPI_Capex__c;
  925.                                 newSoldServiceComponent.OTE__c = component.OTE__c;
  926.                                 newSoldServiceComponent.Budget_OTE__c = component.OTE__c;
  927.                                 newSoldServiceComponent.MRE__c = component.MRE__c;
  928.                                 newSoldServiceComponent.Budget_MRE__c = component.MRE__c;
  929.                                
  930.                                 newSoldServiceComponent.Anticipated_month_one_impact__c = component.Anticipated_month_one_impact__c;
  931.                                
  932.                                 newSoldServiceComponent.A_Location__c = component.A_Location__c;
  933.                                 if((i == 1 && j == 1) || component.A_Port_Option__c != 'New Port') {
  934.                                     newSoldServiceComponent.A_Port__c = component.A_Port__c;
  935.                                 } else if(component.A_Port__c != null && portsToClone.get(component.A_Port__c) != null) {
  936.                                     Port__c newPort = portsToClone.get(component.A_Port__c).clone(false, true);
  937.                                     String p1 = EncodingUtil.ConvertTohex(Crypto.GenerateAESKey(128));
  938.                                     String portUpsertKey = p1.substring(0,8)+ '-' + p1.substring(8,12) + '-' + p1.substring(12,16) + '-' + p1.substring(16,20) + '-' + p1.substring(20);
  939.                                     newPort.TECH_External_ID__c = portUpsertKey;
  940.                                     portsToCreate.add(newPort);
  941.                                     newSoldServiceComponent.A_Port__r = new Port__c(TECH_External_ID__c = portUpsertKey);
  942.                                     portExternalIds.add(portUpsertKey);
  943.                                 }
  944.  
  945.                                 newSoldServiceComponent.A_Port_Option__c = component.A_Port_Option__c;
  946.                                 newSoldServiceComponent.A_Port_Type__c = component.A_Port_Type__c;
  947.                                 newSoldServiceComponent.A_Connector__c = component.A_Port_Connector__c;
  948.                                 newSoldServiceComponent.A_Interface__c = component.A_Port_Interface__c;
  949.                                 newSoldServiceComponent.A_Site__c = component.A_Site__c;
  950.                                 newSoldServiceComponent.A_Demarc_Site__c = component.A_Demarc_Site__c;
  951.                                 newSoldServiceComponent.A_Demarc_Type__c = component.A_Demarc_Type__c;
  952.                                 newSoldServiceComponent.A_Demarc_Comments__c = component.A_Demarc_Comments__c;
  953.                                 newSoldServiceComponent.A_Floor__c = component.A_Floor__c;
  954.                                 newSoldServiceComponent.A_Room__c = component.A_Room__c;
  955.                                 newSoldServiceComponent.A_Rack_Cabinet__c = component.A_Rack_Cabinet__c;
  956.                                 newSoldServiceComponent.A_Homing_Gateway_Location__c = component.A_Homing_Gateway_Location__c;
  957.            
  958.                                 newSoldServiceComponent.B_Location__c = component.B_Location__c;
  959.                                 if((i == 1 && j == 1) || component.B_Port_Option__c != 'New Port') {
  960.                                     newSoldServiceComponent.B_Port__c = component.B_Port__c;
  961.                                 } else if(component.B_Port__c != null && portsToClone.get(component.B_Port__c) != null) {
  962.                                     Port__c newPort = portsToClone.get(component.B_Port__c).clone(false, true);
  963.                                     String p1 = EncodingUtil.ConvertTohex(Crypto.GenerateAESKey(128));
  964.                                     String portUpsertKey = p1.substring(0,8)+ '-' + p1.substring(8,12) + '-' + p1.substring(12,16) + '-' + p1.substring(16,20) + '-' + p1.substring(20);
  965.                                     newPort.TECH_External_ID__c = portUpsertKey;
  966.                                     portsToCreate.add(newPort);
  967.                                     newSoldServiceComponent.B_Port__r = new Port__c(TECH_External_ID__c = portUpsertKey);
  968.                                     portExternalIds.add(portUpsertKey);
  969.                                 }
  970.                                 newSoldServiceComponent.B_Port_Option__c = component.B_Port_Option__c;
  971.                                 newSoldServiceComponent.B_Port_Type__c = component.B_Port_Type__c;
  972.                                 newSoldServiceComponent.B_Connector__c = component.B_Port_Connector__c;
  973.                                 newSoldServiceComponent.B_Interface__c = component.B_Port_Interface__c;
  974.                                 newSoldServiceComponent.B_Site__c = component.B_Site__c;
  975.                                 newSoldServiceComponent.B_Demarc_Site__c = component.B_Demarc_Site__c;
  976.                                 newSoldServiceComponent.B_Demarc_Type__c = component.B_Demarc_Type__c;
  977.                                 newSoldServiceComponent.B_Demarc_Comments__c = component.B_Demarc_Comments__c;
  978.                                 newSoldServiceComponent.B_Floor__c = component.B_Floor__c;
  979.                                 newSoldServiceComponent.B_Room__c = component.B_Room__c;
  980.                                 newSoldServiceComponent.B_Rack_Cabinet__c = component.B_Rack_Cabinet__c;
  981.                                 newSoldServiceComponent.B_Homing_Gateway_Location__c = component.B_Homing_Gateway_Location__c;
  982.                                
  983.                                 newSoldServiceComponent.Product_Type__c = 'Component';
  984.                                 newSoldServiceComponent.Product_Group__c = product.Product_Definition__c != null ? product.Product_Definition__r.Product_Group__c : '';
  985.                                 newSoldServiceComponent.Item_Main_Category__c = newSoldServiceComponent.Product_Group__c;
  986.                                 newSoldServiceComponent.Product_Code__c = typeOfServiceToproductCode.get(component.Type_of_Service__c);
  987.                                
  988.                                 /* assigning attribute values */
  989.                                 Id dualLinkReferenceComponent = null;
  990.                                 String dualLinkFieldComponent = null;
  991.                                 Map<String, String> coloRefMapComponent = new Map<String, String>();
  992.    
  993.                                 if(soldServiceMappings_Attributes.get(product.Product_Definition__c) != null && soldServiceMappings_Attributes.get(product.Product_Definition__c).get(component.Component_Definition__c) != null) {
  994.                                     for(CPQ_Sold_Service_Mapping__c mapping : soldServiceMappings_Attributes.get(product.Product_Definition__c).get(component.Component_Definition__c)) {
  995.                                         if(String.isNotEmpty(mapping.Target_Field_Sold_Service__c)) {
  996.                                             for(CPQ_QuoteItemAttribute__c attr : component.QuoteItemAttributes__r) {
  997.                                                 if(mapping.Attribute__c == attr.Attribute__c) {
  998.                                                     String attrValue = '';
  999.                                                     if(mapping.Attribute__r.Type__c == CPQ_ATR01_Manager.ATR_TYPE_SERVICE_REFERENCE && mapping.Attribute__r.TECH_Definition_ID__c.contains(ATTRIBUTE_DUALLINK_PREFIX)) {
  1000.                                                         if(attr.Value_Quote_Item__c != null) {
  1001.                                                             dualLinkReferenceComponent = attr.Value_Quote_Item__c;
  1002.                                                             dualLinkFieldComponent = mapping.Target_Field_Sold_Service__c;
  1003.                                                             break;
  1004.                                                         } else {
  1005.                                                             attrValue = attr.Value_Sold_Service__c;
  1006.                                                         }
  1007.                                                     } else {
  1008.                                                         attrValue = CPQ_PRI01_Manager.getAttributeValueAsString(attr, true);
  1009.                                                     }
  1010.                                                     CPQ_PRI01_Manager.setFieldValueFromString(newSoldServiceComponent, mapping.Target_Field_Sold_Service__c, attrValue, globalDescribe);
  1011.                                                     break;
  1012.                                                 }
  1013.                                             }
  1014.                                         }
  1015.                                     }
  1016.                                 }
  1017.                                
  1018.                                 /* assigning field values */
  1019.                                 if(soldServiceMappings_Fields.get(product.Product_Definition__c) != null && soldServiceMappings_Fields.get(product.Product_Definition__c).get(component.Component_Definition__c) != null) {
  1020.                                     for(CPQ_Sold_Service_Mapping__c mapping : soldServiceMappings_Fields.get(product.Product_Definition__c).get(component.Component_Definition__c)) {
  1021.                                         if(String.isNotEmpty(mapping.Target_Field_Sold_Service__c)) {
  1022.                                             String fieldValue = String.valueOf(component.get(mapping.Source_Field_Name__c));
  1023.                                             CPQ_PRI01_Manager.setFieldValueFromString(newSoldServiceComponent, mapping.Target_Field_Sold_Service__c, fieldValue, globalDescribe);
  1024.                                         }
  1025.                                     }
  1026.                                 }
  1027.                                
  1028.                                 /* assigning constant values */
  1029.                                 if(soldServiceMappings_Constants.get(product.Product_Definition__c) != null && soldServiceMappings_Constants.get(product.Product_Definition__c).get(component.Component_Definition__c) != null) {
  1030.                                     for(CPQ_Sold_Service_Mapping__c mapping : soldServiceMappings_Constants.get(product.Product_Definition__c).get(component.Component_Definition__c)) {
  1031.                                         if(String.isNotEmpty(mapping.Target_Field_Sold_Service__c)) {
  1032.                                             CPQ_PRI01_Manager.setFieldValueFromString(newSoldServiceComponent, mapping.Target_Field_Sold_Service__c, mapping.Source_Constant_Value__c, globalDescribe);
  1033.                                         }
  1034.                                     }
  1035.                                 }
  1036.    
  1037.                                 if(component.Opportunity__c != null && component.Opportunity__r.CloseDate != null && newSoldServiceComponent.Estimated_Delivery_Date__c == null) {
  1038.                                     Decimal leadTime = component.Lead_Time__c == null ? 0 : component.Lead_Time__c;
  1039.                                     newSoldServiceComponent.Estimated_Delivery_Date__c = component.Opportunity__r.CloseDate.addDays(leadTime.intValue());
  1040.                                 }
  1041.                                
  1042.                                 if(component.Item_Action__c == ACTION_RENEWAL) {
  1043.                                     newSoldServiceComponent.Estimated_Delivery_Date__c = null;
  1044.                                 }
  1045.                                
  1046.                                 if(component.Item_Action__c == ACTION_CHANGE) {
  1047.                                     newSoldServiceComponent.Billing_Commence_Date__c = null;
  1048.                                 }
  1049.                                
  1050.                                 /* generating upsert key */
  1051.                                 String h2 = EncodingUtil.ConvertTohex(Crypto.GenerateAESKey(128));
  1052.                                 String componentUpsertKey = h2.substring(0,8)+ '-' + h2.substring(8,12) + '-' + h2.substring(12,16) + '-' + h2.substring(16,20) + '-' + h2.substring(20);
  1053.                        
  1054.                                 newSoldServiceComponent.Upsert_Key__c = componentUpsertKey;
  1055.                                 quoteItemId2SoldServiceExternalId.put(component.Id, newSoldServiceComponent.Upsert_Key__c);
  1056.                                
  1057.                                 /* handling dual link data */
  1058.                                 if(String.isNotBlank(dualLinkReferenceComponent) && String.isNotBlank(dualLinkFieldComponent)) {
  1059.                                     soldServiceDualLinkReference.put(newSoldServiceComponent.Upsert_Key__c, dualLinkReferenceComponent);
  1060.                                     soldServiceDualLinkField.put(newSoldServiceComponent.Upsert_Key__c, dualLinkFieldComponent);
  1061.                                 }
  1062.                                
  1063.                                 /* handling A / B end data */
  1064.                                 if (!String.isBlank(component.A_End_ID__c)) {
  1065.                                     soldServiceAEndReference.put(componentUpsertKey, component.A_End_ID__c);
  1066.                                 }
  1067.  
  1068.                                 if (!String.isBlank(component.B_End_ID__c)) {
  1069.                                     soldServiceBEndReference.put(componentUpsertKey, component.B_End_ID__c);
  1070.                                 }
  1071.  
  1072.                                 if(newSoldServiceComponent.A_Port__c != null && component.A_Port_Option__c == 'New Port'){
  1073.                                     portIds.add(newSoldServiceComponent.A_Port__c);
  1074.                                 }
  1075.                                 if(newSoldServiceComponent.B_Port__c != null && component.B_Port_Option__c == 'New Port'){
  1076.                                     portIds.add(newSoldServiceComponent.B_Port__c);
  1077.                                 }
  1078.                                
  1079.                                 Date maxTPSDateComponent;
  1080.                                
  1081.                                 if(component.X3rd_Party_Items__r != null) {
  1082.  
  1083.                                     Map<Id, Id> tpiToParent = new Map<Id, Id>();
  1084.                                     Map<Id, String> tpiIdToTPSExternalId = new Map<Id, String>();
  1085.                                     List<X3rd_Party_Services__c> tpsToParentUpdate = new List<X3rd_Party_Services__c>();
  1086.  
  1087.                                     for(X3rd_Party_Item__c tpi : component.X3rd_Party_Items__r){
  1088.                                         if(tpi.Chosen__c){
  1089.                                             X3rd_Party_Services__c tps;
  1090.                                             if(tpi.TPI_Order_Type__c == TPI_ORDER_TYPE_DISMANTLE && tpi.Existing_X3rd_Party_Service__c != null) {
  1091.                                                 tps = new X3rd_Party_Services__c(Id = tpi.Existing_X3rd_Party_Service__c);
  1092.                                                 tps.Status__c = TPS_STATUS_DISMANTLE;
  1093.                                                 tps.Date_for_Dismantle__c = product.Date_Expected_Delivery__c == null ? component.Date_Expected_Delivery__c : product.Date_Expected_Delivery__c;
  1094.                                                 tps.Dismantle_Request_Received__c = component.Opportunity__r.CloseDate;
  1095.                                                 thirdPartyServicesToUpsert2.put(tps.Id, tps);
  1096.                                             } else if(tpi.TPI_Order_Type__c != TPI_ORDER_TYPE_DISMANTLE) {
  1097.                                                 tps = new X3rd_Party_Services__c();
  1098.                                                 tps.Status__c = ApplicationConstant.TPS_STATUS_POREQUIRED;
  1099.                                                 newSoldServiceComponent.Minimum_Status_TPS__c = tps.Status__c;
  1100.                                                 if(ApplicationConstant.TPI_PRIMARY_GENERIC_SUPPLIER_PRODUCT_TSIC_BACKHAUL.equalsIgnoreCase(tpi.Primary_Generic_Supplier_Product__c)
  1101.                                                 && String.isNotBlank(tpi.Supplier_Account_Name__c) && tpi.Supplier_Account_Name__c.containsIgnoreCase(ApplicationConstant.COMPANY_NAME)){
  1102.                                                     tps.Status__c = ApplicationConstant.TPS_STATUS_LIVE;
  1103.                                                     tps.Supplier_Service_Reference__c = ApplicationConstant.COMPANY_NAME;
  1104.                                                 }
  1105.                                            
  1106.                                                 //tps.Name = 'TPS';
  1107.                                                 tps.Name = codes.generateCode(system.label.CRM_THIRD_PARTY_SERVICE);
  1108.                                                 tps.Sold_Service__r = new Sold_Service__c(Upsert_Key__c = newSoldServiceComponent.Upsert_Key__c);
  1109.                                                 tps.Supporting_Sold_Service__c  = tpi.Supporting_Sold_Service__c;
  1110.                                                 tps.Port__c = tpi.Port__c;
  1111.                                                
  1112.                                                 for (String f : tpsFieldMap.keySet()) {
  1113.                                                     tps.put(tpsFieldMap.get(f), tpi.get(f));
  1114.                                                 }
  1115.                                                
  1116.                                                 String h4 = EncodingUtil.ConvertTohex(Crypto.GenerateAESKey(128));
  1117.                                                 String tpsUpsertKey = h4.substring(0,8)+ '-' + h4.substring(8,12) + '-' + h4.substring(12,16) + '-' + h4.substring(16,20) + '-' + h4.substring(20);
  1118.                                                 tps.x3ParSerUID__c = tpsUpsertKey;
  1119.                            
  1120.                                                 if(tpi.Existing_X3rd_Party_Service__c != null) {
  1121.                                                     tps.Replaced_TPS__c = tpi.Existing_X3rd_Party_Service__c;
  1122.                                                     X3rd_Party_Services__c oldTPS = new X3rd_Party_Services__c(Id = tpi.Existing_X3rd_Party_Service__c);
  1123.                                                     oldTPS.TPS_replaced_by__r = new X3rd_Party_Services__c(x3ParSerUID__c = tpsUpsertKey);
  1124.                                                     oldTPS.Status__c = TPS_STATUS_REPLACED;
  1125.                                                     if(component.Item_Action__c == ACTION_RENEWAL) {
  1126.                                                         /* moving TOS under new sold service for renewal */
  1127.                                                         oldTPS.Sold_Service__r = new Sold_Service__c(Upsert_Key__c = newSoldServiceComponent.Upsert_Key__c);
  1128.                                                     }
  1129.                                                     thirdPartyServicesToUpsert2.put(oldTPS.Id, oldTPS);
  1130.                                                 }
  1131.                                                
  1132.                                                 Date maxDate;
  1133.                                                
  1134.                                                 if(tps.Forecasted_Delivery_Date__c != null){
  1135.                                                     maxDate = tps.Forecasted_Delivery_Date__c.date();
  1136.                                                 }
  1137.                                    
  1138.                                                 if(tps.Committed_Delivery_Date__c != null){
  1139.                                                     maxDate = tps.Committed_Delivery_Date__c.date();
  1140.                                                 }
  1141.                                    
  1142.                                                 if(tps.Revised_Delivery_Date__c != null){
  1143.                                                     maxDate = tps.Revised_Delivery_Date__c.date();
  1144.                                                 }
  1145.                                                
  1146.                                                 if(maxDate != null) {
  1147.                                                     if(maxTPSDateComponent == null || maxTPSDateComponent < maxDate) {
  1148.                                                         maxTPSDateComponent = maxDate;
  1149.                                                     }
  1150.                                                 }
  1151.                                                
  1152.                                                 thirdPartyServicesToUpsert.add(tps);
  1153.                                                
  1154.                                                 if(tpi.Parent__c != null && String.isNotEmpty(tpi.Parent__r.Upsert_Key__c)) {
  1155.                                                     tpiToParent.put(tpi.Id, tpi.Parent__c);
  1156.                                                     tpsToParentUpdate.add(tps);
  1157.                                                 }
  1158.                                                 tpiIdToTPSExternalId.put(tpi.Id, tps.x3ParSerUID__c);  
  1159.                                                
  1160.                                                 if(!tpisAlreadyAdded.contains(tpi.Id)) {
  1161.                                                     tpi.RecordTypeId = tpiReadOnlyRecordType;
  1162.                                                     thirdPartyItemsToUpdate.add(tpi);
  1163.                                                     tpisAlreadyAdded.add(tpi.Id);
  1164.                                                 }
  1165.    
  1166.                                                 if (tpi.Secondary_Supplier_Product__c == 'NNI') {
  1167.                                                     newSoldServiceComponent.NNI_Used__c = true;
  1168.                                                 }
  1169.    
  1170.                                                 if (tpi.Secondary_Supplier_Product__c == 'CPE' || tpi.Secondary_Supplier_Product__c == 'NID') {
  1171.                                                     newSoldServiceComponent.Includes_CPE__c = true;
  1172.                                                 }
  1173.                                             }
  1174.                                         }
  1175.                                     }
  1176.                                    
  1177.                                     for(X3rd_Party_Services__c tps : tpsToParentUpdate) {
  1178.                                         if(tpiToParent.keySet().contains(tps.Source_TPI_No__c)) {
  1179.                                             if(tpiIdToTPSExternalId.get(tpiToParent.get(tps.Source_TPI_No__c)) != null) {
  1180.                                                 X3rd_Party_Services__c tpsParent = new X3rd_Party_Services__c(x3ParSerUID__c = tps.x3ParSerUID__c);
  1181.                                                 tpsParent.Parent__r = new X3rd_Party_Services__c(x3ParSerUID__c = tpiIdToTPSExternalId.get(tpiToParent.get(tps.Source_TPI_No__c)));
  1182.                                                 thirdPartyServicesToUpsertParent.add(tpsParent);
  1183.                                             }
  1184.                                         }
  1185.                                     }
  1186.                                 }
  1187.  
  1188.                                 if(maxTPSDateComponent != null) newSoldServiceComponent.Maximum_RFS_Date_TPS__c = maxTPSDateComponent;
  1189.                                
  1190.                                 soldServiceComponentsToUpsert.add(newSoldServiceComponent);
  1191.  
  1192.                                 /* adding charges if appropriate attribute type found */
  1193.                                 for(CPQ_QuoteItemAttribute__c attr : component.QuoteItemAttributes__r) {
  1194.                                     if(attr.Type__c == CPQ_ATR01_Manager.ATR_TYPE_CHARGE) {
  1195.                                         if(String.isNotEmpty(attr.Value_Text_Long__c)){
  1196.                                             List<CPQ_Charge__c> deserializedCharges = (List<CPQ_Charge__c>)JSON.deserialize(attr.Value_Text_Long__c, List<CPQ_Charge__c>.class);
  1197.                                             for(CPQ_Charge__c charge : deserializedCharges){
  1198.                                                 CPQ_Charge__c newCharge;
  1199.                                                 if(charge.Id != null) {
  1200.                                                      newCharge = new CPQ_Charge__c(Id = charge.Id);
  1201.                                                 } else {
  1202.                                                     newCharge = new CPQ_Charge__c();
  1203.                                                 }
  1204.                                                 cloneObject(charge, newCharge, 'CPQ_Charge__c');
  1205.                                                 newCharge.Attribute__c = attr.Attribute__c;
  1206.                                                 newCharge.Quote__c = component.Quote__c;
  1207.                                                 newCharge.Quote_Item__c = component.Id;
  1208.                                                 newCharge.Sold_Service__r = new Sold_Service__c(Upsert_Key__c = newSoldServiceComponent.Upsert_Key__c);
  1209.                                                 chargesToUpsert.add(newCharge);
  1210.                                             }
  1211.                                         }
  1212.                                     }
  1213.                                 }
  1214.                                
  1215.                                 /* Handling port change requests if applicable */
  1216.                                 if(component.Port_Change_Requests__r != null) {
  1217.                                     for(Port_Change_Request__c pcr : component.Port_Change_Requests__r) {
  1218.                                         if(pcr.Port__c == component.A_Port__c && component.A_Port_Option__c == 'Existing Port') {
  1219.                                             newSoldServiceComponent.A_Port_in_Change__c = true;
  1220.                                         }
  1221.                                         if(pcr.Port__c == component.B_Port__c && component.B_Port_Option__c == 'Existing Port') {
  1222.                                             newSoldServiceComponent.B_Port_in_Change__c = true;
  1223.                                         }
  1224.                                        
  1225.                                         Port_Change_Request__c pcrToUpsert = new Port_Change_Request__c(Id = pcr.Id);
  1226.                                         pcrToUpsert.Sold_Service__r = new Sold_Service__c(Upsert_Key__c = newSoldServiceComponent.Upsert_Key__c);
  1227.                                         pcrToUpsert.Stage__c = STAGE_NEW;
  1228.                                         portCRsToUpsert.put(pcr.Id, pcrToUpsert);
  1229.                                     }
  1230.                                 }
  1231.                             }
  1232.                         }
  1233.                     }
  1234.                 }
  1235.             }
  1236.         }
  1237.  
  1238.         upsert portsToCreate;
  1239.         upsert soldServiceProductsToUpsert;
  1240.         upsert soldServiceComponentsToUpsert;
  1241.  
  1242.         sendEmailNotyficationAfterCreatingSoldService(opportunityId);
  1243.        
  1244.         /* build map of Upsert Key to Id */
  1245.         Map<String, Id> sServicesIdMap = new Map<String, Id>();
  1246.         for (Sold_Service__c svc : soldServiceProductsToUpsert) {
  1247.             sServicesIdMap.put(svc.Upsert_Key__c, svc.Id);
  1248.             result.quoteItemToSoldService.put(result.upsertKeyToQuoteItem.get(svc.Upsert_Key__c), svc.Id);
  1249.         }
  1250.         for (Sold_Service__c svc : soldServiceComponentsToUpsert) {
  1251.             sServicesIdMap.put(svc.Upsert_Key__c, svc.Id);
  1252.         }
  1253.        
  1254.         /* replace port name with generated numbers */
  1255.         if(!portIds.isEmpty()) {
  1256.             List<Port__c> portsToUpdate = new List<Port__c>();
  1257.            
  1258.             for(Port__c p : [select Id, Name from Port__c where Id in :portIds or TECH_External_ID__c in :portExternalIds]){
  1259.                 if(p.Name.startsWithIgnoreCase(PORT_PREFIX)) {
  1260.                     p.Name = codes.generateCode(system.label.CRM_COMPONENT);
  1261.                     p.Stage__c = STAGE_NEW;
  1262.                     portsToUpdate.add(p);
  1263.                 }
  1264.             }
  1265.            
  1266.             if(!portsToUpdate.isEmpty()) update portsToUpdate;
  1267.         }
  1268.        
  1269.         codes.updateValues();
  1270.  
  1271.         CPQ_Utils04_RequestStateCls.setOn('TPS_NUMBERS_ASSIGNED');
  1272.         upsert thirdPartyServicesToUpsert;
  1273.         upsert thirdPartyServicesToUpsert2.values();
  1274.         CPQ_Utils04_RequestStateCls.setOff('TPS_NUMBERS_ASSIGNED');
  1275.        
  1276.         /*
  1277.         List<X3rd_Party_Services__c> tpsesToUpsert = new List<X3rd_Party_Services__c>();
  1278.         tpsesToUpsert.addAll(thirdPartyServicesToUpsert);
  1279.         tpsesToUpsert.addAll(thirdPartyServicesToUpsert2);
  1280.         upsert tpsesToUpsert;
  1281.         */
  1282.        
  1283.         upsert thirdPartyServicesToUpsertParent x3ParSerUID__c;
  1284.         update thirdPartyItemsToUpdate;
  1285.         upsert chargesToUpsert;
  1286.        
  1287.         upsert portCRsToUpsert.values();
  1288.  
  1289.         List<Sold_Service__c> sServices = new List<Sold_Service__c>();
  1290.         sServices.addAll(soldServiceProductsToUpsert);
  1291.         sServices.addAll(soldServiceComponentsToUpsert);
  1292.        
  1293.         List<SoldService_Contact_Junction__c> soldServiceContacts = initContacts(sServices, opportunityId);
  1294.         if(soldServiceContacts != null && !soldServiceContacts.isEmpty()) insert soldServiceContacts;
  1295.        
  1296.         createChangeRequestAndLineItems(sServices, opportunityId);
  1297.        
  1298.         /* process dual link data */
  1299.         if(!soldServiceDualLinkReference.isEmpty()) {
  1300.             List<Sold_Service__c> dualLinkServices = new List<Sold_Service__c>();
  1301.             for(String upsertKey : soldServiceDualLinkReference.keySet()){
  1302.                 if(quoteItemId2SoldServiceExternalId.get(soldServiceDualLinkReference.get(upsertKey)) != null){
  1303.                     Sold_Service__c sserv = new Sold_Service__c(Upsert_Key__c = upsertKey);
  1304.                     String fieldValue = '';
  1305.                     for(Sold_Service__c s : sServices) {
  1306.                         if(s.Upsert_Key__c == quoteItemId2SoldServiceExternalId.get(soldServiceDualLinkReference.get(upsertKey))) {
  1307.                             fieldValue = s.Id;
  1308.                             break;
  1309.                         }
  1310.                     }
  1311.                     CPQ_PRI01_Manager.setFieldValueFromString(sserv, soldServiceDualLinkField.get(upsertKey), fieldValue, globalDescribe);
  1312.                     dualLinkServices.add(sserv);
  1313.                 }
  1314.             }
  1315.             upsert dualLinkServices Upsert_Key__c;
  1316.         }
  1317.  
  1318.         /* process a/b end data - reference to quote item / sold service should be put into A_End__c, B_End__c fields on quote item */
  1319.         Map<String, Sold_Service__c> soldServiceEndReferenceToUpdateMap = new Map<String, Sold_Service__c>();
  1320.         if (!soldServiceAEndReference.isEmpty()) {
  1321.             for(String upsertKey : soldServiceAEndReference.keySet()){
  1322.                 Sold_Service__c sserv = new Sold_Service__c(Upsert_Key__c = upsertKey);
  1323.                 if (soldServiceAEndReference.get(upsertKey).startsWith(CPQ_QuoteItem__c.sObjectType.getDescribe().getKeyPrefix())) {
  1324.                     sserv.A_End__c = sServicesIdMap.get(quoteItemId2SoldServiceExternalId.get(soldServiceAEndReference.get(upsertKey)));
  1325.                 } else if (soldServiceAEndReference.get(upsertKey).startsWith(Sold_Service__c.sObjectType.getDescribe().getKeyPrefix())) {
  1326.                     sserv.A_End__c = soldServiceAEndReference.get(upsertKey);
  1327.                 }
  1328.                 soldServiceEndReferenceToUpdateMap.put(upsertKey, sserv);
  1329.             }
  1330.         }
  1331.  
  1332.         if (!soldServiceBEndReference.isEmpty()) {
  1333.             for(String upsertKey : soldServiceBEndReference.keySet()){
  1334.                 Sold_Service__c sserv = (soldServiceEndReferenceToUpdateMap.get(upsertKey) == null ? new Sold_Service__c(Upsert_Key__c = upsertKey) : soldServiceEndReferenceToUpdateMap.get(upsertKey));
  1335.                 if (soldServiceBEndReference.get(upsertKey).startsWith(CPQ_QuoteItem__c.sObjectType.getDescribe().getKeyPrefix())) {
  1336.                     sserv.B_End__c = sServicesIdMap.get(quoteItemId2SoldServiceExternalId.get(soldServiceBEndReference.get(upsertKey)));
  1337.                 } else if (soldServiceBEndReference.get(upsertKey).startsWith(Sold_Service__c.sObjectType.getDescribe().getKeyPrefix())) {
  1338.                     sserv.B_End__c = soldServiceBEndReference.get(upsertKey);
  1339.                 }
  1340.                 soldServiceEndReferenceToUpdateMap.put(upsertKey, sserv);
  1341.             }
  1342.         }
  1343.        
  1344.         if (!soldServiceEndReferenceToUpdateMap.isEmpty()) {
  1345.             upsert soldServiceEndReferenceToUpdateMap.values() Upsert_Key__c;
  1346.         }
  1347.        
  1348.         System.debug('@@ END CLASS: CPQ_PRD04_SoldServiceMappingHlpr METHOD: createSoldServices');
  1349.         return result;
  1350.     }
  1351.  
  1352.     //Email Message Automation Step 1
  1353.     @future
  1354.     public static void sendEmailNotyficationAfterCreatingSoldService(Id opportunityId) {
  1355.  
  1356.         System.debug('@@ START CLASS: CPQ_PRD04_SoldServiceMappingHlpr METHOD: sendEmailNotyficationAfterCreatingSoldService');
  1357.  
  1358.         Opportunity opp = [Select id,
  1359.                                   OwnerId,
  1360.                                   Opportunity_Business_Line__c,
  1361.                                   Owner.Email,
  1362.                                   Owner.Name,
  1363.                                   Commercial_Contact__r.Email,
  1364.                                   Commercial_Contact__c,
  1365.                                   (SELECT Id,
  1366.                                           Item_Action__c
  1367.                                         from Sold_Services__r)
  1368.                                   from Opportunity where  Id = :opportunityId
  1369.                                   ];
  1370.         Boolean actionDismante =false;
  1371.  
  1372.         for(Sold_Service__c ssList : opp.Sold_Services__r) {
  1373.             if(ssList.Item_Action__c == ACTION_DISMANTLE){
  1374.                 actionDismante = true;
  1375.             }
  1376.         }
  1377.  
  1378.         if (opp.Opportunity_Business_Line__c !='Internal Orders' && actionDismante==false && !opp.Sold_Services__r.isEmpty()) {
  1379.  
  1380.             String FOLDER_AUTOMATION = 'D&I Delivery Automation';
  1381.  
  1382.             String mainString;
  1383.             String emailBody;
  1384.             String emailTable = '';
  1385.             Id contactId;
  1386.             Boolean isMoreThanOnePort = false;
  1387.             List<String> mailAdresses = new List<String>();
  1388.             List<Sold_Service__c> parentSoldServiceList = new List<Sold_Service__c>();
  1389.             List<Sold_Service__c> sortedSoldServiceList = new List<Sold_Service__c>();
  1390.  
  1391.             List<String> ccAddresses = new List<String>();
  1392.             Set<String> ssSet = new Set<String>();
  1393.             Set<String> ccAddressesSet = new Set<String>();
  1394.             EmailTemplate templateBody;
  1395.             EmailTemplate templateTable;
  1396.  
  1397.             DelComSettings__c temNames = DelComSettings__c.getInstance();
  1398.             System.debug('@@ SS1 Body Loading' + temNames);
  1399.             List<Sold_Service__c> soldServiceList = [SELECT Id,
  1400.                                                             Opp_Link__c,
  1401.                                                             A_Port__c,
  1402.                                                             B_Location__c,
  1403.                                                             Delivery_Coordinator__r.Email,
  1404.                                                             (Select id,Contact__c,Contact__r.Email from SoldService_Contact_Junctions__r where Name = 'Delivery Contact'),
  1405.                                                             B_Port__c,
  1406.                                                             CRM_Parent_Sold_Service__c,
  1407.                                                             Opp_Link__r.Commercial_Contact__c,
  1408.                                                             Name, CRM_Account__c,
  1409.                                                             Type_of_Service__c,
  1410.                                                             RFS_Date__c,
  1411.                                                             Item_Name__c,
  1412.                                                             Stage__c,
  1413.                                                             Status__c
  1414.                                                             from Sold_Service__c where Opp_Link__c = :opportunityId
  1415.                                                             ];
  1416.  
  1417.             for (Sold_Service__c ss : soldServiceList) {
  1418.  
  1419.                 List<SoldService_Contact_Junction__c> ssJun = ss.SoldService_Contact_Junctions__r;
  1420.  
  1421.                 for(SoldService_Contact_Junction__c ssJunCon : ssJun)
  1422.                     {
  1423.                          if (ssJunCon.Contact__r.Email != null && ssJunCon.Contact__c != contactId) {
  1424.                             ccAddressesSet.add(ssJunCon.Contact__r.Email);
  1425.                        }
  1426.                     }
  1427.                
  1428.  
  1429.                 if (ss.B_Port__c != null || ss.B_Location__c != null) {
  1430.                     isMoreThanOnePort = true;
  1431.                 }
  1432.                 if(ss.CRM_Parent_Sold_Service__c == null){
  1433.                     parentSoldServiceList.add(ss);
  1434.                 }
  1435.             }
  1436.  
  1437.             mailAdresses.add(opp.Commercial_Contact__r.Email);
  1438.             ccAddresses.addAll(ccAddressesSet);
  1439.             List<EmailTemplate> templates = [select Id, Name, Subject, Folder.Name , HtmlValue from EmailTemplate where Folder.Name = : FOLDER_AUTOMATION];
  1440.  
  1441.             for (EmailTemplate et : templates) {
  1442.                 if (isMoreThanOnePort) {
  1443.                     if (et.Name.contains(temNames.Step_1_with_A_B_Table__c)) {
  1444.                         templateTable = et;
  1445.                     }
  1446.                     if (et.Name.contains(temNames.Step_1_with_A_B__c)) {
  1447.                         templateBody = et;
  1448.                     }
  1449.  
  1450.                 } else {
  1451.                     if (et.Name.contains(temNames.Step_1_with_A_only_Table__c)) {
  1452.                         templateTable = et;
  1453.                     }
  1454.                     if (et.Name.contains(temNames.Step_1_with_A_only__c)) {
  1455.                         templateBody = et;
  1456.                     }
  1457.                 }
  1458.             }
  1459.  
  1460.             List<String> mailBodies = loadEmailTable(templateTable, soldServiceList);
  1461.             Integer cursor = 0;
  1462.             for (String mailBody : mailBodies) {
  1463.                 String rowCss = '<tr height=\'30px\' style=\'background-color: #FFFFFF; margin: 0px; padding: 0px;\' id="templateBody">';
  1464.                 if (Math.mod(cursor, 2) == 0) {
  1465.                     rowCss = '<tr height=\'30px\' style=\'background-color: #f2f2f2; margin: 0px; padding: 0px;\'>';
  1466.                 }
  1467.                 emailTable += rowCss + mailBody + '</tr>';
  1468.                 cursor++;
  1469.             }
  1470.             System.debug('@@ SS1 emailBody Loading' + emailTable);
  1471.  
  1472.             emailBody = loadEmailBody(templateBody, opportunityId , opp.Commercial_Contact__c);
  1473.  
  1474.             System.debug('@@ SS1 emailBody Loading ' + emailBody);
  1475.  
  1476.             mainString = emailBody.substring(0, emailBody.indexOf('<tr id="splitCursor"></tr>'))  + emailTable +  emailBody.substring(emailBody.indexOf('<tr id="splitCursor"></tr>'), emailBody.length());
  1477.  
  1478.             List<Messaging.SingleEmailMessage> mails = new List<Messaging.SingleEmailMessage>();
  1479.             Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
  1480.  
  1481.             mail.setHtmlBody(mainString);
  1482.             mail.setWhatId(opportunityId);
  1483.             mail.setToAddresses(mailAdresses);
  1484.             if (!ccAddressesSet.isEmpty() && ccAddressesSet != null) {
  1485.                 mail.setCcAddresses(ccAddresses);
  1486.             }
  1487.             mail.setTargetObjectId(opp.Commercial_Contact__c);
  1488.             mail.setSubject(templateBody.Subject);
  1489.             mail.setSaveAsActivity(true);
  1490.             //mail.setReplyTo(opp.Owner.Email);
  1491.  
  1492.  
  1493.             mails.add(mail);
  1494.  
  1495.             try {
  1496.                 Messaging.sendEmail(mails);
  1497.  
  1498.             } catch (Exception e) {
  1499.                 System.debug('Attachment insert failed. Details: ' + e);
  1500.             }
  1501.  
  1502.             System.debug('@@ END CLASS: CPQ_PRD04_SoldServiceMappingHlpr METHOD: sendEmailNotyficationAfterCreatingSoldService');
  1503.         }
  1504.  
  1505.     }
  1506.     //Email Template Body Loading
  1507.     public static String loadEmailBody(EmailTemplate emailTemplate , Id objectId , Id conId) {
  1508.         String result = '';
  1509.         Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
  1510.  
  1511.         mail.setWhatId(objectId);
  1512.         if (emailTemplate != null) {
  1513.             mail.setTemplateId(emailTemplate.Id);
  1514.         } else {
  1515.             mail.setHtmlBody('<p>test</p>');
  1516.         }
  1517.         mail.setUseSignature(false);
  1518.         mail.setTargetObjectId(conId);
  1519.  
  1520.         Savepoint sp = Database.setSavepoint();
  1521.         Messaging.sendEmail(new Messaging.SingleEmailMessage[] {mail});
  1522.         Database.rollback(sp);
  1523.  
  1524.         result = mail.getHtmlBody();
  1525.  
  1526.         return result;
  1527.     }
  1528.     //Email Template Table Loading
  1529.     public static List<String> loadEmailTable(EmailTemplate emailTemplate, List<Sold_Service__c> soldService) {
  1530.         List<String> result = new List<String>();
  1531.         Set<String> ssSet = new Set<String>();
  1532.         String valueOfField;
  1533.         Pattern pt = Pattern.compile('\\{([^}]*)\\}');
  1534.         Matcher m = pt.matcher(emailTemplate.htmlValue);
  1535.         for (Sold_Service__c listSs : soldService) {
  1536.  
  1537.             ssSet.add(listSs.Id);
  1538.         }
  1539.  
  1540.  
  1541.         Map<String, Schema.SObjectField> sObjMap = Schema.SObjectType.Sold_Service__c.fields.getMap();
  1542.  
  1543.         Schema.SObjectField sField;
  1544.         Schema.DisplayType sFldType;
  1545.  
  1546.  
  1547.         List<String> names = new List<String>();
  1548.         while (m.find()) {
  1549.             names.add(m.group().replace('{!Sold_Service__c.', '').replace('}', ''));
  1550.         }
  1551.         List<Sold_Service__c> sSoldServiceList = Database.query('SELECT ' + String.join(names, ',') + ' FROM Sold_Service__c WHERE Id IN :ssSet');
  1552.  
  1553.         for (Sold_Service__c ss : sSoldServiceList) {
  1554.             String email = '';
  1555.             email = emailTemplate.htmlValue;
  1556.             for (String field : names) {
  1557.                 if (String.valueOf( ss.get(field)) != null) {
  1558.                     if (String.valueOf( ss.get(field)) != null) {
  1559.  
  1560.                         sFldType = sObjMap.get(field.toLowerCase()).getDescribe().getType();
  1561.  
  1562.                         if (sFldType == Schema.DisplayType.DateTime) {
  1563.                             valueOfField = String.valueOf(Datetime.valueOf(String.valueOf(ss.get(field))).date());
  1564.                         } else {
  1565.  
  1566.                             valueOfField = String.valueOf( ss.get(field));
  1567.                         }
  1568.  
  1569.                     } else {
  1570.                         valueOfField = '';
  1571.                     }
  1572.                 } else {
  1573.                     valueOfField = '';
  1574.                 }
  1575.                 email = email.replace('{!Sold_Service__c.' + field + '}', valueOfField);
  1576.             }
  1577.             result.add(email);
  1578.         }
  1579.         return result;
  1580.  
  1581.     }
  1582.  
  1583.     public static void updateQuoteItemFromSoldServiceMain(Set<Id> mergedQuoteItems) {
  1584.         if(mergedQuoteItems.size() <= QUANTITY_SUM_TRESHOLD) {
  1585.             updateQuoteItemFromSoldService(mergedQuoteItems);
  1586.         } else {
  1587.             CPQ_PRD09_UpdateFromSoldServiceBatchHlpr batch = new CPQ_PRD09_UpdateFromSoldServiceBatchHlpr(mergedQuoteItems);
  1588.             Database.executeBatch(batch, BATCH_SIZE);            
  1589.         }
  1590.     }
  1591.  
  1592.     public static void updateQuoteItemFromSoldService(Set<Id> mergedQuoteItems) {
  1593.        
  1594.         System.debug('### updateQuoteItemFromSoldService [' + mergedQuoteItems + ']');
  1595.        
  1596.         String quoteItemsQuery = 'select ' + CPQ_Utils01_SObjectHelperCls.getFieldListForSOQL('CPQ_QuoteItem__c', null, null) + ', RecordType.Name, Product_Definition__r.Product_Group__c, Product_Definition__r.Name, Component_Definition__r.Name, Existing_Object_ID__r.Name ' +
  1597.                     'from CPQ_QuoteItem__c where Id in :mergedQuoteItems and Item_Action__c != \'Add\'';
  1598.        
  1599.         List<CPQ_QuoteItem__c> products = new List<CPQ_QuoteItem__c>();
  1600.         Map<Id, List<CPQ_QuoteItem__c>> components = new Map<Id, List<CPQ_QuoteItem__c>>();
  1601.         Set<Id> productIds = new Set<Id>();
  1602.         Set<Id> componentIds = new Set<Id>();
  1603.         Set<Id> soldServiceIds = new Set<Id>();
  1604.         Set<Id> opportunityLineItemIds = new Set<Id>();
  1605.         Map<Id, CPQ_QuoteItem__c> soldServiceToQuoteItemMap = new Map<Id, CPQ_QuoteItem__c>();
  1606.        
  1607.         List<CPQ_QuoteItem__c> quoteItemsQueryResult = Database.query(quoteItemsQuery);
  1608.         for(CPQ_QuoteItem__c qItem : Database.query(quoteItemsQuery)) {
  1609.             if(qItem.RecordType.Name == RT_QUITEM_PRODUCT) {
  1610.                 products.add(qItem);
  1611.                 productIds.add(qItem.Product_Definition__c);
  1612.                 soldServiceIds.add(qItem.Existing_Object_ID__c);
  1613.                 opportunityLineItemIds.add(qItem.OpportunityLineItem_ID__c);
  1614.                 soldServiceToQuoteItemMap.put(qItem.Existing_Object_ID__c, qItem);
  1615.             } else if(qItem.RecordType.Name == RT_QUITEM_COMPONENT) {
  1616.                 List<CPQ_QuoteItem__c> componentsList = components.get(qItem.Parent_Item__c);
  1617.                 if(componentsList == null) {
  1618.                     componentsList = new List<CPQ_QuoteItem__c>();
  1619.                     components.put(qItem.Parent_Item__c, componentsList);
  1620.                 }
  1621.                 componentsList.add(qItem);
  1622.                 componentIds.add(qItem.Component_Definition__c);
  1623.                 soldServiceIds.add(qItem.Existing_Object_ID__c);
  1624.                 opportunityLineItemIds.add(qItem.OpportunityLineItem_ID__c);
  1625.                 soldServiceToQuoteItemMap.put(qItem.Existing_Object_ID__c, qItem);
  1626.             }
  1627.         }
  1628.  
  1629.        
  1630.         /* loading opportunity products */
  1631.         Map<Id, OpportunityLineItem> opportunityLineItems = new Map<Id, OpportunityLineItem>([select Id, OLI_No__c, CurrencyIsoCode from OpportunityLineItem where Id in :opportunityLineItemIds]);
  1632.         Map<String, Decimal> currencyMap = CurrencyConversation.CurrencyUtilitymethod();
  1633.        
  1634.         /* loading mapping configuration */
  1635.         Map<Id, Map<Id, List<CPQ_Sold_Service_Mapping__c>>> soldServiceMappings_Attributes = new Map<Id, Map<Id, List<CPQ_Sold_Service_Mapping__c>>>();
  1636.         Map<Id, Map<Id, List<CPQ_Sold_Service_Mapping__c>>> soldServiceMappings_Fields = new Map<Id, Map<Id, List<CPQ_Sold_Service_Mapping__c>>>();
  1637.         Map<Id, Map<Id, List<CPQ_Sold_Service_Mapping__c>>> soldServiceMappings_Constants = new Map<Id, Map<Id, List<CPQ_Sold_Service_Mapping__c>>>();
  1638.         Map<Id, Map<Id, List<CPQ_Sold_Service_Mapping__c>>> soldServiceMappings_Numbers = new Map<Id, Map<Id, List<CPQ_Sold_Service_Mapping__c>>>();
  1639.  
  1640.        
  1641.         for(CPQ_Sold_Service_Mapping__c mapping : [select Id, Attribute__c, Component__c, Data_Type__c, Generate_ICC_Number__c, Generate_IC_Number__c, Product__c,
  1642.                         Source_Constant_Value__c, Source_Field_Name__c, Target_Field_OLI__c, Target_Field_Sold_Service__c from CPQ_Sold_Service_Mapping__c where Product__c in :productIds]){
  1643.            
  1644.             Map<Id, List<CPQ_Sold_Service_Mapping__c>> componentMappings = new Map<Id, List<CPQ_Sold_Service_Mapping__c>>();
  1645.            
  1646.             if(mapping.Data_Type__c == CPQ_PRD03_SoldServiceMappingDesignCtrl.TYPE_ATTRIBUTE_MAPPING) {
  1647.                 componentMappings = soldServiceMappings_Attributes.get(mapping.Product__c);
  1648.                 if(componentMappings == null){
  1649.                     componentMappings = new Map<Id, List<CPQ_Sold_Service_Mapping__c>>();
  1650.                     soldServiceMappings_Attributes.put(mapping.Product__c, componentMappings);
  1651.                 }
  1652.             } else if(mapping.Data_Type__c == CPQ_PRD03_SoldServiceMappingDesignCtrl.TYPE_FIELD_MAPPING) {
  1653.                 componentMappings = soldServiceMappings_Fields.get(mapping.Product__c);
  1654.                 if(componentMappings == null){
  1655.                     componentMappings = new Map<Id, List<CPQ_Sold_Service_Mapping__c>>();
  1656.                     soldServiceMappings_Fields.put(mapping.Product__c, componentMappings);
  1657.                 }
  1658.             } else if(mapping.Data_Type__c == CPQ_PRD03_SoldServiceMappingDesignCtrl.TYPE_CONSTANT_MAPPING) {
  1659.                 componentMappings = soldServiceMappings_Constants.get(mapping.Product__c);
  1660.                 if(componentMappings == null){
  1661.                     componentMappings = new Map<Id, List<CPQ_Sold_Service_Mapping__c>>();
  1662.                     soldServiceMappings_Constants.put(mapping.Product__c, componentMappings);
  1663.                 }
  1664.             } else if(mapping.Data_Type__c == CPQ_PRD03_SoldServiceMappingDesignCtrl.TYPE_NUMBER_MAPPING) {
  1665.                 componentMappings = soldServiceMappings_Numbers.get(mapping.Product__c);
  1666.                 if(componentMappings == null){
  1667.                     componentMappings = new Map<Id, List<CPQ_Sold_Service_Mapping__c>>();
  1668.                     soldServiceMappings_Numbers.put(mapping.Product__c, componentMappings);
  1669.                 }
  1670.             }
  1671.            
  1672.             List<CPQ_Sold_Service_Mapping__c> mappings = componentMappings.get(mapping.Component__c);
  1673.             if(mappings == null) {
  1674.                 mappings = new List<CPQ_Sold_Service_Mapping__c>();
  1675.                 componentMappings.put(mapping.Component__c, mappings);
  1676.             }
  1677.            
  1678.             mappings.add(mapping);
  1679.         }
  1680.        
  1681.         // QUERY SOLD SERVICES
  1682.         String soldServiceQuery = 'select ' + CPQ_Utils01_SObjectHelperCls.getFieldListForSOQL('Sold_Service__c', null, null) + ', A_Port__r.Port_Type__c, A_Port__r.Homing_Gateway__c, A_Port__r.Homing_Gateway__r.Continent__c, B_Port__r.Port_Type__c, B_Port__r.Homing_Gateway__c, B_Port__r.Homing_Gateway__r.Continent__c, A_End__r.Name, B_End__r.Name, ' +
  1683.                     '(select ' + CPQ_Utils01_SObjectHelperCls.getFieldListForSOQL('CPQ_Charge__c', null, null) + ' from Charges__r order by Id) ' +
  1684.                     'from Sold_Service__c where Id in :soldServiceIds or (CRM_Parent_Sold_Service__c in :soldServiceIds and Status__c = \'Active\')';
  1685.         Map<Id, Sold_Service__c> soldServices = new Map<Id, Sold_Service__c>((List<Sold_Service__c>)Database.query(soldServiceQuery));
  1686.        
  1687.         // QUERY TPS'ES AND BUILD MAP (ID of SOLD SERVICE WITH LIST OF ALL CHILD TPS'es)
  1688.         //      MASIM - added due to "Aggregate query has too many rows for direct assignment - QC-1944"
  1689.         Map<Id, List<X3rd_Party_Services__c>> thirdPartyServicesMap = new Map<Id, List<X3rd_Party_Services__c>>();
  1690.         Set<Id> soldServicesIds = soldServices.keySet();
  1691.         String thirdPartyServiceQuery = 'select ' + CPQ_Utils01_SObjectHelperCls.getFieldListForSOQL('X3rd_Party_Services__c', null, null) + ', Parent__r.x3ParSerUID__c, Supplier_Account__r.Name ' +
  1692.                                         'from X3rd_Party_Services__c where Sold_Service__c IN :soldServicesIds ORDER BY Sold_Service__c';
  1693.         List<X3rd_Party_Services__c> childThirdPartyServices = new List<X3rd_Party_Services__c>();
  1694.  
  1695.         //IT-6341 - Przemyslaw Tustanowski
  1696.         for (X3rd_Party_Services__c tps : (List<X3rd_Party_Services__c>)Database.query(thirdPartyServiceQuery)) {
  1697.             if(!thirdPartyServicesMap.containsKey(tps.Sold_Service__c)){
  1698.                 thirdPartyServicesMap.put(tps.Sold_Service__c, new List<X3rd_Party_Services__c>());
  1699.             }
  1700.             thirdPartyServicesMap.get(tps.Sold_Service__c).add(tps);
  1701.         }
  1702.  
  1703.         // QUERY ATTRIBUTES
  1704.         String attributeDefinitionQuery = 'select ' + CPQ_Utils01_SObjectHelperCls.getFieldListForSOQL('CPQ_Attribute__c', null, null) + ', ' +
  1705.                     '(select ' + CPQ_Utils01_SObjectHelperCls.getFieldListForSOQL('CPQ_AttributeValue__c', null, null) + ' from AttributeValues__r) ' +
  1706.                     'from CPQ_Attribute__c where Id in (select Attribute__c from CPQ_ProductAttribute__c where Product__c in :productIds or Component__c in :componentIds)';
  1707.         Map<Id, CPQ_Attribute__c> attributeDefinitions = new Map<Id, CPQ_Attribute__c>((List<CPQ_Attribute__c>)Database.query(attributeDefinitionQuery));
  1708.        
  1709.         /* try to find Date of Change within attributes definition */
  1710.         Id dateOfChangeAttributeId = null;
  1711.         Id billingCommDateAttributeId = null;
  1712.         Id contractLengthAttributeId = null;
  1713.         for(CPQ_Attribute__c attr : attributeDefinitions.values()) {
  1714.             if(attr.TECH_Definition_ID__c == ATTRIBUTE_DATE_OF_CHANGE) {
  1715.                 dateOfChangeAttributeId = attr.Id;
  1716.             } else if(attr.TECH_Definition_ID__c == ATTRIBUTE_BILLING_COMM) {
  1717.                 billingCommDateAttributeId = attr.Id;
  1718.             } else if(attr.TECH_Definition_ID__c == ATTRIBUTE_CONTRACT_LENGTH) {
  1719.                 contractLengthAttributeId = attr.Id;
  1720.             }
  1721.         }
  1722.  
  1723.         Map<String, Schema.SObjectType> globalDescribe = Schema.getGlobalDescribe();
  1724.         List<CPQ_QuoteItemAttribute__c> attributesToInsert = new List<CPQ_QuoteItemAttribute__c>();
  1725.         List<CPQ_QuoteItem__c> quoteItemsToUpdate = new List<CPQ_QuoteItem__c>();
  1726.         List<X3rd_Party_Item__c> thirdPartyItemsToInsert = new List<X3rd_Party_Item__c>();
  1727.         List<X3rd_Party_Item__c> thirdPartyItemsToUpsertParent = new List<X3rd_Party_Item__c>();
  1728.        
  1729.         /* initializing fields for TPS -> TPI mapping */
  1730.         Map<String,String> tpsFieldMap = SoldServiceUtility.buildFieldMapping(ApplicationConstant.FIELD_MAPPING_THIRDPARTY);        
  1731.        
  1732.         for(CPQ_QuoteItem__c product : products) {
  1733.             Sold_Service__c productSoldService = soldServices.get(product.Existing_Object_ID__c);
  1734.             if(productSoldService != null) {
  1735.                 //product.Configuration_Loaded__c = true;
  1736.                 product.Description__c = productSoldService.Service_Description__c;
  1737.                
  1738.                 product.OTC_List__c = CPQ_PRI01_Manager.convertCurrencyAmount(productSoldService.List_OTC__c, productSoldService.CurrencyIsoCode, product.CurrencyIsoCode, currencyMap); // productSoldServi.List_OTC__c;
  1739.                 product.OTC__c = CPQ_PRI01_Manager.convertCurrencyAmount(productSoldService.OTC__c, productSoldService.CurrencyIsoCode, product.CurrencyIsoCode, currencyMap); // productSoldService.OTC__c;
  1740.                 product.MRC_List__c = CPQ_PRI01_Manager.convertCurrencyAmount(productSoldService.List_MRC__c, productSoldService.CurrencyIsoCode, product.CurrencyIsoCode, currencyMap); // productSoldService.List_MRC__c;
  1741.                 product.MRC__c = CPQ_PRI01_Manager.convertCurrencyAmount(productSoldService.MRC__c, productSoldService.CurrencyIsoCode, product.CurrencyIsoCode, currencyMap); // productSoldService.MRC__c;
  1742.                 product.MRC_Previous__c = CPQ_PRI01_Manager.convertCurrencyAmount(productSoldService.MRC_Total__c, productSoldService.CurrencyIsoCode, product.CurrencyIsoCode, currencyMap); // productSoldService.MRC_Total__c;
  1743.                 product.MRE_Previous__c = CPQ_PRI01_Manager.convertCurrencyAmount(productSoldService.MRE__c, productSoldService.CurrencyIsoCode, product.CurrencyIsoCode, currencyMap); // productSoldService.MRE__c;
  1744.                 product.Unit_Price_Previous__c = CPQ_PRI01_Manager.convertCurrencyAmount(productSoldService.Recommended_Base_Unit_Price__c, productSoldService.CurrencyIsoCode, product.CurrencyIsoCode, currencyMap); // productSoldService.Unit_Price__c;
  1745.                 product.Previous_CDR__c = productSoldService.Previous_CDR__c; // productSoldService.Previous_CDR__c;
  1746.                
  1747.                 product.A_Location__c = productSoldService.A_Location__c;
  1748.                 product.A_Port__c = productSoldService.A_Port__c;
  1749.                 product.A_Port_Option__c = productSoldService.A_Port_Option__c;
  1750.                 product.A_Port_Type__c = productSoldService.A_Port_Type__c;
  1751.                 product.A_Site__c = productSoldService.A_Site__c;
  1752.                 product.A_Demarc_Site__c = productSoldService.A_Demarc_Site__c;
  1753.                 product.A_Demarc_Type__c = productSoldService.A_Demarc_Type__c;
  1754.                 product.A_Demarc_Comments__c = productSoldService.A_Demarc_Comments__c;
  1755.                 product.A_Floor__c = productSoldService.A_Floor__c;
  1756.                 product.A_Room__c = productSoldService.A_Room__c;
  1757.                 product.A_Rack_Cabinet__c = productSoldService.A_Rack_Cabinet__c;
  1758.                 product.A_Homing_Gateway_Location__c = productSoldService.A_Homing_Gateway_Location__c;
  1759.  
  1760.                 /* Handling A End reference */
  1761.                 if (!String.isBlank(productSoldService.A_End__c)) {
  1762.                     if (soldServiceIds.contains(productSoldService.A_End__c)) {
  1763.                         product.A_End_ID__c = soldServiceToQuoteItemMap.get(productSoldService.A_End__c).Id;
  1764.                         product.A_End_Name__c = soldServiceToQuoteItemMap.get(productSoldService.A_End__c).Name;
  1765.                     } else {
  1766.                         product.A_End_ID__c = productSoldService.A_End__c;
  1767.                         product.A_End_Name__c = productSoldService.A_End__r.Name;
  1768.                     }
  1769.                 }
  1770.  
  1771.                 product.B_Location__c = productSoldService.B_Location__c;
  1772.                 product.B_Port__c = productSoldService.B_Port__c;
  1773.                 product.B_Port_Option__c = productSoldService.B_Port_Option__c;
  1774.                 product.B_Port_Type__c = productSoldService.B_Port_Type__c;
  1775.                 product.B_Site__c = productSoldService.B_Site__c;
  1776.                 product.B_Demarc_Site__c = productSoldService.B_Demarc_Site__c;
  1777.                 product.B_Demarc_Type__c = productSoldService.B_Demarc_Type__c;
  1778.                 product.B_Demarc_Comments__c = productSoldService.B_Demarc_Comments__c;
  1779.                 product.B_Floor__c = productSoldService.B_Floor__c;
  1780.                 product.B_Room__c = productSoldService.B_Room__c;
  1781.                 product.B_Rack_Cabinet__c = productSoldService.B_Rack_Cabinet__c;
  1782.                 product.B_Homing_Gateway_Location__c = productSoldService.B_Homing_Gateway_Location__c;
  1783.                
  1784.                 /* Handling B End reference */
  1785.                 if (!String.isBlank(productSoldService.B_End__c)) {
  1786.                     if (soldServices.containsKey(productSoldService.B_End__c)) {
  1787.                         product.B_End_ID__c = soldServiceToQuoteItemMap.get(productSoldService.B_End__c).Id;
  1788.                         product.B_End_Name__c = soldServiceToQuoteItemMap.get(productSoldService.B_End__c).Name;
  1789.                     } else {
  1790.                         product.B_End_ID__c = productSoldService.B_End__c;
  1791.                         product.B_End_Name__c = productSoldService.B_End__r.Name;
  1792.                     }
  1793.                 }
  1794.  
  1795.                 if(product.Item_Action__c == ACTION_DISMANTLE) {
  1796.                     product.OTC_List__c = 0;
  1797.                     product.OTC__c = 0;
  1798.                     product.MRC_List__c = 0;
  1799.                     product.MRC__c = 0;
  1800.                 } else if(product.Item_Action__c == ACTION_RENEWAL) {
  1801.                     product.OTC_List__c = 0;
  1802.                     product.OTC__c = 0;
  1803.                 }
  1804.                
  1805.                 /* creating delivery date, billing date and contract length attributes */
  1806.                 Boolean dateOfChangeAttributeCreated = false;
  1807.                 Boolean billingCommDateAttributeCreated = false;
  1808.                 Boolean contractLengthAttributeCreated = false;
  1809.                
  1810.                 Date expectedDeliveryDate = product.Date_Expected_Delivery__c;
  1811.                 if(expectedDeliveryDate != null) {
  1812.                     if(dateOfChangeAttributeId != null) {
  1813.                         attributesToInsert.add(createAttribute(product.Id, attributeDefinitions.get(dateOfChangeAttributeId), String.valueOf(expectedDeliveryDate), product.Product_Definition__c, false));
  1814.                         dateOfChangeAttributeCreated = true;
  1815.                     }
  1816.                     if(billingCommDateAttributeId != null) {
  1817.                         attributesToInsert.add(createAttribute(product.Id, attributeDefinitions.get(billingCommDateAttributeId), String.valueOf(expectedDeliveryDate), product.Product_Definition__c, false));
  1818.                         billingCommDateAttributeCreated = true;
  1819.                     }
  1820.                 }
  1821.                
  1822.                 if(product.Contract_Length__c != null && contractLengthAttributeId != null) {
  1823.                     attributesToInsert.add(createAttribute(product.Id, attributeDefinitions.get(contractLengthAttributeId), String.valueOf(product.Contract_Length__c), product.Product_Definition__c, false));
  1824.                     contractLengthAttributeCreated = true;
  1825.                 }
  1826.                
  1827.                 /* assigning attribute values */
  1828.                 if(soldServiceMappings_Attributes.get(product.Product_Definition__c) != null && soldServiceMappings_Attributes.get(product.Product_Definition__c).get(null) != null) {
  1829.                     for(CPQ_Sold_Service_Mapping__c mapping : soldServiceMappings_Attributes.get(product.Product_Definition__c).get(null)) {
  1830.                         if(String.isNotEmpty(mapping.Target_Field_Sold_Service__c)) {
  1831.                             if(attributeDefinitions.get(mapping.Attribute__c) != null && attributeDefinitions.get(mapping.Attribute__c).Type__c != CPQ_ATR01_Manager.ATR_TYPE_CHARGE
  1832.                                 && (mapping.Attribute__c != dateOfChangeAttributeId || dateOfChangeAttributeCreated == false)
  1833.                                 && (mapping.Attribute__c != billingCommDateAttributeId || billingCommDateAttributeCreated == false)
  1834.                                 && (mapping.Attribute__c != contractLengthAttributeId || contractLengthAttributeCreated == false)) {
  1835.                                
  1836.                                 String fieldValue = '';
  1837.                                 if(attributeDefinitions.get(mapping.Attribute__c).TECH_Definition_ID__c == ATTRIBUTE_PORTS_GRID) {
  1838.                                     List<Sold_Service__c> soldServiceComponents = new List<Sold_Service__c>();
  1839.                                     for(Sold_Service__c s : soldServices.values()){
  1840.                                         if(s.CRM_Parent_Sold_Service__c == product.Existing_Object_ID__c){
  1841.                                             soldServiceComponents.add(s);
  1842.                                         }
  1843.                                     }
  1844.                                    
  1845.                                     fieldValue = CalculateGridValueForPorts(attributeDefinitions.get(mapping.Attribute__c).Grid_Layout__c, null, soldServiceComponents);
  1846.                                 } else {
  1847.                                     fieldValue = productSoldService.get(mapping.Target_Field_Sold_Service__c) == null ? '' : String.valueOf(productSoldService.get(mapping.Target_Field_Sold_Service__c));
  1848.                                 }                              
  1849.                                
  1850.                                 if(String.isNotEmpty(fieldValue)){
  1851.                                     attributesToInsert.add(createAttribute(product.Id, attributeDefinitions.get(mapping.Attribute__c), fieldValue, product.Product_Definition__c, false));
  1852.                                 }
  1853.                             }
  1854.                         }
  1855.                     }
  1856.                 }
  1857.                
  1858.                 /* assigning charge attributes */
  1859.                 Map<Id, List<CPQ_Charge__c>> chargesToProcess = new Map<Id, List<CPQ_Charge__c>>();
  1860.                 if(productSoldService.Charges__r != null){
  1861.                     for(CPQ_Charge__c c : productSoldService.Charges__r){
  1862.                         if(c.Attribute__c != null) {
  1863.                             List<CPQ_Charge__c> charges = chargesToProcess.get(c.Attribute__c);
  1864.                             if(charges == null) {
  1865.                                 charges = new List<CPQ_Charge__c>();
  1866.                                 chargesToProcess.put(c.Attribute__c, charges);
  1867.                             }
  1868.                             charges.add(c);
  1869.                         }
  1870.                     }
  1871.                 }
  1872.                
  1873.                 System.debug('### chargesToProcess = ' + chargesToProcess);
  1874.                
  1875.                 if(!chargesToProcess.isEmpty()) {
  1876.                     for(Id attributeId : chargesToProcess.keySet()){
  1877.                         String fieldValue = JSON.serialize(chargesToProcess.get(attributeId));
  1878.                         attributesToInsert.add(createAttribute(product.Id, attributeDefinitions.get(attributeId), fieldValue, product.Product_Definition__c, false));
  1879.                     }
  1880.                 }
  1881.                
  1882.                 /* assigning field values */
  1883.                 if(soldServiceMappings_Fields.get(product.Product_Definition__c) != null && soldServiceMappings_Fields.get(product.Product_Definition__c).get(null) != null) {
  1884.                     for(CPQ_Sold_Service_Mapping__c mapping : soldServiceMappings_Fields.get(product.Product_Definition__c).get(null)) {
  1885.                         if(String.isNotEmpty(mapping.Target_Field_Sold_Service__c)) {
  1886.                             String fieldValue = String.valueOf(productSoldService.get(mapping.Target_Field_Sold_Service__c));
  1887.                             CPQ_PRI01_Manager.setFieldValueFromString(product, mapping.Source_Field_Name__c, fieldValue, globalDescribe);
  1888.                         }
  1889.                     }
  1890.                 }
  1891.  
  1892.                 if(String.isNotEmpty(productSoldService.A_Port_Option__c) && (product.A_Port_Option__c == 'New Port' || product.A_Port_Option__c == 'Port from Opportunity')) {
  1893.                     product.A_Port_Option__c = 'Existing Port';
  1894.                 }
  1895.                 if(String.isNotEmpty(productSoldService.B_Port_Option__c) && (product.B_Port_Option__c == 'New Port' || product.B_Port_Option__c == 'Port from Opportunity')) {
  1896.                     product.B_Port_Option__c = 'Existing Port';
  1897.                 }
  1898.                
  1899.                 if(expectedDeliveryDate != null) {
  1900.                     product.Date_Expected_Delivery__c = expectedDeliveryDate;
  1901.                 }
  1902.                
  1903.                 quoteItemsToUpdate.add(product);
  1904.                
  1905.                 if(product.Item_Action__c != ACTION_DISMANTLE && product.Item_Action__c != ACTION_NO_ACTION && product.Item_Action__c != ACTION_CHANGE) {
  1906.                     if(thirdPartyServicesMap.containsKey(productSoldService.Id)) {
  1907.                        
  1908.                         Map<Id, Id> tpsToParent = new Map<Id, Id>();
  1909.                         Map<Id, String> tpsIdToTPIExternalId = new Map<Id, String>();
  1910.                         List<X3rd_Party_Item__c> tpiToParentUpdate = new List<X3rd_Party_Item__c>();
  1911.                        
  1912.                         for(X3rd_Party_Services__c tps : thirdPartyServicesMap.get(productSoldService.Id)) {
  1913.                            
  1914.                             /* exclude TSIC TPSes & TPS Support for POP Expenses*/
  1915.                             Boolean includeTPS = true;
  1916.                             if((tps.Supplier_Account__c != null && tps.Supplier_Account__r.Name.startsWithIgnoreCase(ApplicationConstant.COMPANY_NAME)) || (tps.Primary_Generic_Supplier_Product__c == TPS_PRIMARY_PROD_SITE)) {
  1917.                                 includeTPS = false;
  1918.                             }
  1919.                            
  1920.                             if(tps.Status__c == '10 Delivered' && includeTPS) {
  1921.                                 X3rd_Party_Item__c tpi = new X3rd_Party_Item__c();
  1922.                                
  1923.                                 for (String f : tpsFieldMap.keySet()) {
  1924.                                     if(f != 'Id' && f != 'CreatedDate') {
  1925.                                         tpi.put(f, tps.get(tpsFieldMap.get(f)));
  1926.                                         System.debug('### Copying data from ' + tpsFieldMap.get(f) + ' (TPS) to ' + f + ' (TPI)');
  1927.                                     }
  1928.                                 }
  1929.                                
  1930.                                 tpi.Chosen__c = true;
  1931.                                 tpi.Existing_X3rd_Party_Service__c = tps.Id;
  1932.                                 tpi.Opportunity__c = product.Opportunity__c;
  1933.                                 tpi.Opportunity_Line_Item__c = product.OpportunityLineItem_ID__c;
  1934.                                 tpi.OLI_No__c = opportunityLineItems.get(product.OpportunityLineItem_ID__c) != null ? opportunityLineItems.get(product.OpportunityLineItem_ID__c).OLI_No__c : '?';
  1935.                                 tpi.Sold_Service__c = product.Existing_Object_ID__c;
  1936.                                 tpi.Quote_Item__c = product.Id;
  1937.                                 tpi.Quantity__c = 1;
  1938.                                 tpi.Port__c = tps.Port__c;
  1939.    
  1940.                                 tpi.Initial_MRE__c = tps.MRE__c;
  1941.                                 //tpi.Initial_OTE_COGS__c = tps.OTE_COGS__c;
  1942.                                 //tpi.Initial_OTE_Capex__c = tps.OTE_Capex__c;
  1943.                                 tpi.Previous_MRE__c = tps.MRE__c;
  1944.    
  1945.                                 tpi.Unit_Initial_MRE_COGS__c = tps.MRE__c;
  1946.                                 tpi.Unit_Initial_OTE_COGS__c = 0;
  1947.                                 tpi.Unit_Initial_OTE_CAPEX__c = 0;
  1948.    
  1949.                                 /* clear values that might have been mapped */
  1950.                                 tpi.Unit_Final_MRE_COGS__c = null;
  1951.                                 tpi.Unit_Final_OTE_COGS__c = null;
  1952.                                 tpi.Unit_Final_OTE_CAPEX__c = null;
  1953.                                 tpi.Final_MRE__c = null;
  1954.                                 tpi.Final_OTE_COGS__c = null;
  1955.                                 tpi.Final_OTE_Capex__c = null;
  1956.                                 tpi.Initial_OTE_COGS__c = 0;
  1957.                                 tpi.Initial_OTE_Capex__c = 0;
  1958.                                
  1959.                                 tpi.Status__c = TPI_STATUS_QUOTE_REQ;
  1960.    
  1961.                                 if(product.Item_Action__c == ACTION_RENEWAL || product.Item_Action__c == ACTION_CEASE) {
  1962.                                     tpi.TPI_Order_Type__c = 'Renew';
  1963.                                 } else {
  1964.                                     tpi.TPI_Order_Type__c = 'Upgrade / Downgrade';
  1965.                                 }
  1966.                                
  1967.                                 if(String.isEmpty(tpi.Item_End_Type__c)) {
  1968.                                     tpi.Item_End_Type__c = 'A';
  1969.                                    
  1970.                                     if(product.B_Port__c != null && tpi.Port__c != null && product.B_Port__c == tpi.Port__c) {
  1971.                                         tpi.Item_End_Type__c = 'B';
  1972.                                     }
  1973.                                 }
  1974.                                
  1975.                                 String h3 = EncodingUtil.ConvertTohex(Crypto.GenerateAESKey(128));
  1976.                                 String tpiUpsertKey = h3.substring(0,8)+ '-' + h3.substring(8,12) + '-' + h3.substring(12,16) + '-' + h3.substring(16,20) + '-' + h3.substring(20);
  1977.                                 tpi.Upsert_Key__c = tpiUpsertKey;
  1978.                                
  1979.                                 if(tps.Parent__c != null && String.isNotEmpty(tps.Parent__r.x3ParSerUID__c)) {
  1980.                                     tpsToParent.put(tps.Id, tps.Parent__c);
  1981.                                     tpiToParentUpdate.add(tpi);
  1982.                                 }
  1983.                                 tpsIdToTPIExternalId.put(tps.Id, tpi.Upsert_Key__c);
  1984.                                
  1985.                                 thirdPartyItemsToInsert.add(tpi);
  1986.                             }
  1987.                         }
  1988.                        
  1989.                         for(X3rd_Party_Item__c tpi : tpiToParentUpdate) {
  1990.                             if(tpsToParent.keySet().contains(tpi.Existing_X3rd_Party_Service__c)) {
  1991.                                 if(tpsIdToTPIExternalId.get(tpsToParent.get(tpi.Existing_X3rd_Party_Service__c)) != null) {
  1992.                                     X3rd_Party_Item__c tpiParent = new X3rd_Party_Item__c(Upsert_Key__c = tpi.Upsert_Key__c);
  1993.                                     tpiParent.Parent__r = new X3rd_Party_Item__c(Upsert_Key__c = tpsIdToTPIExternalId.get(tpsToParent.get(tpi.Existing_X3rd_Party_Service__c)));
  1994.                                     thirdPartyItemsToUpsertParent.add(tpiParent);
  1995.                                 }
  1996.                             }
  1997.                         }
  1998.                     }
  1999.                 }
  2000.             }
  2001.            
  2002.             if(components.get(product.Id) != null) {
  2003.                 for(CPQ_QuoteItem__c component : components.get(product.Id)) {
  2004.                    
  2005.                     Sold_Service__c componentSoldService = soldServices.get(component.Existing_Object_ID__c);
  2006.                    
  2007.                     //component.Configuration_Loaded__c = true;
  2008.                     component.Description__c = componentSoldService.Service_Description__c;
  2009.                    
  2010.                     component.OTC_List__c = CPQ_PRI01_Manager.convertCurrencyAmount(componentSoldService.List_OTC__c, componentSoldService.CurrencyIsoCode, component.CurrencyIsoCode, currencyMap); // componentSoldService.List_OTC__c;
  2011.                     component.OTC__c = CPQ_PRI01_Manager.convertCurrencyAmount(componentSoldService.OTC__c, componentSoldService.CurrencyIsoCode, component.CurrencyIsoCode, currencyMap); // componentSoldService.OTC__c;
  2012.                     component.MRC_List__c = CPQ_PRI01_Manager.convertCurrencyAmount(componentSoldService.List_MRC__c, componentSoldService.CurrencyIsoCode, component.CurrencyIsoCode, currencyMap); // componentSoldService.List_MRC__c;
  2013.                     component.MRC__c = CPQ_PRI01_Manager.convertCurrencyAmount(componentSoldService.MRC__c, componentSoldService.CurrencyIsoCode, component.CurrencyIsoCode, currencyMap); // componentSoldService.MRC__c;
  2014.                     component.MRC_Previous__c = CPQ_PRI01_Manager.convertCurrencyAmount(componentSoldService.MRC_Total__c, componentSoldService.CurrencyIsoCode, component.CurrencyIsoCode, currencyMap); // componentSoldService.MRC__c;
  2015.                     component.MRE_Previous__c = CPQ_PRI01_Manager.convertCurrencyAmount(componentSoldService.MRE__c, componentSoldService.CurrencyIsoCode, component.CurrencyIsoCode, currencyMap); // componentSoldService.MRE__c;
  2016.                     component.Unit_Price_Previous__c = CPQ_PRI01_Manager.convertCurrencyAmount(componentSoldService.Recommended_Base_Unit_Price__c, productSoldService.CurrencyIsoCode, component.CurrencyIsoCode, currencyMap); // componentSoldService.Unit_Price__c;
  2017.                     component.Previous_CDR__c = componentSoldService.Previous_CDR__c; // componentSoldService.Previous_CDR__c;
  2018.                    
  2019.                     component.A_Location__c = componentSoldService.A_Location__c;
  2020.                     component.A_Port__c = componentSoldService.A_Port__c;
  2021.                     component.A_Port_Option__c = componentSoldService.A_Port_Option__c;
  2022.                     component.A_Port_Type__c = componentSoldService.A_Port_Type__c;
  2023.                     component.A_Site__c = componentSoldService.A_Site__c;
  2024.                     component.A_Demarc_Site__c = componentSoldService.A_Demarc_Site__c;
  2025.                     component.A_Demarc_Type__c = componentSoldService.A_Demarc_Type__c;
  2026.                     component.A_Demarc_Comments__c = componentSoldService.A_Demarc_Comments__c;
  2027.                     component.A_Floor__c = componentSoldService.A_Floor__c;
  2028.                     component.A_Room__c = componentSoldService.A_Room__c;
  2029.                     component.A_Rack_Cabinet__c = componentSoldService.A_Rack_Cabinet__c;
  2030.                     component.A_Homing_Gateway_Location__c = componentSoldService.A_Homing_Gateway_Location__c;
  2031.  
  2032.                     /* Handling A End reference */
  2033.                     if (!String.isBlank(componentSoldService.A_End__c)) {
  2034.                         if (soldServices.containsKey(componentSoldService.A_End__c)) {
  2035.                             component.A_End_ID__c = soldServiceToQuoteItemMap.get(componentSoldService.A_End__c).Id;
  2036.                             component.A_End_Name__c = soldServiceToQuoteItemMap.get(componentSoldService.A_End__c).Name;
  2037.                         } else {
  2038.                             component.A_End_ID__c = componentSoldService.A_End__c;
  2039.                             component.A_End_Name__c = componentSoldService.A_End__r.Name;
  2040.                         }
  2041.                     }
  2042.    
  2043.                     component.B_Location__c = componentSoldService.B_Location__c;
  2044.                     component.B_Port__c = componentSoldService.B_Port__c;
  2045.                     component.B_Port_Option__c = componentSoldService.B_Port_Option__c;
  2046.                     component.B_Port_Type__c = componentSoldService.B_Port_Type__c;
  2047.                     component.B_Site__c = componentSoldService.B_Site__c;
  2048.                     component.B_Demarc_Site__c = componentSoldService.B_Demarc_Site__c;
  2049.                     component.B_Demarc_Type__c = componentSoldService.B_Demarc_Type__c;
  2050.                     component.B_Demarc_Comments__c = componentSoldService.B_Demarc_Comments__c;
  2051.                     component.B_Floor__c = componentSoldService.B_Floor__c;
  2052.                     component.B_Room__c = componentSoldService.B_Room__c;
  2053.                     component.B_Rack_Cabinet__c = componentSoldService.B_Rack_Cabinet__c;
  2054.                     component.B_Homing_Gateway_Location__c = componentSoldService.B_Homing_Gateway_Location__c;
  2055.  
  2056.                     /* Handling B End reference */
  2057.                     if (!String.isBlank(componentSoldService.B_End__c)) {
  2058.                         if (soldServices.containsKey(componentSoldService.B_End__c)) {
  2059.                             component.B_End_ID__c = soldServiceToQuoteItemMap.get(componentSoldService.B_End__c).Id;
  2060.                             component.B_End_Name__c = soldServiceToQuoteItemMap.get(componentSoldService.B_End__c).Name;
  2061.                         } else {
  2062.                             component.B_End_ID__c = componentSoldService.B_End__c;
  2063.                             component.B_End_Name__c = componentSoldService.B_End__r.Name;
  2064.                         }
  2065.                     }
  2066.  
  2067.                     if(component.Item_Action__c == ACTION_DISMANTLE) {
  2068.                         component.OTC_List__c = 0;
  2069.                         component.OTC__c = 0;
  2070.                         component.MRC_List__c = 0;
  2071.                         component.MRC__c = 0;
  2072.                     } else if(component.Item_Action__c == ACTION_RENEWAL) {
  2073.                         component.OTC_List__c = 0;
  2074.                         component.OTC__c = 0;
  2075.                     }
  2076.                    
  2077.                     /* creating delivery date, billing date and contract length attributes */
  2078.                     Boolean dateOfChangeAttributeComponentCreated = false;
  2079.                     Boolean billingCommDateAttributeComponentCreated = false;
  2080.                     Boolean contractLengthAttributeComponentCreated = false;
  2081.                    
  2082.                     Date expectedDeliveryDateComponent = component.Date_Expected_Delivery__c;
  2083.                     if(expectedDeliveryDateComponent != null) {
  2084.                         if(dateOfChangeAttributeId != null) {
  2085.                             attributesToInsert.add(createAttribute(component.Id, attributeDefinitions.get(dateOfChangeAttributeId), String.valueOf(expectedDeliveryDateComponent), component.Component_Definition__c, true));
  2086.                             dateOfChangeAttributeComponentCreated = true;
  2087.                         }
  2088.                         if(billingCommDateAttributeId != null) {
  2089.                             attributesToInsert.add(createAttribute(component.Id, attributeDefinitions.get(billingCommDateAttributeId), String.valueOf(expectedDeliveryDateComponent), component.Component_Definition__c, true));
  2090.                             billingCommDateAttributeComponentCreated = true;
  2091.                         }
  2092.                     }
  2093.                    
  2094.                     if(component.Contract_Length__c != null && contractLengthAttributeId != null) {
  2095.                         attributesToInsert.add(createAttribute(component.Id, attributeDefinitions.get(contractLengthAttributeId), String.valueOf(component.Contract_Length__c), component.Component_Definition__c, true));
  2096.                         contractLengthAttributeComponentCreated = true;
  2097.                     }
  2098.                
  2099.                     /* assigning attribute values */
  2100.                     if(soldServiceMappings_Attributes.get(product.Product_Definition__c) != null && soldServiceMappings_Attributes.get(product.Product_Definition__c).get(component.Component_Definition__c) != null) {
  2101.                         for(CPQ_Sold_Service_Mapping__c mapping : soldServiceMappings_Attributes.get(product.Product_Definition__c).get(component.Component_Definition__c)) {
  2102.                             if(String.isNotEmpty(mapping.Target_Field_Sold_Service__c)) {
  2103.                                 if(attributeDefinitions.get(mapping.Attribute__c) != null && attributeDefinitions.get(mapping.Attribute__c).Type__c != CPQ_ATR01_Manager.ATR_TYPE_CHARGE
  2104.                                     && (mapping.Attribute__c != dateOfChangeAttributeId || dateOfChangeAttributeComponentCreated == null)
  2105.                                     && (mapping.Attribute__c != billingCommDateAttributeId || billingCommDateAttributeComponentCreated == null)
  2106.                                     && (mapping.Attribute__c != contractLengthAttributeId || contractLengthAttributeComponentCreated == null)) {
  2107.                                     String fieldValue = componentSoldService.get(mapping.Target_Field_Sold_Service__c) == null ? '' : String.valueOf(componentSoldService.get(mapping.Target_Field_Sold_Service__c));
  2108.                                     if(String.isNotEmpty(fieldValue)){
  2109.                                         attributesToInsert.add(createAttribute(component.Id, attributeDefinitions.get(mapping.Attribute__c), fieldValue, component.Component_Definition__c, true));
  2110.                                     }
  2111.                                 }
  2112.                             }
  2113.                         }
  2114.                     }
  2115.                    
  2116.                     /* assigning charge attributes */
  2117.                     Map<Id, List<CPQ_Charge__c>> chargesToProcess = new Map<Id, List<CPQ_Charge__c>>();
  2118.                     if(componentSoldService.Charges__r != null){
  2119.                         for(CPQ_Charge__c c : componentSoldService.Charges__r){
  2120.                             if(c.Attribute__c != null) {
  2121.                                 List<CPQ_Charge__c> charges = chargesToProcess.get(c.Attribute__c);
  2122.                                 if(charges == null) {
  2123.                                     charges = new List<CPQ_Charge__c>();
  2124.                                     chargesToProcess.put(c.Attribute__c, charges);
  2125.                                 }
  2126.                                 charges.add(c);
  2127.                             }
  2128.                         }
  2129.                     }
  2130.                     if(!chargesToProcess.isEmpty()) {
  2131.                         for(Id attributeId : chargesToProcess.keySet()){
  2132.                             String fieldValue = JSON.serialize(chargesToProcess.get(attributeId));
  2133.                             attributesToInsert.add(createAttribute(component.Id, attributeDefinitions.get(attributeId), fieldValue, component.Product_Definition__c, false));
  2134.                         }
  2135.                     }
  2136.                    
  2137.                     /* assigning field values */
  2138.                     if(soldServiceMappings_Fields.get(product.Product_Definition__c) != null && soldServiceMappings_Fields.get(product.Product_Definition__c).get(null) != null) {
  2139.                         for(CPQ_Sold_Service_Mapping__c mapping : soldServiceMappings_Fields.get(product.Product_Definition__c).get(null)) {
  2140.                             if(String.isNotEmpty(mapping.Target_Field_Sold_Service__c)) {
  2141.                                 String fieldValue = String.valueOf(productSoldService.get(mapping.Target_Field_Sold_Service__c));
  2142.                                 CPQ_PRI01_Manager.setFieldValueFromString(product, mapping.Source_Field_Name__c, fieldValue, globalDescribe);
  2143.                             }
  2144.                         }
  2145.                     }
  2146.  
  2147.                     /* assigning field values */
  2148.                     if(soldServiceMappings_Fields.get(product.Product_Definition__c) != null && soldServiceMappings_Fields.get(product.Product_Definition__c).get(component.Component_Definition__c) != null) {
  2149.                         for(CPQ_Sold_Service_Mapping__c mapping : soldServiceMappings_Fields.get(product.Product_Definition__c).get(component.Component_Definition__c)) {
  2150.                             if(String.isNotEmpty(mapping.Target_Field_Sold_Service__c)) {
  2151.                                 String fieldValue = String.valueOf(componentSoldService.get(mapping.Target_Field_Sold_Service__c));
  2152.                                 CPQ_PRI01_Manager.setFieldValueFromString(component, mapping.Source_Field_Name__c, fieldValue, globalDescribe);
  2153.                             }
  2154.                         }
  2155.                     }
  2156.  
  2157.                     if(String.isNotEmpty(componentSoldService.A_Port_Option__c) && (component.A_Port_Option__c == 'New Port' || component.A_Port_Option__c == 'Port from Opportunity')) {
  2158.                         component.A_Port_Option__c = 'Existing Port';
  2159.                     }
  2160.                     if(String.isNotEmpty(componentSoldService.B_Port_Option__c) && (component.B_Port_Option__c == 'New Port' || component.B_Port_Option__c == 'Port from Opportunity')) {
  2161.                         component.B_Port_Option__c = 'Existing Port';
  2162.                     }
  2163.                    
  2164.                     if(expectedDeliveryDateComponent != null) {
  2165.                         component.Date_Expected_Delivery__c = expectedDeliveryDateComponent;
  2166.                     }
  2167.  
  2168.                     quoteItemsToUpdate.add(component);
  2169.                    
  2170.                     if(component.Item_Action__c != ACTION_DISMANTLE && component.Item_Action__c != ACTION_CHANGE) {
  2171.                         if(thirdPartyServicesMap.containsKey(componentSoldService.Id)) {
  2172.                            
  2173.                             Map<Id, Id> tpsToParent = new Map<Id, Id>();
  2174.                             Map<Id, String> tpsIdToTPIExternalId = new Map<Id, String>();
  2175.                             List<X3rd_Party_Item__c> tpiToParentUpdate = new List<X3rd_Party_Item__c>();
  2176.                        
  2177.                             for(X3rd_Party_Services__c tps : thirdPartyServicesMap.get(componentSoldService.Id)) {
  2178.                                
  2179.                                 /* exclude TSIC TPSes */
  2180.                                 Boolean includeTPS = true;
  2181.                                 if((tps.Supplier_Account__c != null && tps.Supplier_Account__r.Name.startsWithIgnoreCase(ApplicationConstant.COMPANY_NAME)) || (tps.Primary_Generic_Supplier_Product__c == TPS_PRIMARY_PROD_SITE)) {
  2182.                                     includeTPS = false;
  2183.                                 }
  2184.                                
  2185.                                 if(tps.Status__c == '10 Delivered' && includeTPS) {
  2186.                                     X3rd_Party_Item__c tpi = new X3rd_Party_Item__c();
  2187.                                    
  2188.                                     for (String f : tpsFieldMap.keySet()) {
  2189.                                         if(f != 'Id' && f != 'CreatedDate') {
  2190.                                             tpi.put(f, tps.get(tpsFieldMap.get(f)));
  2191.                                             System.debug('### Copying data from ' + tpsFieldMap.get(f) + ' (TPS) to ' + f + ' (TPI)');
  2192.                                         }
  2193.                                     }
  2194.                                    
  2195.                                     tpi.Chosen__c = true;
  2196.                                     tpi.Existing_X3rd_Party_Service__c = tps.Id;
  2197.                                     tpi.Opportunity__c = component.Opportunity__c;
  2198.                                     tpi.Opportunity_Line_Item__c = component.OpportunityLineItem_ID__c;
  2199.                                     tpi.OLI_No__c = opportunityLineItems.get(component.OpportunityLineItem_ID__c) != null ? opportunityLineItems.get(component.OpportunityLineItem_ID__c).OLI_No__c : '?';
  2200.                                     tpi.Sold_Service__c = component.Existing_Object_ID__c;
  2201.                                     tpi.Quote_Item__c = component.Id;
  2202.                                     tpi.Quantity__c = 1;
  2203.                                     tpi.Port__c = tps.Port__c;
  2204.                                    
  2205.                                     tpi.Initial_MRE__c = tps.MRE__c;
  2206.                                     //tpi.Initial_OTE_COGS__c = tps.OTE_COGS__c;
  2207.                                     //tpi.Initial_OTE_Capex__c = tps.OTE_Capex__c;
  2208.                                     tpi.Previous_MRE__c = tps.MRE__c;
  2209.    
  2210.                                     tpi.Unit_Initial_MRE_COGS__c = tps.MRE__c;
  2211.                                     tpi.Unit_Initial_OTE_COGS__c = 0;
  2212.                                     tpi.Unit_Initial_OTE_CAPEX__c = 0;
  2213.    
  2214.                                     /* clear values that might have been mapped */
  2215.                                     tpi.Unit_Final_MRE_COGS__c = null;
  2216.                                     tpi.Unit_Final_OTE_COGS__c = null;
  2217.                                     tpi.Unit_Final_OTE_CAPEX__c = null;
  2218.                                     tpi.Final_MRE__c = null;
  2219.                                     tpi.Final_OTE_COGS__c = null;
  2220.                                     tpi.Final_OTE_Capex__c = null;
  2221.                                     tpi.Initial_OTE_COGS__c = 0;
  2222.                                     tpi.Initial_OTE_Capex__c = 0;
  2223.                                    
  2224.                                     tpi.Status__c = TPI_STATUS_QUOTE_REQ;
  2225.    
  2226.                                     if(component.Item_Action__c == ACTION_RENEWAL || component.Item_Action__c == ACTION_CEASE) {
  2227.                                         tpi.TPI_Order_Type__c = 'Renew';
  2228.                                     } else {
  2229.                                         tpi.TPI_Order_Type__c = 'Upgrade / Downgrade';
  2230.                                     }
  2231.                                    
  2232.                                     if(String.isEmpty(tpi.Item_End_Type__c)) {
  2233.                                         tpi.Item_End_Type__c = 'A';
  2234.                                        
  2235.                                         if(component.B_Port__c != null && tpi.Port__c != null && component.B_Port__c == tpi.Port__c) {
  2236.                                             tpi.Item_End_Type__c = 'B';
  2237.                                         }
  2238.                                     }
  2239.                                    
  2240.                                     String h3 = EncodingUtil.ConvertTohex(Crypto.GenerateAESKey(128));
  2241.                                     String tpiUpsertKey = h3.substring(0,8)+ '-' + h3.substring(8,12) + '-' + h3.substring(12,16) + '-' + h3.substring(16,20) + '-' + h3.substring(20);
  2242.                                     tpi.Upsert_Key__c = tpiUpsertKey;
  2243.                                    
  2244.                                     if(tps.Parent__c != null && String.isNotEmpty(tps.Parent__r.x3ParSerUID__c)) {
  2245.                                         System.debug('### TPS has a parent!');
  2246.                                         tpsToParent.put(tps.Id, tps.Parent__c);
  2247.                                         tpiToParentUpdate.add(tpi);
  2248.                                     }
  2249.                                     tpsIdToTPIExternalId.put(tps.Id, tpi.Upsert_Key__c);
  2250.    
  2251.                                     thirdPartyItemsToInsert.add(tpi);
  2252.                                 }
  2253.                             }
  2254.                            
  2255.                             for(X3rd_Party_Item__c tpi : tpiToParentUpdate) {
  2256.                                 if(tpsToParent.keySet().contains(tpi.Existing_X3rd_Party_Service__c)) {
  2257.                                     if(tpsIdToTPIExternalId.get(tpsToParent.get(tpi.Existing_X3rd_Party_Service__c)) != null) {
  2258.                                         X3rd_Party_Item__c tpiParent = new X3rd_Party_Item__c(Upsert_Key__c = tpi.Upsert_Key__c);
  2259.                                         tpiParent.Parent__r = new X3rd_Party_Item__c(Upsert_Key__c = tpsIdToTPIExternalId.get(tpsToParent.get(tpi.Existing_X3rd_Party_Service__c)));
  2260.                                         thirdPartyItemsToUpsertParent.add(tpiParent);
  2261.                                         System.debug('### Adding tpi to upsert list');
  2262.                                     }
  2263.                                 }
  2264.                             }
  2265.                         }
  2266.                     }
  2267.                 }
  2268.             }
  2269.         }
  2270.  
  2271.         Integer j = 0;
  2272.         Set<Id> skippedQuoteItems = new Set<Id>();
  2273.         while (j < quoteItemsToUpdate.size()) {
  2274.           if(quoteItemsToUpdate.get(j).Configuration_Loaded__c == true) {
  2275.             skippedQuoteItems.add(quoteItemsToUpdate.get(j).Id);
  2276.             quoteItemsToUpdate.remove(j);
  2277.           } else {
  2278.             j++;
  2279.           }
  2280.         }
  2281.         updateQIfromQIAttr(attributesToInsert, quoteItemsToUpdate);
  2282.         update quoteItemsToUpdate;
  2283.         CPQ_Utils04_RequestStateCls.setOn('QLI_SET_CONFIGURATION_DESCRIPTION');
  2284.  
  2285.         // 03/03/2017 - MASIM - QC-1944 - ensure that duplicate attributes are not created
  2286.         List<CPQ_QuoteItemAttribute__c> attributesToUpsert = new List<CPQ_QuoteItemAttribute__c>();
  2287.         for (CPQ_QuoteItemAttribute__c atr : attributesToInsert) {
  2288.             if (!skippedQuoteItems.contains(atr.Quote_Item__c)) {
  2289.                 atr.TECH_Unique_Key__c = atr.Quote_Item__c + '_' + atr.Attribute__c;
  2290.                 attributesToUpsert.add(atr);
  2291.             }
  2292.         }
  2293.         upsert attributesToUpsert TECH_Unique_Key__c;
  2294.  
  2295.         /* disabling trigger setting Upsert_Key__c */
  2296.         CPQ_Utils04_RequestStateCls.setOn('SET_DEFAULTS_TPI');
  2297.         insert thirdPartyItemsToInsert;
  2298.         upsert thirdPartyItemsToUpsertParent Upsert_Key__c;
  2299.  
  2300.         /* A/B End handling - swop relationships */
  2301.  
  2302.  
  2303.     }
  2304.  
  2305.     //---Przemyslaw Tustanowski--
  2306.     //this part of code updates particullar quote items' fields from QIattribute, this is needed before configuration (i.e. to get full description - with banwitdth)  
  2307.     private static void updateQIfromQIAttr(List<CPQ_QuoteItemAttribute__c> attributesToInsert, List<CPQ_QuoteItem__c> quoteItemsToUpdate){
  2308.         Map<String, CPQ_QuoteItem__c> mappedFieldsToUpdate = new Map<String,CPQ_QuoteItem__c>(); // QuoteItem id mapped to new QuoteItem - this is to keep appropierate fields types
  2309.         Map<String, Set<String>> listedFields4QI = new Map<String, Set<String>>(); // Mapped quoteItem Id to list of fields, which will be synced from attribute
  2310.         for(CPQ_QuoteItemAttribute__c attr : attributesToInsert){
  2311.             if(attr.Component_Field_to_Update__c != null || attr.Product_Field_to_Update__c != null){
  2312.                 if(mappedFieldsToUpdate.isEmpty() || !mappedFieldsToUpdate.containsKey(attr.Quote_Item__c)){
  2313.                     mappedFieldsToUpdate.put(attr.Quote_Item__c, new CPQ_QuoteItem__c());
  2314.                     listedFields4QI.put(attr.Quote_Item__c, new Set<String>());
  2315.                 }
  2316.                 if(attr.Component_Field_to_Update__c != null){
  2317.                     listedFields4QI.get(attr.Quote_Item__c).add(attr.Component_Field_to_Update__c);
  2318.                     mappedFieldsToUpdate = findMapElements(mappedFieldsToUpdate, attr.Component_Field_to_Update__c, attr);
  2319.                 }
  2320.                 if(attr.Product_Field_to_Update__c != null){
  2321.                     listedFields4QI.get(attr.Quote_Item__c).add(attr.Product_Field_to_Update__c);
  2322.                     mappedFieldsToUpdate = findMapElements(mappedFieldsToUpdate, attr.Product_Field_to_Update__c, attr);
  2323.                 }                
  2324.             }
  2325.         }
  2326.  
  2327.         if(!mappedFieldsToUpdate.isEmpty() && !quoteItemsToUpdate.isEmpty()){
  2328.             for(CPQ_QuoteItem__c quotItem : quoteItemsToUpdate){
  2329.                 if(mappedFieldsToUpdate.containsKey(quotItem.Id)){
  2330.                     for(String filed2upd : listedFields4QI.get(quotItem.Id)){
  2331.                         quotItem.put(filed2upd, mappedFieldsToUpdate.get(quotItem.Id).get(filed2upd));
  2332.                     }
  2333.                 }
  2334.             }
  2335.         }
  2336.     }
  2337.  
  2338.     private static Map<String, CPQ_QuoteItem__c> findMapElements(Map<String, CPQ_QuoteItem__c> mapStructure, String field2search, CPQ_QuoteItemAttribute__c attr){
  2339.         Map<String, CPQ_QuoteItem__c> mappedFieldsToUpdate = mapStructure;
  2340.         if(attr.Type__c == 'Radio' || attr.Type__c == 'Picklist'){
  2341.             mappedFieldsToUpdate.get(attr.Quote_Item__c).put(field2search, attr.Value_Attribute__r.Name);
  2342.         } else if(attr.Type__c == 'Text' || attr.Type__c == 'Textarea' || attr.Type__c == 'Contract'){
  2343.             mappedFieldsToUpdate.get(attr.Quote_Item__c).put(field2search, attr.Value_Text_Short__c);
  2344.         } else if(attr.Type__c == 'Boolean'){
  2345.             String bool2str = attr.Value_Boolean__c ? 'true' : 'false';
  2346.             mappedFieldsToUpdate.get(attr.Quote_Item__c).put(field2search, bool2str);
  2347.         } else if(attr.Type__c == 'Date'){
  2348.             mappedFieldsToUpdate.get(attr.Quote_Item__c).put(field2search, attr.Value_Date__c);
  2349.         } else if(attr.Type__c == 'DateTime'){
  2350.             mappedFieldsToUpdate.get(attr.Quote_Item__c).put(field2search, attr.Value_Datetime__c);
  2351.         } else if(attr.Type__c == 'Currency'){
  2352.             mappedFieldsToUpdate.get(attr.Quote_Item__c).put(field2search, attr.Value_Currency__c);
  2353.         } else if(attr.Type__c == 'Percent'){
  2354.             mappedFieldsToUpdate.get(attr.Quote_Item__c).put(field2search, attr.Value_Percent__c);
  2355.         } else if(attr.Type__c == 'Number'){
  2356.             try{
  2357.                 mappedFieldsToUpdate.get(attr.Quote_Item__c).put(field2search, attr.Value_Number__c); //some numeric value on QuoteItem Attribute are also numeric on quoteItem, and some are as text
  2358.             } catch (Exception e){
  2359.                 try{
  2360.                     mappedFieldsToUpdate.get(attr.Quote_Item__c).put(field2search, String.valueOf(attr.Value_Number__c));
  2361.                 } catch (Exception ex){
  2362.                     System.debug('Error: ' + ex + '   Ignore this field');
  2363.                 }
  2364.             }
  2365.         } else if(attr.Type__c == 'Service Reference'){
  2366.             String serv = attr.Value_Sold_Service__c != null ? attr.Value_Sold_Service__r.Name : attr.Value_Quote_Item__r.Name;
  2367.             mappedFieldsToUpdate.get(attr.Quote_Item__c).put(field2search, serv);
  2368.         } else if(attr.Type__c == 'Charge' || attr.Type__c == 'Lookup'){
  2369.             mappedFieldsToUpdate.get(attr.Quote_Item__c).put(field2search, attr.Value_Text_Long_Trim__c);
  2370.         }
  2371.         return mappedFieldsToUpdate;
  2372.     }
  2373.  
  2374.  
  2375.     public static CPQ_QuoteItemAttribute__c createAttribute(Id parentId, CPQ_Attribute__c attributeDefinition, String value, Id parentDefinitionId, Boolean isComponent) {
  2376.         CPQ_QuoteItemAttribute__c attribute = new CPQ_QuoteItemAttribute__c();
  2377.         attribute.Quote_Item__c = parentId;
  2378.         attribute.Attribute__c = attributeDefinition.Id;
  2379.         attribute.Type__c = attributeDefinition.Type__c;
  2380.         if(!isComponent) {
  2381.             attribute.Component_Field_to_Update__c = attributeDefinition.Component_Field_to_Update__c;
  2382.         } else {
  2383.             attribute.Product_Field_to_Update__c = attributeDefinition.Product_Field_to_Update__c;
  2384.         }
  2385.        
  2386.         String name4descr;
  2387.         if(attribute.Type__c == CPQ_ATR01_Manager.ATR_TYPE_PICKLIST || attribute.Type__c == CPQ_ATR01_Manager.ATR_TYPE_RADIO){
  2388.  
  2389.             String oldValue = value;
  2390.             value = '';
  2391.                
  2392.             for(CPQ_AttributeValue__c av : attributeDefinition.AttributeValues__r){            
  2393.                 if(oldValue.equalsIgnoreCase(av.Name) && av.Global__c){
  2394.                     //value = av.TECH_Value_ID__c;
  2395.                     value = av.Id;
  2396.                     name4descr = av.Name;
  2397.                     break;
  2398.                 } else if(oldValue.equalsIgnoreCase(av.Name) && av.Exclusive_for_Product__c == parentDefinitionId && !isComponent) {
  2399.                     //value = av.TECH_Value_ID__c;
  2400.                     value = av.Id;
  2401.                     name4descr = av.Name;
  2402.                     break;
  2403.                 } else if(oldValue.equalsIgnoreCase(av.Name) && av.Exclusive_for_Component__c == parentDefinitionId && isComponent) {
  2404.                     //value = av.TECH_Value_ID__c;
  2405.                     value = av.Id;
  2406.                     name4descr = av.Name;
  2407.                     break;
  2408.                 }
  2409.             }
  2410.  
  2411.         }
  2412.        
  2413.         CPQ_PRI01_Manager.setAttributeValueFromString(attribute, value);
  2414.         if(attribute.Value_Attribute__r != null && name4descr != ''){
  2415.             attribute.Value_Attribute__r.Name = name4descr;
  2416.         }
  2417.         return attribute;
  2418.     }
  2419.  
  2420.     public static String CalculateGridValueForPorts(String gridLayout, List<CPQ_QuoteItem__c> components, List<Sold_Service__c> soldServices) {
  2421.  
  2422.         if(components != null) {
  2423.             System.debug('### layout = "' + gridLayout + '"; components = "' + components.size() + '"');
  2424.         } else if(soldServices != null) {
  2425.             System.debug('### layout = "' + gridLayout + '"; components = "' + soldServices.size() + '"');
  2426.         }
  2427.        
  2428.         Map<String, Map<String, String>> columns = new Map<String, Map<String, String>>();
  2429.         Map<String, Map<String, Integer>> currentPorts = new Map<String, Map<String, Integer>>();
  2430.         String result = '';
  2431.        
  2432.         Set<Id> portsAlreadyAdded = new Set<Id>();
  2433.  
  2434.         /* checking values from components */
  2435.         if(components != null) {
  2436.             for(CPQ_QuoteItem__c component : components) {
  2437.                 String portType = '';
  2438.                 String continent = '';
  2439.  
  2440.                 if(component.A_Port__c != null && !portsAlreadyAdded.contains(component.A_Port__c)) {
  2441.                     portType = component.A_Port__r.Port_Type__c;
  2442.                     continent = component.A_Port__r.Homing_Gateway__c == null ? '' : component.A_Port__r.Homing_Gateway__r.Continent__c;
  2443.                     portsAlreadyAdded.add(component.A_Port__c);
  2444.                 }
  2445.  
  2446.                 if(String.isNotEmpty(portType) && String.isNotEmpty(continent)) {
  2447.                     Map<String, Integer> portTypes = currentPorts.get(continent.toLowerCase());
  2448.                     if(portTypes == null) {
  2449.                         portTypes = new Map<String, Integer>();
  2450.                         currentPorts.put(continent.toLowerCase(), portTypes);
  2451.                     }
  2452.  
  2453.                     Integer portCounter = portTypes.get(portType.toLowerCase());
  2454.                     if(portCounter == null) portCounter = 0;
  2455.                     portCounter = portCounter + 1;
  2456.                     portTypes.put(portType.toLowerCase(), portCounter);
  2457.                 }
  2458.  
  2459.                 System.debug('### Port A  type = "' + portType + '"; continent = "' + continent + '"');
  2460.  
  2461.                 portType = '';
  2462.                 continent = '';
  2463.  
  2464.                 if(component.B_Port__c != null && !portsAlreadyAdded.contains(component.B_Port__c)) {
  2465.                     portType = component.B_Port__r.Port_Type__c;
  2466.                     continent = component.B_Port__r.Homing_Gateway__c == null ? '' : component.B_Port__r.Homing_Gateway__r.Continent__c;
  2467.                     portsAlreadyAdded.add(component.B_Port__c);
  2468.                 }
  2469.  
  2470.                 if(String.isNotEmpty(portType) && String.isNotEmpty(continent)) {
  2471.                     Map<String, Integer> portTypes = currentPorts.get(continent.toLowerCase());
  2472.                     if(portTypes == null) {
  2473.                         portTypes = new Map<String, Integer>();
  2474.                         currentPorts.put(continent.toLowerCase(), portTypes);
  2475.                     }
  2476.  
  2477.                     Integer portCounter = portTypes.get(portType.toLowerCase());
  2478.                     if(portCounter == null) portCounter = 0;
  2479.                     portCounter = portCounter + 1;
  2480.                     portTypes.put(portType.toLowerCase(), portCounter);
  2481.                 }
  2482.  
  2483.                 System.debug('### Port B  type = "' + portType + '"; continent = "' + continent + '"');
  2484.             }
  2485.         } else if(soldServices != null) {
  2486.             for(Sold_Service__c soldService : soldServices) {
  2487.                 String portType = '';
  2488.                 String continent = '';
  2489.  
  2490.                 if(soldService.A_Port__c != null && !portsAlreadyAdded.contains(soldService.A_Port__c)) {
  2491.                     portType = soldService.A_Port__r.Port_Type__c;
  2492.                     continent = soldService.A_Port__r.Homing_Gateway__c == null ? '' : soldService.A_Port__r.Homing_Gateway__r.Continent__c;
  2493.                     portsAlreadyAdded.add(soldService.A_Port__c);
  2494.                 }
  2495.  
  2496.                 if(String.isNotEmpty(portType) && String.isNotEmpty(continent)) {
  2497.                     Map<String, Integer> portTypes = currentPorts.get(continent.toLowerCase());
  2498.                     if(portTypes == null) {
  2499.                         portTypes = new Map<String, Integer>();
  2500.                         currentPorts.put(continent.toLowerCase(), portTypes);
  2501.                     }
  2502.  
  2503.                     Integer portCounter = portTypes.get(portType.toLowerCase());
  2504.                     if(portCounter == null) portCounter = 0;
  2505.                     portCounter = portCounter + 1;
  2506.                     portTypes.put(portType.toLowerCase(), portCounter);
  2507.                 }
  2508.  
  2509.                 System.debug('### Port A  type = "' + portType + '"; continent = "' + continent + '"');
  2510.  
  2511.                 portType = '';
  2512.                 continent = '';
  2513.  
  2514.                 if(soldService.B_Port__c != null && !portsAlreadyAdded.contains(soldService.B_Port__c)) {
  2515.                     portType = soldService.B_Port__r.Port_Type__c;
  2516.                     continent = soldService.B_Port__r.Homing_Gateway__c == null ? '' : soldService.B_Port__r.Homing_Gateway__r.Continent__c;
  2517.                     portsAlreadyAdded.add(soldService.B_Port__c);
  2518.                 }
  2519.  
  2520.                 if(String.isNotEmpty(portType) && String.isNotEmpty(continent)) {
  2521.                     Map<String, Integer> portTypes = currentPorts.get(continent.toLowerCase());
  2522.                     if(portTypes == null) {
  2523.                         portTypes = new Map<String, Integer>();
  2524.                         currentPorts.put(continent.toLowerCase(), portTypes);
  2525.                     }
  2526.  
  2527.                     Integer portCounter = portTypes.get(portType.toLowerCase());
  2528.                     if(portCounter == null) portCounter = 0;
  2529.                     portCounter = portCounter + 1;
  2530.                     portTypes.put(portType.toLowerCase(), portCounter);
  2531.                 }
  2532.  
  2533.                 System.debug('### Port B  type = "' + portType + '"; continent = "' + continent + '"');
  2534.             }
  2535.         }
  2536.  
  2537.         System.debug('### currentPorts: ' + currentPorts);
  2538.  
  2539.         /* setting attribute value based on layout */
  2540.         if(String.isNotEmpty(gridLayout)) {
  2541.             Map<String, Object> gridMap = (Map<String, Object>)JSON.deserializeUntyped(gridLayout);
  2542.             List<Object> cols = (List<Object>)gridMap.get('cols');
  2543.             List<Object> rows = (List<Object>)gridMap.get('rows');
  2544.  
  2545.             System.debug('### cols: ' + cols);
  2546.             System.debug('### rows: ' + rows);
  2547.  
  2548.             result += '{';
  2549.             for(Object col : cols) {
  2550.                 String colString = String.valueOf(col).replace('"','');
  2551.                 result += '"' + colString + '":{';
  2552.                 for(Object row : rows) {
  2553.                     String rowString = String.valueOf(row).replace('"','');
  2554.                     Integer count = 0;
  2555.                     if(currentPorts.get(colString.toLowerCase()) != null && currentPorts.get(colString.toLowerCase()).get(rowString.toLowerCase()) != null){
  2556.                         count = currentPorts.get(colString.toLowerCase()).get(rowString.toLowerCase());
  2557.                     }
  2558.  
  2559.                     if(count > 0) {
  2560.                         result += '"' + rowString + '":"' + String.valueOf(count) + '",';
  2561.                     } else {
  2562.                         result += '"' + rowString + '":"",';
  2563.                     }
  2564.                 }
  2565.  
  2566.                 result = result.removeEnd(',');
  2567.                 result += '},';
  2568.             }
  2569.             result = result.removeEnd(',');
  2570.             result += '}';
  2571.         }
  2572.  
  2573.         System.debug('### Calculated IP Grid: ' + result);
  2574.         return result;
  2575.     }
  2576.  
  2577.     private static List<SoldService_Contact_Junction__c> initContacts(List<Sold_Service__c> soldServices, Id opportunityId) {
  2578.        
  2579.         System.debug('@@ START CLASS: CPQ_PRD04_SoldServiceMappingHlpr METHOD: initContacts');
  2580.        
  2581.         List<SoldService_Contact_Junction__c> conToInsert = new List<SoldService_Contact_Junction__c>();
  2582.        
  2583.         Map<Id, List<Sold_Service__c>> oliToSoldServices = new Map<Id, List<Sold_Service__c>>();
  2584.        
  2585.         for(Sold_Service__c ss : soldServices){
  2586.             if(String.isNotBlank(ss.OLI_Link_ID__c)) {
  2587.                 List<Sold_Service__c> services = oliToSoldServices.get(ss.OLI_Link_ID__c);
  2588.                 if(services == null){
  2589.                     services = new List<Sold_Service__c>();
  2590.                     oliToSoldServices.put(ss.OLI_Link_ID__c, services);
  2591.                 }
  2592.                 services.add(ss);
  2593.             }
  2594.         }
  2595.  
  2596.         // Target field on Contact > Destination field on Sold Service Contact
  2597.         Map<String,String> fieldMap = SoldServiceUtility.buildFieldMapping(ApplicationConstant.FIELD_MAPPING_CONTACT);
  2598.        
  2599.         String queryString = 'select ' + CPQ_Utils01_SObjectHelperCls.getFieldListForSOQL('Contact_Junction__c', null, null) + ' from Contact_Junction__c where Opportunity__c = :opportunityId Order by Role__c asc nulls last';
  2600.         List<Contact_Junction__c> contacts = Database.query(queryString);
  2601.  
  2602.         if(contacts == null || contacts.isEmpty()) {
  2603.             System.debug('@@ END CLASS: CPQ_PRD04_SoldServiceMappingHlpr METHOD: initContacts (null)');
  2604.             return null;
  2605.         }
  2606.        
  2607.         for (Contact_Junction__c curr : contacts) {
  2608.             if (String.isNotBlank(curr.Opportunity_Line_Item_ID__c) && oliToSoldServices.containsKey(curr.Opportunity_Line_Item_ID__c)) {
  2609.                 if(curr.Contact__c != null && String.isNotBlank(curr.Role__c) && !contactIdByRole.containsKey(curr.Role__c.toLowerCase())){
  2610.                     contactIdByRole.put(curr.Role__c.toLowerCase(), curr.Contact__c);
  2611.                 }
  2612.  
  2613.                 List<Sold_Service__c> lstSoldService = oliToSoldServices.get(curr.Opportunity_Line_Item_ID__c);
  2614.                
  2615.                 for(Integer i = 0, j = lstSoldService.size(); i < j; i++){
  2616.                     SoldService_Contact_Junction__c scj = new SoldService_Contact_Junction__c();
  2617.                     scj.Sold_Service__c                 = lstSoldService[i].Id;
  2618.                     scj.Name = 'Test Contact Junction';
  2619.                     // Map fields using a custom setting 'SoldServiceMapping__c'
  2620.                     for (String f : fieldMap.keySet())
  2621.                         scj.put(fieldMap.get(f), curr.get(f));
  2622.                    
  2623.                     conToInsert.add(scj);
  2624.                 }
  2625.             }
  2626.         }
  2627.        
  2628.         System.debug('@@ END CLASS: CPQ_PRD04_SoldServiceMappingHlpr METHOD: initContacts');
  2629.         return conToInsert;
  2630.     }
  2631.  
  2632.     private static void createChangeRequestAndLineItems(List<Sold_Service__c> lstSoldServices, Id opportunityId){
  2633.  
  2634.         System.debug('@@ START CLASS: CPQ_PRD04_SoldServiceMappingHlpr METHOD: createChangeRequestAndLineItems');
  2635.  
  2636.         Map<ID,Map<String, Change_Request__c>> changeRequestByIpBillingGroupSoldServiceId = new Map<ID,Map<String, Change_Request__c>>();
  2637.        
  2638.         Map<Id, Sold_Service__c> mapOfSoldServices = new Map<Id, Sold_Service__c>([SELECT A_Port__r.LAG_LACP__c, CRM_Parent_Sold_Service__r.Type_of_Service_Description__c, CRM_Parent_Sold_Service__c FROM Sold_Service__c WHERE Id IN :lstSoldServices]);
  2639.  
  2640.         Id ownerId = null;
  2641.        
  2642.         for(Opportunity opp : [select Id, OwnerId from Opportunity where Id = :opportunityId limit 1]){
  2643.             ownerId = opp.OwnerId;
  2644.         }
  2645.  
  2646.         for(Sold_Service__c ss :lstSoldServices){
  2647.             if(ApplicationConstant.ITEMNAME_IP_SERVICE.equalsIgnoreCase(ss.Item_Name__c)
  2648.                 && ApplicationConstant.OLI_ITEM_ACTION_ADD.equalsIgnoreCase(ss.Item_Action__c)
  2649.                 && mapOfSoldServices.get(ss.Id).CRM_Parent_Sold_Service__c != null
  2650.                 && mapOfSoldServices.get(ss.Id).A_Port__r.LAG_LACP__c != 'Existing'
  2651.                 && mapOfSoldServices.get(ss.Id).CRM_Parent_Sold_Service__r.Type_of_Service_Description__c != ApplicationConstant.ITEMNAME_IP_PEERING_GROUP
  2652.             ){
  2653.                 if(!contactIdByRole.containsKey(ApplicationConstant.OPERATIONAL_CONTACT_ROLE_IP_CONFIGURATION.toLowerCase())) {
  2654.                     System.debug('### ' + ApplicationConstant.OPERATIONAL_CONTACT_ROLE_IP_CONFIGURATION + ' contact role was not found');
  2655.                     throw new TeliaException(ApplicationConstant.OPERATIONAL_CONTACT_ROLE_IP_CONFIGURATION + ' contact does not exist.');
  2656.                 }
  2657.                 if(!contactIdByRole.containsKey(ApplicationConstant.OPERATIONAL_CONTACT_ROLE_DELIVERY_CONTACT.toLowerCase())){
  2658.                     System.debug('### ' + ApplicationConstant.OPERATIONAL_CONTACT_ROLE_DELIVERY_CONTACT + ' contact role was not found');
  2659.                     throw new TeliaException(ApplicationConstant.OPERATIONAL_CONTACT_ROLE_DELIVERY_CONTACT + ' does not exist.');
  2660.                 }
  2661.  
  2662.                 Change_Request__c req = new Change_Request__c();
  2663.                 req.Sold_Service__c = mapOfSoldServices.get(ss.Id).CRM_Parent_Sold_Service__c;
  2664.                 req.Status__c = ApplicationConstant.CHANGE_REQUEST_STATUS_OPEN;
  2665.                 req.Type__c = ApplicationConstant.CHANGE_REQUEST_TYPE_NEW;
  2666.                 req.Contact_Requested_By__c = contactIdByRole.get(ApplicationConstant.OPERATIONAL_CONTACT_ROLE_IP_CONFIGURATION.toLowerCase());
  2667.                 req.Contact_Sent_To__c = contactIdByRole.get(ApplicationConstant.OPERATIONAL_CONTACT_ROLE_IP_CONFIGURATION.toLowerCase());
  2668.                 req.Additional_Contact_Recipient__c = contactIdByRole.get(ApplicationConstant.OPERATIONAL_CONTACT_ROLE_DELIVERY_CONTACT.toLowerCase());
  2669.                 req.Send_Email__c = true;
  2670.                 req.Sold_Service_Type__c = ss.Type_of_Service__c;
  2671.                 req.OwnerId = ownerId;
  2672.  
  2673.                 if (!changeRequestByIpBillingGroupSoldServiceId.containsKey(mapOfSoldServices.get(ss.Id).CRM_Parent_Sold_Service__c) ) {
  2674.                     changeRequestByIpBillingGroupSoldServiceId.put(mapOfSoldServices.get(ss.Id).CRM_Parent_Sold_Service__c, new Map<String, Change_Request__c>());
  2675.                 }
  2676.                 changeRequestByIpBillingGroupSoldServiceId.get(mapOfSoldServices.get(ss.Id).CRM_Parent_Sold_Service__c).put(ss.Type_of_Service__c, req);
  2677.             }
  2678.         }
  2679.  
  2680.         if(!changeRequestByIpBillingGroupSoldServiceId.isEmpty()){
  2681.             System.debug('### Inserting Change Requests');
  2682.             List<Change_Request__c> listOfChangeRequests = new List<Change_Request__c>();
  2683.  
  2684.             for (Map<String, Change_Request__c> changeRequests : changeRequestByIpBillingGroupSoldServiceId.values()) {
  2685.                 listOfChangeRequests.addAll(changeRequests.values());
  2686.             }
  2687.  
  2688.             upsert listOfChangeRequests;
  2689.  
  2690.         } else {
  2691.             System.debug('@@ END CLASS: CPQ_PRD04_SoldServiceMappingHlpr METHOD: createChangeRequestAndLineItems (null)');
  2692.             return;
  2693.         }
  2694.         List<Change_Request_Line_Item__c> lineItemToCreate = new List<Change_Request_Line_Item__c>();
  2695.         for(Sold_Service__c ss :lstSoldServices){
  2696.             if(ApplicationConstant.ITEMNAME_IP_SERVICE.equalsIgnoreCase(ss.Item_Name__c)
  2697.             && changeRequestByIpBillingGroupSoldServiceId.containsKey(mapOfSoldServices.get(ss.Id).CRM_Parent_Sold_Service__c)
  2698.             && ApplicationConstant.OLI_ITEM_ACTION_ADD.equalsIgnoreCase(ss.Item_Action__c)
  2699.             ){
  2700.                 Map<String,Change_Request__c> listOfRequestsForSoldService = changeRequestByIpBillingGroupSoldServiceId.get(mapOfSoldServices.get(ss.Id).CRM_Parent_Sold_Service__c);
  2701.                 for (String key : listOfRequestsForSoldService.keySet()) {
  2702.                     if(key == ss.Type_of_Service__c && mapOfSoldServices.get(ss.Id).A_Port__r.LAG_LACP__c != 'Existing'){
  2703.                         Change_Request_Line_Item__c requestLineItem = new Change_Request_Line_Item__c();
  2704.                         requestLineItem.Sold_Service__c = ss.Id;
  2705.                         requestLineItem.Change_Request__c = listOfRequestsForSoldService.get(key).Id;
  2706.                         requestLineItem.Status__c = ApplicationConstant.CHANGE_REQUEST_STATUS_OPEN;
  2707.                         requestLineItem.Type__c = ApplicationConstant.CHANGE_REQUEST_LINE_ITEM_TYPE_IP_CONFIGURATION_DETAILS;
  2708.                         lineItemToCreate.add(requestLineItem);
  2709.                     }
  2710.                 }
  2711.  
  2712.             }
  2713.         }
  2714.        
  2715.         if(!lineItemToCreate.isEmpty()) insert lineItemToCreate;
  2716.        
  2717.         System.debug('@@ END CLASS: CPQ_PRD04_SoldServiceMappingHlpr METHOD: createChangeRequestAndLineItems');
  2718.     }
  2719.  
  2720.     public static void cloneObject(sObject sourceObject, sObject targetObject, String objectType) {
  2721.         Map<String, Schema.DescribeFieldResult> objectFields = CPQ_Utils01_SObjectHelperCls.getFieldDescriptions(objectType);
  2722.         set<String> excludedFields = new set<String>(new String[]{'CreatedDate', 'LastModifiedDate', 'LastViewedDate', 'SystemModstamp', 'LastReferencedDate', 'LastModifiedById', 'OwnerId', 'CreatedById'});
  2723.         for(String fieldName : objectFields.keySet()) {
  2724.             if(objectFields.get(fieldName).getType() != Schema.DisplayType.Reference && objectFields.get(fieldName).isCreateable() && !excludedFields.contains(fieldName)){
  2725.                 if(objectFields.get(fieldName).getType() == Schema.DisplayType.Boolean) {
  2726.                     if(sourceObject.get(fieldName) != null) {
  2727.                         targetObject.put(fieldName, sourceObject.get(fieldName));
  2728.                     } else {
  2729.                         targetObject.put(fieldName, false);
  2730.                     }
  2731.                 } else {
  2732.                     targetObject.put(fieldName, sourceObject.get(fieldName));
  2733.                 }
  2734.             }
  2735.         }
  2736.     }  
  2737.  
  2738.     public static String key(Integer i, Id id) {
  2739.         return String.valueOf(i)+String.valueOf(Id);
  2740.     }
  2741.  
  2742.     /************************************************************************
  2743.     Description : Data format returned from creating sold services. This is needed for execution of method from batch,
  2744.                   so the information about created sold services is not lost.
  2745.     ************************************************************************/    
  2746.     public class createSoldServicesResult {
  2747.         public Map<String, Id> quoteItemToSoldService = new Map<String, Id>();
  2748.         public Map<String, String> upsertKeyToQuoteItem = new Map<String, String>();
  2749.     }
  2750. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement