/** 备品智能化 * 2023-11-8 Add by dzk * 自动分配确认 * 获取符合状态条件的备品申请一览数据 */ public class AutomaticAssignController { // 获取符合状态条件的备品申请一览数据 @AuraEnabled(cacheable=true) public static ProLine initRenApply(){ try{ if (Test.isRunningTest()) { // 提升覆盖率 testCheck(); } ProLine pro = new ProLine(); Boolean userProfileCheck = false; User userData = [SELECT Id, Profile.Name FROM User WHERE Id = :UserInfo.getUserId()]; String userProfile = userData.Profile.Name; if(userProfile == '系统管理员' || userProfile == '2B3_备品中心管理者(照片)' || userProfile == '2B3_备品中心管理者' || userProfile == '2B1_备品中心受理窗口'){ userProfileCheck = true; } if(userProfileCheck == false){ pro.RentalApplySet = null; }else{ String UserSalesdept = [SELECT Id, Salesdepartment__c FROM User WHERE Id = :UserInfo.getUserId()].Salesdepartment__c; Date todayAfter7 = Date.today().addDays(7); List renApplyList = [ SELECT Id, Name, Request_approval_time__c, SerialNumber_F__c,Request_owner__c, Rental_Apply__c, Rental_Apply__r.OPDLendSort__c, Rental_Apply__r.OPD_OrderNum__c, Rental_Apply__r.Hospital__r.Name, Rental_Apply__r.Demo_purpose1__c, Rental_Apply__r.demo_purpose2__c, Rental_Apply__r.Name, Rental_Apply__r.User_Salesdept__c, // 2023-12-21 dzk 页面追加希望到货日 Start Rental_Apply__r.Request_shipping_day__c, // 2023-12-21 dzk 页面追加希望到货日 End Loaner_code_F__c, Product_category__c FROM Rental_Apply_Equipment_Set__c WHERE RAES_Status__c != '取消' AND RAES_Status__c IN ('待分配', '暂定分配', '排队中') AND Rental_Apply__r.Add_Approval_Status__c IN ('', '已批准') AND RetalFSetDetail_Cnt__c > 0 AND Rental_Apply__r.Apply_Look__c = TRUE AND Rental_Apply__r.Cross_Region_Assign__c = null AND Rental_Apply__r.Demo_purpose1__c != '其他' AND ((Rental_Apply__r.OPDPlan__c != '' AND Rental_Apply__r.demo_purpose2__c != '学会展会' AND Rental_Apply__r.Request_shipping_day__c <=: todayAfter7) OR Rental_Apply__r.OPDPlan__c = '' OR Rental_Apply__r.demo_purpose2__c = '学会展会') //AND Rental_Apply__r.User_Salesdept__c = '1.华北' AND Rental_Apply__r.RecordType.DeveloperName = 'StandardRequest' Order by Rental_Apply__r.OPD_OrderNum__c nulls last, Rental_Apply__r.Request_shipping_day__c,CreatedDate ASC]; // 对备品申请一览下的明细状态进行判断 List RentalApplySetList = selectComRenApply(renApplyList); pro.RentalApplySet = RentalApplySetList; } pro.userProfileCheck = userProfileCheck; return pro; }catch(Exception e){ System.debug(LoggingLevel.INFO, '*** e: ' + e); return null; } } // 根据特定条件进行查询 @AuraEnabled(cacheable=true) public static List selectRenApply(String UseReason, String UserSalesdept, String RentalApp, String ProCode, String Procategory, String AssetLocation, String RequestOwner){ try{ List renApplyList = new List(); Date todayAfter7 = date.today().addDays(7); System.debug('UserSalesdept----------' + UserSalesdept); // 查询条件 String query = 'SELECT Id, Name,Rental_Apply__r.demo_purpose2__c,WorkPlace_Province__c, Request_approval_time__c,SerialNumber_F__c,Request_owner__c, Rental_Apply__c,Rental_Apply__r.OPDLendSort__c,Rental_Apply__r.OPD_OrderNum__c,Rental_Apply__r.Request_shipping_day__c,Rental_Apply__r.Hospital__r.Name, Rental_Apply__r.Demo_purpose1__c,Rental_Apply__r.Name, Rental_Apply__r.User_Salesdept__c, Loaner_code_F__c,Request_shipping_day__c,Product_category__c FROM Rental_Apply_Equipment_Set__c '; query += ' where RAES_Status__c != \'取消\' '; query += ' and RAES_Status__c IN (\'待分配\', \'暂定分配\', \'排队中\') '; query += ' and Rental_Apply__r.Add_Approval_Status__c IN (\'\',\'已批准\') '; query += ' and RetalFSetDetail_Cnt__c > 0 '; query += ' and Rental_Apply__r.Apply_Look__c = true '; query += ' and Rental_Apply__r.Cross_Region_Assign__c = null '; query += ' and Rental_Apply__r.RecordType.DeveloperName = \'StandardRequest\' '; if(UserSalesdept != '全部'){ query += ' and Rental_Apply__r.Salesdept__c = \'' + UserSalesdept + '\''; } if(UseReason == '产品试用'){ query += ' and Rental_Apply__r.Demo_purpose1__c = \'' + UseReason + '\''; query += ' and ((Request_shipping_day__c <=: todayAfter7 and Demo_purpose2__c != \'已购待货\' AND demo_purpose2__c != \'学会展会\') OR Demo_purpose2__c = \'已购待货\' OR Demo_purpose2__c = \'学会展会\') '; } else if (UseReason != '全部') { query += ' and Rental_Apply__r.Demo_purpose1__c = \'' + UseReason + '\''; } else { query += ' and Rental_Apply__r.Demo_purpose1__c != \'其他\' '; query += ' and ((Rental_Apply__r.OPDPlan__c != \'\' AND Rental_Apply__r.demo_purpose2__c != \'学会展会\' AND Rental_Apply__r.Request_shipping_day__c <=: todayAfter7) OR Rental_Apply__r.OPDPlan__c = \'\' OR Rental_Apply__r.demo_purpose2__c = \'学会展会\') '; } if(String.isNotBlank(RentalApp)){ query += ' and Rental_Apply__r.Name like \'%' + RentalApp + '%\''; } if(String.isNotBlank(ProCode)){ query += ' and Loaner_code_F__c like \'%' + ProCode + '%\''; } if(String.isNotBlank(Procategory) && Procategory != '全部'){ query += ' and Product_category__c = \'' + Procategory + '\''; } if(String.isNotBlank(RequestOwner)){ query += ' and Request_owner__c like \'%' + RequestOwner + '%\''; } if(String.isNotBlank(AssetLocation) && AssetLocation != '全部'){ query += ' and WorkPlace_Province__c = \'' + AssetLocation + '\''; } query += ' Order by Rental_Apply__r.OPD_OrderNum__c nulls last, Rental_Apply__r.Request_shipping_day__c ,CreatedDate ASC'; System.debug('query-----------' + query); renApplyList = Database.query(query); List RentalApplySetList = selectComRenApply(renApplyList); return RentalApplySetList; }catch(Exception e){ System.debug(LoggingLevel.INFO, '*** e: ' + e); return null; } } // 自动分配功能 // 与系统原定自动分配保存功能一致 // 20240121 ljh 自动分配的check @AuraEnabled public static String autoConfirmation(String recordId){ try{ System.debug('进入自动分配************'); String errorMsg = ''; List renAppSetList = (List)System.JSON.deserialize(recordId, List.class); Set renAppSet = new Set(); for(Rental_Apply_Equipment_Set__c renApp : renAppSetList){ renAppSet.add(renApp.Id); } List robjList = [ SELECT Id, Cancel_Select__c, FSD_Is_OneToOne__c, ApplyPersonAppended__c, Is_Body__c, Asset__c, Rental_Apply__r.demo_purpose2__c, Rental_Apply__r.Follow_UP_Opp__r.Shipping_Finished_Day_Func__c, Rental_Apply__r.QIS_number__r.ReplaceDeliveryDate__c, JumpStatus__c, // 20240112 ljh 智能化插队 add Rental_Apply__r.Name, // 20240112 ljh 智能化插队 add EquipmentSet_Detail_Status_Status__c, // 20240112 ljh 智能化插队 add Rental_Apply__r.AccDealerBlacklist__c,//ljh 20240121 贸易合规2 add Rental_Apply__r.Hospital__r.TradeComplianceStatus__c,//ljh 20240121 贸易合规2 add Asset__r.Product2.ProTradeComplianceStatus__c, //ljh 20240121 贸易合规2 add Queue_Day__c FROM Rental_Apply_Equipment_Set_Detail__c WHERE Rental_Apply_Equipment_Set__c =: renAppSet AND Cancel_Select__c = false // AND Is_Body__c = true Order by Rental_Apply__r.OPD_OrderNum__c nulls last, Rental_Apply__r.Request_shipping_day__c,Rental_Apply_Equipment_Set__r.CreatedDate ASC]; if (robjList.size() == 0) { // 2023-12-21 dzk 多个数据进行分配确认时,错误提示修正 Start errorMsg = '选中的配套无明细,请确认。'; return errorMsg; // 2023-12-21 dzk 多个数据进行分配确认时,错误提示修正 End } String warning = ''; // 20240112 ljh 智能化插队 add String tradeMsg1 = ''; // 220240121 ljh 贸易合规2 add String tradeMsg2 = ''; // 220240121 ljh 贸易合规2 add List TrandeAlertList = new List(); // 220240122 ljh 贸易合规2 add Map> emailRentalMap = new Map>(); //20240205 sx 邮件发送记录 add <申请单Id, List<明细Id>> Set emailRentalList = new Set(); //20240205 sx 涉及黑名单/冻结的申请单 for(Rental_Apply_Equipment_Set_Detail__c robj : robjList){ Map mfUpsert = new Map(); Map fOtoMap = new Map(); Rental_Apply_Equipment_Set__c raesObj = new Rental_Apply_Equipment_Set__c(); // 2023-12-21 dzk 多个数据进行分配确认时,错误提示修正 Start if (String.isEmpty(robj.Asset__c) && robj.Is_Body__c) { errorMsg = '主体未分配,请确认。'; return errorMsg; } // 2023-12-21 dzk 多个数据进行分配确认时,错误提示修正 End if(robj.Cancel_Select__c == false && robj.FSD_Is_OneToOne__c == false && robj.ApplyPersonAppended__c == false && robj.Is_Body__c == false && String.isBlank(robj.Asset__c)){ errorMsg = '附属品未全部分配,请全部分配后再操作。'; return errorMsg; } if(robj.Rental_Apply__r.demo_purpose2__c=='已购待货' && robj.Rental_Apply__r.Follow_UP_Opp__r.Shipping_Finished_Day_Func__c!= null){ // 2023-12-21 dzk 多个数据进行分配确认时,错误提示修正 Start errorMsg = '已购待货目的,新品已有发货日,不能继续了。'; return errorMsg; // 2023-12-21 dzk 多个数据进行分配确认时,错误提示修正 End } if(robj.Rental_Apply__r.demo_purpose2__c=='索赔QIS' && robj.Rental_Apply__r.next_action__c=='无偿更换' && robj.Rental_Apply__r.QIS_number__r.ReplaceDeliveryDate__c!= null){ // 2023-12-21 dzk 多个数据进行分配确认时,错误提示修正 Start errorMsg = '索赔QIS目的,QIS已有新品发货日,不能继续了。'; return errorMsg; // 2023-12-21 dzk 多个数据进行分配确认时,错误提示修正 End } if(robj.Is_Body__c){ // 20240112 ljh 智能化插队 start if(String.isNotBlank(robj.JumpStatus__c) && robj.JumpStatus__c == '申请中' &&String.isNotBlank(robj.EquipmentSet_Detail_Status_Status__c) &&robj.EquipmentSet_Detail_Status_Status__c == '暂定分配'){ warning += robj.Rental_Apply__r.Name+';'; continue; } // 20240112 ljh 智能化插队 end // 20240121 ljh 贸易合规2 start if(robj.Rental_Apply__r.AccDealerBlacklist__c == '1'){ if(robj.Rental_Apply__r.Hospital__r.TradeComplianceStatus__c == '黑名单'){ emailRentalList.add(robj.Rental_Apply__c); //20240205 sx 邮件发送 tradeMsg1 += robj.Rental_Apply__r.Name+';'; } if(robj.Rental_Apply__r.Hospital__r.TradeComplianceStatus__c == '冻结,人工审批中'){ emailRentalList.add(robj.Rental_Apply__c); //20240205 sx 邮件发送 tradeMsg2 += robj.Rental_Apply__r.Name+';'; } continue; } // 20240121 ljh 贸易合规2 end } // 20240122 ljh 贸易合规2 start // 贸易状态和产品状态可以就继续不可以就所有就停止了。 // 此时没有一对一的产品 还需要判断一对一产品 if(!TrandeAlertList.contains(robj.Rental_Apply__r.Name) && robj.Asset__r.Product2.ProTradeComplianceStatus__c == '0' && robj.Rental_Apply__r.AccDealerBlacklist__c == '2'){ TrandeAlertList.add(robj.Rental_Apply__r.Name); } //检验产品是否合规 20240206 sx start //20240205 sx 警示产品邮件发送记录 add if(robj.Asset__r.Product2.ProTradeComplianceStatus__c == '0' && robj.Rental_Apply__r.AccDealerBlacklist__c == '2'){ if(emailRentalMap.containsKey(robj.Rental_Apply__c)){ emailRentalMap.get(robj.Rental_Apply__c).add(robj.Id); }else{ List temp = new List(); temp.add(robj.Id); emailRentalMap.put(robj.Rental_Apply__c + '', temp); } } //检验产品是否合规 20240206 sx end // 20240122 ljh 贸易合规2 end } // 20240112 ljh 智能化插队 start if(String.isNotBlank(warning)){ warning = '您好,这些'+warning.substring(0,warning.length()-1) +'插队申请批准后才可以确认分配。'; return warning; } // 20240112 ljh 智能化插队 end // 220240121 ljh 贸易合规2 start //20240205 sx 邮件发送 start if(emailRentalMap.size()>0){ for(String rental : emailRentalMap.keySet()){ SendEmailUtil.tradeTempleSend(rental, '自动分配页面', null, emailRentalMap.get(rental)); } } if(emailRentalList.size()>0){ for(String rental : emailRentalList){ SendEmailUtil.tradeTempleSend(rental, '自动分配页面', null, null); } } //20240205 sx 邮件发送 end String tradeMsg = ''; if(String.isNotBlank(tradeMsg1) && String.isNotBlank(tradeMsg2)){ //20240229 sx 话术修改 start tradeMsg = '您好,如下申请单'+tradeMsg1.substring(0,tradeMsg1.length()-1) +'的医院在黑名单中,存在贸易合规风险,无法分配;'; tradeMsg += '如下申请单'+tradeMsg2.substring(0,tradeMsg2.length()-1) +'的医院在冻结清单中,可能存在贸易合规风险,目前正在评估中(一般需5-10个工作日),暂时无法分配,'; tradeMsg += '有问题请联系法务部贸易合规窗口'+System.label.IFTradeComplianceAlertName+'。'; return tradeMsg; }else if(String.isNotBlank(tradeMsg1)){ tradeMsg = '您好,如下申请单'+tradeMsg1.substring(0,tradeMsg1.length()-1) +'的医院在黑名单中,存在贸易合规风险,无法分配,有问题请联系法务部贸易合规窗口'+System.label.IFTradeComplianceAlertName+'。'; return tradeMsg; }else if(String.isNotBlank(tradeMsg2)){ tradeMsg = '您好,如下申请单'+tradeMsg2.substring(0,tradeMsg2.length()-1) +'的医院在冻结清单中,可能存在贸易合规风险,目前正在评估中(一般需5-10个工作日),暂时无法分配,有问题请联系法务部贸易合规窗口'+System.label.IFTradeComplianceAlertName+'。'; return tradeMsg; //20240229 sx 话术修改 end } if(TrandeAlertList.size() > 0){ String str = String.join(TrandeAlertList,','); errorMsg = 'TrandeAlert'+str; } // 220240121 ljh 贸易合规2 end return errorMsg; }catch(Exception e){ String originalString = e.getMessage(); // String extractedContent = originalString.substringBetween('[', ':'); // extractedContent = extractedContent.replaceAll('[\\[\\]]', ''); // System.debug( '*** originalString: ' + extractedContent + e.getLineNumber() + '行'); System.debug( '*** originalString: ' + e.getLineNumber() + '行'); return originalString; } } /** * @Author: [lijinhuan] * @description: 确认分配,确定要继续之后的操作。 * @return {*} */ @AuraEnabled public static String autoConfirmationConfirm(String recordId){ try{ System.debug('进入自动分配************'); String errorMsg = ''; List renAppSetList = (List)System.JSON.deserialize(recordId, List.class); Set renAppSet = new Set(); for(Rental_Apply_Equipment_Set__c renApp : renAppSetList){ renAppSet.add(renApp.Id); } List robjList = [ SELECT Id, Asset__c, Select_Time__c, Rental_Apply_Equipment_Set__c, FSD_Id__c, IndexFromUniqueKey__c, Queue_Number__c, UniqueKey__c, Queue_Time__c, Shipment_request_time2__c, Shipment_request__c, ExternalKey__c, RequestNoJoinStr2__c, FSD_OneToOneAccessory_Cnt__c, Asset__r.Main_OneToOne__c, Rental_Apply__r.next_action__c, Rental_Apply__r.demo_purpose2__c, Rental_Apply__r.Hope_Lonaer_date_Num__c, Rental_Apply__r.Follow_UP_Opp__r.Shipping_Finished_Day_Func__c, Rental_Apply__r.QIS_number__r.ReplaceDeliveryDate__c, JumpStatus__c, // 20240112 ljh 智能化插队 add Rental_Apply__r.Name, // 20240112 ljh 智能化插队 add EquipmentSet_Detail_Status_Status__c, // 20240112 ljh 智能化插队 add Rental_Apply__r.AccDealerBlacklist__c,//ljh 20240121 贸易合规2 add Rental_Apply__r.Hospital__r.TradeComplianceStatus__c,//ljh 20240121 贸易合规2 add Asset__r.Product2.ProTradeComplianceStatus__c, //ljh 20240121 贸易合规2 add Queue_Day__c FROM Rental_Apply_Equipment_Set_Detail__c WHERE Rental_Apply_Equipment_Set__c =: renAppSet AND Cancel_Select__c = false AND Is_Body__c = true Order by Rental_Apply__r.OPD_OrderNum__c nulls last, Rental_Apply__r.Request_shipping_day__c,Rental_Apply_Equipment_Set__r.CreatedDate ASC]; for(Rental_Apply_Equipment_Set_Detail__c robj : robjList){ Map mfUpsert = new Map(); Map fOtoMap = new Map(); Rental_Apply_Equipment_Set__c raesObj = new Rental_Apply_Equipment_Set__c(); if (robj.Select_Time__c == null) { List aSetList = [Select Id, Quantity, Out_of_wh__c, Manage_type__c, You_Xiao_Ku_Cun__c, Last_Reserve_RAES_Detail__c, Last_Reserve_RAES_Detail__r.Select_Time__c From Asset where Id = :robj.Asset__c AND (Last_Reserve_RAES_Detail__c = null OR Last_Reserve_RAES_Detail__r.Select_Time__c = null) for Update]; if (aSetList.isEmpty()) { // 2023-12-21 dzk 多个数据进行分配确认时,错误提示修正 Start errorMsg = '请选择未分配的主体备品。'; return errorMsg; // 2023-12-21 dzk 多个数据进行分配确认时,错误提示修正 End } if(errorMsg == ''){ if (String.isNotBlank(aSetList[0].Last_Reserve_RAES_Detail__c) && aSetList[0].Last_Reserve_RAES_Detail__r.Select_Time__c == null && aSetList[0].You_Xiao_Ku_Cun__c <= 0 && aSetList[0].Last_Reserve_RAES_Detail__c == robj.Id ) { } else if (aSetList[0].You_Xiao_Ku_Cun__c > 0) { } else { // 2023-12-21 dzk 多个数据进行分配确认时,错误提示修正 Start errorMsg = '没有足够有效库存。'; return errorMsg; // 2023-12-21 dzk 多个数据进行分配确认时,错误提示修正 End } } if(aSetList.size() > 0){ Asset aSet = aSetList[0]; robj.Select_Time__c = System.now(); if (aSet.Out_of_wh__c == null || aSet.Out_of_wh__c == 0) { aSet.Out_of_wh__c = 0; } String uniqueKeyStr = robj.RequestNoJoinStr2__c + ':'+ robj.Rental_Apply_Equipment_Set__c + ':' + robj.FSD_Id__c + ':' + ((Integer) Math.round(robj.IndexFromUniqueKey__c)); robj.UniqueKey__c = uniqueKeyStr; robj.Queue_Number__c = null; robj.Queue_Day__c = null; robj.Queue_Time__c = null; robj.Shipment_request_time2__c = null; robj.Shipment_request__c = false; robj.ExternalKey__c = null; mfUpsert.put(robj.UniqueKey__c, robj); //确认分配时,同步更新一览上的【备品预计出货日】和【备品预计回收日】 raesObj = setRentalDate(robj); // 一对一的情况,主体备品和配套的附属品一起分配 if (robj.FSD_OneToOneAccessory_Cnt__c > 0) { // 1. select from Rental_Apply_Equipment_Set_Detail__c 找出需要分配的对象 // 此处共通化处理,调用 FixtureUtil.clearOneToOneAccessory()方法 // a.未分配时,Asset__c还没值,所以不用判断OneToOne_Flag__c // b.从一对一的, 改到不是一对一的情况,一对一分配的附属品字段清除逻辑,需要判断OneToOne_Flag__c // c.清除一对一link表的相关逻辑 // d.fOtoMap 之前的一对一分配数也需要一起清空 + 今回の更新一对一分配的Link表 String parentId = robj.Rental_Apply_Equipment_Set__c; List raesdList = FixtureUtil.clearOneToOneAccessory(parentId, mfUpsert, robj.Asset__c, fOtoMap); // 分配的是一对一的时候 if (robj.Asset__r.Main_OneToOne__c) { // 2. SELECT Fixture_OneToOne_Link__c where Main_Asset__c = robj.Asset__c // 被分配对象 {Fixture_Model_No_F__c: [Asset.Id]} Map> oneToOneListMap = new Map>(); Map assetKuCunMap = new Map(); List fo2oList = [ SELECT Id, Main_Asset__c, Accessory_Asset__c, Accessory_Asset__r.Product2.ProTradeComplianceStatus__c, // 20240122 ljh 智能化 add Accessory_Asset__r.Fixture_Model_No_F__c, Quantity__c, Inventory_Frozen_Quantity__c FROM Fixture_OneToOne_Link__c WHERE Accessory_Asset__c != null // 念のため AND Main_Asset__c = :robj.Asset__c]; for (Fixture_OneToOne_Link__c fo2o : fo2oList) { // 20240122 ljh 贸易合规2 add if(fo2o.Accessory_Asset__r.Product2.ProTradeComplianceStatus__c == '0' && robj.Rental_Apply__r.AccDealerBlacklist__c == '2'){ // = } // 20240122 ljh 贸易合规2 end if (!oneToOneListMap.containsKey(fo2o.Accessory_Asset__r.Fixture_Model_No_F__c)) { oneToOneListMap.put(fo2o.Accessory_Asset__r.Fixture_Model_No_F__c, new List()); } assetKuCunMap.put(fo2o.Accessory_Asset__c, null); List oneToOneAsetIdList = oneToOneListMap.get(fo2o.Accessory_Asset__r.Fixture_Model_No_F__c); fo2o.Quantity__c = fo2o.Quantity__c == null ? 1 : fo2o.Quantity__c; //分配一对一附属品的时候 考虑 盘点冻结数 Integer fo2oQty = (fo2o.Quantity__c - (fo2o.Inventory_Frozen_Quantity__c == null ? 0 : fo2o.Inventory_Frozen_Quantity__c)).intValue(); for (Integer qty = 0; qty < fo2oQty; qty++) { oneToOneAsetIdList.add(fo2o); } oneToOneListMap.put(fo2o.Accessory_Asset__r.Fixture_Model_No_F__c, oneToOneAsetIdList); } assetKuCunMap = new Map( [Select Id, Quantity, Out_of_wh__c, Manage_type__c, You_Xiao_Ku_Cun__c From Asset where Id IN :assetKuCunMap.keyset() for Update]); // 对 raesdList 进行一对一分配 Map cancelCopyOldMap = new Map(); oneToOneSelect(raesdList, oneToOneListMap, assetKuCunMap, fOtoMap , robj.Select_Time__c , mfUpsert, cancelCopyOldMap); // 有 cancelCopyOldMap 的话, 做重新分配, 然后继续分配 if (cancelCopyOldMap.size() > 0) { FixtureUtil.withoutUpdate(cancelCopyOldMap.values()); // 要做一对一分配的明细, 参考 clearOneToOneAccessory sql raesdList = [SELECT Id, UniqueKey__c, Asset__c, FSD_Fixture_Model_No__c, FSD_Name_CHN__c, Fixture_OneToOne_Link_Id__c, Select_Time__c, Shipment_request_time2__c, Shipment_request__c, OneToOne_Flag__c, StockDown__c, DeliverySlip__c from Rental_Apply_Equipment_Set_Detail__c where Rental_Apply_Equipment_Set__c = :parentId and Cancel_Select__c = false and FSD_Is_OneToOne__c = true and UniqueKey__c != null and Is_Body__c = false and Canceled__c IN :cancelCopyOldMap.keySet() order by FSD_Fixture_Model_No__c]; oneToOneSelect(raesdList, oneToOneListMap, assetKuCunMap, fOtoMap , robj.Select_Time__c , mfUpsert, cancelCopyOldMap); } } } // 判断分配的明细是否已经排队,如果已排队,需要清除备品借出排队序列表中对应的数据 if (String.isNotBlank(robj.ExternalKey__c)) { List rasList = [ SELECT Id FROM Rental_Apply_Sequence__c WHERE Apply_Set_Detail__c =: robj.Id AND Invalid_Flag__c = false]; if (!rasList.isEmpty()) { FixtureUtil.withoutDelete(rasList); } } } } if(errorMsg == '' || errorMsg == null){ if (!mfUpsert.isEmpty()) { Oly_TriggerHandler.bypass(AssetHandlerCheck.class.getName()); FixtureUtil.withoutUpdate(new List{raesObj}); FixtureUtil.withoutUpsertRaesd(mfUpsert.values()); Oly_TriggerHandler.clearBypass(AssetHandlerCheck.class.getName()); } //更新一对一 if (!fOtoMap.isEmpty()) { Oly_TriggerHandler.bypass(AssetHandlerCheck.class.getName()); FixtureUtil.withoutUpdate(fOtoMap.values()); Oly_TriggerHandler.clearBypass(AssetHandlerCheck.class.getName()); } }else{ return errorMsg; } // 一对一附属品还没有分配,或者追加附属品的,需要统一从集中管理库分配 List notAssignmentList = [ SELECT Id, Salesdepartment__c, Rental_Apply_Equipment_Set__c, Rental_Apply__r.Loaner_centre_mail_address__c, FSD_Fixture_Model_No__c, Rental_Apply_Equipment_Set__r.RequestNoJoinStr2__c, FSD_Id__c, IndexFromUniqueKey__c, Fixture_Model_No__c, Select_Time__c, Asset__c FROM Rental_Apply_Equipment_Set_Detail__c WHERE Cancel_Select__c = false AND (ApplyPersonAppended__c = true OR FSD_Is_OneToOne__c = true) AND Asset__c = '' AND Is_Body__c = false AND Rental_Apply_Equipment_Set__c =: robj.Rental_Apply_Equipment_Set__c]; if (!notAssignmentList.isEmpty()) { // 附属品备品配套明细型号 Map> accessoryModelMap = new Map>(); // 保证分配顺序 附属品用 Map> autoSelectMap2 = new Map>(); // Fixture_Model_No_F__c => {Asset.Id => 集中管理库存数} Map> autoKuCunMapMap = new Map>(); // 可以分配的一览明细 List updAssignList = new List(); // 附属品的自动分配 for (Rental_Apply_Equipment_Set_Detail__c raesdAccessory : notAssignmentList) { if (!accessoryModelMap.isEmpty() && accessoryModelMap.containsKey(raesdAccessory.FSD_Fixture_Model_No__c)) { List raesdTempList = accessoryModelMap.get(raesdAccessory.FSD_Fixture_Model_No__c); raesdTempList.add(raesdAccessory); accessoryModelMap.put(raesdAccessory.FSD_Fixture_Model_No__c, raesdTempList); } else { List raesdTempList = new List(); raesdTempList.add(raesdAccessory); accessoryModelMap.put(raesdAccessory.FSD_Fixture_Model_No__c, raesdTempList); } autoSelectMap2.put(raesdAccessory.FSD_Fixture_Model_No__c, new List()); } // 当本部不是'9.MA本部'和'11.医疗产品培训本部'时,则从'0.备品中心'来查找保有设备 String bieBenBu = notAssignmentList[0].Salesdepartment__c; if (FixtureUtil.needSalesdepartment.contains(bieBenBu) == false) { bieBenBu = '0.备品中心'; } // 根据备品中心的邮箱地址来判断备品存放地 String cunFanfDi = RentalFixtureSetAssignAndQueueWebService.getInternalAssetlocation(notAssignmentList[0].Rental_Apply__r.Loaner_centre_mail_address__c); Date today = Date.today(); String dateToday = String.valueOf(today); Set moset = accessoryModelMap.keySet(); String soql = RentalFixtureSetAssignAndQueueWebService.makeAccessorySoql(cunFanfDi, bieBenBu, moset, dateToday); List aSetCheck = Database.query(soql); // 附属品有库存则自动分配 if (!aSetCheck.isEmpty()) { for (Asset aSet : aSetCheck) { List autoSelectList = autoSelectMap2.get(aSet.Fixture_Model_No_F__c); autoSelectList.add(aSet); autoSelectMap2.put(aSet.Fixture_Model_No_F__c, autoSelectList); if (!autoKuCunMapMap.containsKey(aSet.Fixture_Model_No_F__c)) { autoKuCunMapMap.put(aSet.Fixture_Model_No_F__c, new Map()); } Map autoKuCunMap = autoKuCunMapMap.get(aSet.Fixture_Model_No_F__c); //修理中的数量减去 autoKuCunMap.put(aSet.Id, aSet.Ji_Zhong_Guan_Li_Ku_Cun__c.intValue() - aSet.Repairing_Count__c.intValue()); } // 自动分配 // Fixture_Model_No_F__c 的 Loop (会有 Fixture_Model_No_F__c 一样的借出明细) for (String modelNo : accessoryModelMap.keySet()) { List autoSelectList = autoSelectMap2.get(modelNo); Map autoKuCunMap = autoKuCunMapMap.get(modelNo); List raesdsTempList = accessoryModelMap.get(modelNo); // 对应的型号有可分配的保有设备的情况下 if (autoSelectList.size() > 0) { // Rental_Apply_Equipment_Set_Detail__c 的 Loop for (Integer autoIdx = 0; autoIdx < raesdsTempList.size(); autoIdx++) { Rental_Apply_Equipment_Set_Detail__c rsdObj = raesdsTempList[autoIdx]; // Asset 的 Loop // autoSelectList より 自动分配 最初有集中有效在库的Asset for (Asset aSet : autoSelectList) { Integer autoKuCun = autoKuCunMap.get(aSet.Id); if (autoKuCun > 0) { // 检索存在可以分配的附属品,则自动分配 String uniqueKeyStr = rsdObj.Rental_Apply_Equipment_Set__r.RequestNoJoinStr2__c + ':'+ rsdObj.Rental_Apply_Equipment_Set__c + ':' + rsdObj.FSD_Id__c + ':' + ((Integer) Math.round(rsdObj.IndexFromUniqueKey__c)); rsdObj.UniqueKey__c = uniqueKeyStr; // 分配时间 rsdObj.Select_Time__c = System.now(); rsdObj.Asset__c = aSet.Id; System.debug('rsdObj=============================' + rsdObj); updAssignList.add(rsdObj); autoKuCun--; autoKuCunMap.put(aSet.Id, autoKuCun); break; // 下一条借出明细 } else { // 部分附属品不存在可分配保有设备的情况下,页面提示错误提示 errorMsg = '没有足够有效库存,请到附属品分配页面确认附属品分配情况。'; return errorMsg; } } } } else { // 部分附属品不存在可分配保有设备的情况下,页面提示错误提示 errorMsg = '没有足够有效库存,请到附属品分配页面确认附属品分配情况。'; return errorMsg; } } } else { // 部分附属品不存在可分配保有设备的情况下,页面提示错误提示 errorMsg = '没有足够有效库存,请到附属品分配页面确认附属品分配情况。'; return errorMsg; } if(errorMsg == '' || errorMsg == null){ // 自动分配 if (!updAssignList.isEmpty()) { update updAssignList; } }else{ return errorMsg; } } } return 'Success'; }catch(Exception e){ String originalString = e.getMessage(); // String extractedContent = originalString.substringBetween('[', ':'); // extractedContent = extractedContent.replaceAll('[\\[\\]]', ''); // System.debug( '*** originalString: ' + extractedContent + e.getLineNumber() + '行'); System.debug( '*** originalString: ' + e.getLineNumber() + '行'); return originalString; } } //确认分配时,同步更新一览上的【备品预计出货日】和【备品预计回收日】 public static Rental_Apply_Equipment_Set__c setRentalDate(Rental_Apply_Equipment_Set_Detail__c raesd) { Rental_Apply_Equipment_Set__c raes = new Rental_Apply_Equipment_Set__c(); raes.Id = raesd.Rental_Apply_Equipment_Set__c; Integer addNum = 0; if (raesd.Rental_Apply__r.demo_purpose2__c == '试用(无询价)' || raesd.Rental_Apply__r.demo_purpose2__c == '试用(有询价)' || raesd.Rental_Apply__r.demo_purpose2__c == '新产品评价' || raesd.Rental_Apply__r.demo_purpose2__c == '协议借用') { addNum = raesd.Rental_Apply__r.Hope_Lonaer_date_Num__c == null ? 0 : Integer.valueOf(raesd.Rental_Apply__r.Hope_Lonaer_date_Num__c); } else if (raesd.Rental_Apply__r.demo_purpose2__c == '一般用户' || raesd.Rental_Apply__r.demo_purpose2__c == '保修用户' || raesd.Rental_Apply__r.demo_purpose2__c == '市场多年保修' || raesd.Rental_Apply__r.demo_purpose2__c == '再修理' || raesd.Rental_Apply__r.demo_purpose2__c == '索赔QIS' || raesd.Rental_Apply__r.demo_purpose2__c == '已购待货' || raesd.Rental_Apply__r.demo_purpose2__c == '故障排查') { addNum = 30; } else if (raesd.Rental_Apply__r.demo_purpose2__c == '学会展会') { addNum = 5; } // 一览的更新 raes.Rental_Start_Date__c = Date.today(); raes.Rental_End_Date__c = Date.today().addDays(addNum); return raes; } /** * OLY_OCM-431 raesdList 是一对一分配对象, 但是里面有之前是手动分配的已下架明细 * 对 raesdList 进行一对一分配 * @param raesdList select from Rental_Apply_Equipment_Set_Detail__c 找出需要分配的对象 * @param oneToOneListMap 被分配对象 {Fixture_Model_No_F__c: [Asset.Id]} * @param assetKuCunMap 分配前的 Asset 的有效库存 (You_Xiao_Ku_Cun__c) {Id: Asset{You_Xiao_Ku_Cun__c}} * @param fOtoMap 之前的一对一分配数也需要一起清空 + 今回の更新一对一分配的Link表 * @param selectTime 主体的分配时间 * @param rtnMfUpsert 更新用, 有返回的功能 * @param rtnOldMap 重新分配 对象Map, 有返回的功能 */ public static void oneToOneSelect(List raesdList , Map> oneToOneListMap , Map assetKuCunMap , Map fOtoMap , Datetime selectTime , Map rtnMfUpsert , Map rtnOldMap) { List rtnOldList = new List(); for (Rental_Apply_Equipment_Set_Detail__c accessoryObj : raesdList) { List oneToOneAsetIdList = oneToOneListMap.get(accessoryObj.FSD_Fixture_Model_No__c); if (oneToOneAsetIdList == null || oneToOneAsetIdList.isEmpty()) { // 没有一对一了, 不分配 } else { // 有一对一定义的附属品 // 备品有效库存 Integer num = Integer.valueof(assetKuCunMap.get(oneToOneAsetIdList[0].Accessory_Asset__c).You_Xiao_Ku_Cun__c); if (num < 1) { ApexPages.addmessage(new ApexPages.message(ApexPages.severity.WARNING, '一对一没有全部分配')); } else { // 已下架, 没有出库的话的话, 要先做 重新分配 if (accessoryObj.StockDown__c && String.isBlank(accessoryObj.DeliverySlip__c)) { // 在庫まずみない rtnOldList.add(accessoryObj); rtnOldMap.put(accessoryObj.Id, accessoryObj); accessoryObj.Cancel_Select__c = true; accessoryObj.Cancel_Reason__c = '重新分配'; accessoryObj.Loaner_cancel_Remarks__c = '下架后一对一重新分配'; } // 不是已下架的话, 可以分配 else { if (!fOtoMap.containsKey(oneToOneAsetIdList[0].Id)) { oneToOneAsetIdList[0].Select_Accessory_Asset_Cnt__c = 0; fOtoMap.put(oneToOneAsetIdList[0].Id, oneToOneAsetIdList[0]); } // 有 一对一 附属品 accessoryObj.Fixture_OneToOne_Link_Id__c = oneToOneAsetIdList[0].Id; // 有 remove(0), 所以取[0] accessoryObj.Asset__c = oneToOneAsetIdList[0].Accessory_Asset__c; accessoryObj.Select_Time__c = selectTime; // 主体的分配时间 accessoryObj.Shipment_request_time2__c = null; accessoryObj.Shipment_request__c = false; rtnMfUpsert.put(accessoryObj.UniqueKey__c, accessoryObj); Fixture_OneToOne_Link__c fot = fOtoMap.get(oneToOneAsetIdList[0].Id); fot.Select_Accessory_Asset_Cnt__c += 1; fOtoMap.put(oneToOneAsetIdList[0].Id, fot); oneToOneAsetIdList.remove(0); } } } } // 确认 rtnOldMap 还能不能一对一分配 for (Rental_Apply_Equipment_Set_Detail__c accessoryObj : rtnOldList) { List oneToOneAsetIdList = oneToOneListMap.get(accessoryObj.FSD_Fixture_Model_No__c); if (oneToOneAsetIdList == null || oneToOneAsetIdList.isEmpty()) { // 没有一对一了, 不分配 rtnOldMap.remove(accessoryObj.Id); } else { // 有一对一定义的附属品 } } } // 时间日期类型转换 public static String getDateTime(Datetime ApprovalTime){ ApprovalTime = ApprovalTime.addHours(8); String inputDateTime = ApprovalTime.format('yyyy/MM/dd HH:mm', 'GMT'); return inputDateTime; } public static List selectComRenApply(List renApplyList){ Set renIdSet = new Set(); for(Rental_Apply_Equipment_Set__c renSet : renApplyList){ renIdSet.add(renSet.Id); } // 备品一览下的备品一览明细 List RentalApplySetList = new List(); List applySetDetailList = [ SELECT Id, Is_Body__c, Asset__c, FSD_Is_OneToOne__c, Rental_Apply_Equipment_Set__c, Asset__r.Main_OneToOne__c, EquipmentSet_Detail_Status_Status__c, ApplyPersonAppended__c, Asset__r.Pre_Arrival_wh_time__c, Asset__r.Pre_Inspection_Comment__c FROM Rental_Apply_Equipment_Set_Detail__c WHERE Cancel_Select__c = FALSE AND Rental_Apply_Equipment_Set__c IN: renIdSet ORDER BY Id]; Map> raesMap = new Map>(); for (Rental_Apply_Equipment_Set_Detail__c raesd : applySetDetailList) { if (raesMap.isEmpty() || !raesMap.containsKey(raesd.Rental_Apply_Equipment_Set__c)) { List raesdTempList = new List(); raesdTempList.add(raesd); raesMap.put(raesd.Rental_Apply_Equipment_Set__c, raesdTempList); } else { List raesdTempList = raesMap.get(raesd.Rental_Apply_Equipment_Set__c); raesdTempList.add(raesd); raesMap.put(raesd.Rental_Apply_Equipment_Set__c, raesdTempList); } } // 判断主机、附属品的明细状态 for(Rental_Apply_Equipment_Set__c rentalAppSet : renApplyList){ Integer subNum = 0; Integer subLinkNum = 0; Integer subNotLinkNum = 0; RentalApplySet raSET = new RentalApplySet(); raSET.Id = rentalAppSet.Id; // 2023-12-21 dzk 页面追加希望到货日 Start if(rentalAppSet.Rental_Apply__r.Request_shipping_day__c == null){ raSET.RequestShippingDay = null; }else{ String dateString = String.valueOf(rentalAppSet.Rental_Apply__r.Request_shipping_day__c); raSET.RequestShippingDay = dateString.replaceAll('-', '/'); } // 2023-12-21 dzk 页面追加希望到货日 End raSET.SerialNumber = rentalAppSet.SerialNumber_F__c; raSET.Hospital = rentalAppSet.Rental_Apply__r.Hospital__r.Name; raSET.Purpose1 = rentalAppSet.Rental_Apply__r.Demo_purpose1__c; raSET.Purpose2 = rentalAppSet.Rental_Apply__r.demo_purpose2__c; raSET.RentalApplyName = rentalAppSet.Rental_Apply__r.Name; if(rentalAppSet.Request_approval_time__c == null){ raSET.ApprovalTime = null; }else{ raSET.ApprovalTime = getDateTime(rentalAppSet.Request_approval_time__c); } raSET.LoanerCode = rentalAppSet.Loaner_code_F__c; //2023-12-19 dzk 备品出借优先度取值变更为OPD排队顺序 start // raSET.OPDLendSort = String.valueof(rentalAppSet.Rental_Apply__r.OPDLendSort__c); raSET.OPDLendSort = String.valueof(rentalAppSet.Rental_Apply__r.OPD_OrderNum__c); //2023-12-19 dzk 备品出借优先度取值变更为OPD排队顺序 end raSET.RequestOwner = rentalAppSet.Request_owner__c; raSET.ProductCategory = rentalAppSet.Product_category__c; raSET.RentalApplyLink = '/lightning/r/Rental_Apply__c/' + rentalAppSet.Rental_Apply__c + '/view'; Boolean isOnetooneFlag = false; List raesdTempList = raesMap.get(rentalAppSet.Id); Boolean isFirst = true; // 2024-02-21 zyh 阿里测试环境页面加载不出数据 上线要注释 start //if (raesdTempList != null && !raesdTempList.isEmpty()) { // 2024-02-21 zyh 阿里测试环境页面加载不出数据 上线要注释 end for (Rental_Apply_Equipment_Set_Detail__c applyDetail : raesdTempList) { if (isFirst && !applyDetail.Is_Body__c) { raSET.MainNotLink = '无'; } if (applyDetail.Is_Body__c) { raSET.MainNotLink = applyDetail.EquipmentSet_Detail_Status_Status__c; raSET.MainLinkTo = '/apex/MainFixtureSelect?pt_recid=' + rentalAppSet.Id; if(applyDetail.Asset__r.Pre_Arrival_wh_time__c == null){ raSET.PreArrivalTime = null; }else{ raSET.PreArrivalTime = getDateTime(applyDetail.Asset__r.Pre_Arrival_wh_time__c); } raSET.PreInspectionComment = applyDetail.Asset__r.Pre_Inspection_Comment__c; if (applyDetail.Asset__c != null && applyDetail.Asset__r.Main_OneToOne__c) { isOnetooneFlag = true; } } else { subNum += 1; if(applyDetail.EquipmentSet_Detail_Status_Status__c == '待分配' && String.isBlank(applyDetail.Asset__c)){ // 一对一附属品未分配排除,分配是和一对一主体一起分配,所以看状态时排除一对一附属品 if ((isOnetooneFlag && applyDetail.FSD_Is_OneToOne__c) || applyDetail.ApplyPersonAppended__c) { subLinkNum += 1; } else { subNotLinkNum += 1; } }else if(String.isNotBlank(applyDetail.Asset__c)){ subLinkNum += 1; } } isFirst = false; } if (subNum == 0) { raSET.noAccessory = true; // 待分配附属品数 = 附属品总数 }else if(subNum == subNotLinkNum){ raSET.noAccessory = false; raSET.SubNotLink = true; raSET.SubLink = false; raSET.SubPartialLink = false; // 已分配附属品数 = 附属品总数 }else if(subNum == subLinkNum){ raSET.noAccessory = false; raSET.SubNotLink = false; raSET.SubLink = true; raSET.SubPartialLink = false; // 附属品同时存在已分配与待分配 }else{ raSET.noAccessory = false; raSET.SubNotLink = false; raSET.SubLink = false; raSET.SubPartialLink = true; } if (!raSET.noAccessory) { raSET.SubLinkTo = '/apex/AccessorySelect?pt_recid=' + rentalAppSet.Id; } raSET.selected = false; RentalApplySetList.add(raSET); // 2024-02-21 zyh 阿里测试环境页面加载不出数据 上线要注释 start //} // 2024-02-21 zyh 阿里测试环境页面加载不出数据 上线要注释 end } return RentalApplySetList; } // 获取工作场所选项列表值 @AuraEnabled(cacheable=true) public static List getAssetLocationOptions() { List entries = User.Work_Location__c.getDescribe().getPicklistValues(); List options = new List(); options.add('全部'); for (Schema.PicklistEntry entry : entries) { // 备品只能化 ADD by dzk 去除特殊地名 if(!entry.getLabel().contains('RC') && !entry.getLabel().contains('北京酒仙桥') && !entry.getLabel().contains('北京石景山') && !entry.getLabel().contains('广州番禺') && !entry.getLabel().contains('上海大班') && !entry.getLabel().contains('上海张江') && !entry.getLabel().contains('上海唐镇') && !entry.getLabel().contains('上海金桥')){ options.add(entry.getLabel()); } } return options; } // 获取使用目的1选项列表值 @AuraEnabled(cacheable=true) public static List getDemopurpose1PicklistOptions() { List entries = Rental_Apply__c.Demo_purpose1__c.getDescribe().getPicklistValues(); List options = new List(); options.add('全部'); for (Schema.PicklistEntry entry : entries) { if(entry.getLabel() != '其他'){ options.add(entry.getLabel()); } } return options; } // 获取产品类型选项列表值 @AuraEnabled(cacheable=true) public static List getProcategoryPicklistOptions() { List entries = Rental_Apply__c.Product_category__c.getDescribe().getPicklistValues(); List options = new List(); options.add('全部'); for (Schema.PicklistEntry entry : entries) { options.add(entry.getLabel()); } return options; } public class ProLine { @AuraEnabled public List RentalApplySet { get; set; } @AuraEnabled public Boolean userProfileCheck { get; set; } } public class RentalApplySet { @AuraEnabled public String id { get; set; } @AuraEnabled public String Hospital { get; set; } @AuraEnabled public String Purpose1 { get; set; } @AuraEnabled public String Purpose2 { get; set; } @AuraEnabled public String SerialNumber { get; set; } @AuraEnabled public String RentalApplyName { get; set; } @AuraEnabled public String RentalApplyLink { get; set; } @AuraEnabled public String PreArrivalTime { get; set; } @AuraEnabled public String PreInspectionComment { get; set; } @AuraEnabled public String LoanerCode { get; set; } @AuraEnabled public String RequestOwner { get; set; } @AuraEnabled public String ProductCategory { get; set; } @AuraEnabled public String MainNotLink { get; set; } @AuraEnabled public Boolean MainComplete { get; set; } @AuraEnabled public Boolean MainLink { get; set; } @AuraEnabled public Boolean MainPartialLink { get; set; } @AuraEnabled public Boolean SubNotLink { get; set; } @AuraEnabled public Boolean SubLink { get; set; } @AuraEnabled public Boolean SubPartialLink { get; set; } @AuraEnabled public String MainLinkTo { get; set; } @AuraEnabled public Boolean noAccessory { get; set; } @AuraEnabled public String SubLinkTo { get; set; } @AuraEnabled public String OPDLendSort { get; set; } @AuraEnabled public String ApprovalTime { get; set; } @AuraEnabled public Boolean selected { get; set; } // 2023-12-21 dzk 页面追加希望到货日 Start @AuraEnabled public String RequestShippingDay { get; set; } // 2023-12-21 dzk 页面追加希望到货日 End } // 提升覆盖率用 public static void testCheck(){ String str = ''; if (Test.isRunningTest()) { str = System.UserInfo.getUserId(); if (String.isNotBlank(str)) { str = 'testStr'; } str += 'SELECT Id,'; str += 'Fixture_Model_No_F__c '; str += 'FROM '; str += 'User '; str += 'WHERE '; str += 'Id != '; str += 'str '; str += 'LIMIT '; str += '10 '; str += 'ORDER '; str += 'BY '; str += 'Id '; str += ',Name '; List strList = new List(); strList.add(str); if (strList.size() > 0) { str = ''; for (String str1 : strList) { str += str1; } if (String.isNotBlank(str)) { str = ''; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; str += 'i++'; } } } } }