public without sharing class RentalAgencyReceivedController { public List esdList { get; set; } public String stepName {get;set;} public String qrcode {get;set;} public boolean done_flg {get;set;} public String raId {get;set;} public Boolean readOnly { get; set; } public Boolean stockupActive{get;set;} public String lostResult {get;set;} // 检索用 public String cdsResult {get;set;} // 检索用 private Rental_Apply__c parentObj; private Boolean isSameCity; public String skipId{get;set;} private static final Map DEVELOPERNAMEMAP = Schema.SObjectType.Rental_Apply__c.getRecordTypeInfosByDeveloperName(); public Boolean isAdvocateFollow{get;set;} public Boolean isImportReceiptForm{get;set;} public RentalAgencyReceivedController() { raId = ApexPages.currentPage().getParameters().get('id'); stepName = ''; lostResult = ''; cdsResult = ''; isImportReceiptForm = false; isAdvocateFollow = false; skipId = ''; } private List getDetails() { List raesdList = [ select Id , Rental_Apply_Equipment_Set__c , Asset__r.Product2Id , Asset__r.CountForRepair__c , Asset__r.Abandoned_RealThing__c , Asset__r.You_Xiao_Ku_Cun__c , Asset_return_time__c , Fixture_Model_No__c , SerialNumber_F__c , Arrival_wh_Flag_F__c , Arrival_wh_Abandoned_Flag_F__c , Fixture_Set_Detail__r.Is_OneToOne__c , Is_Body__c , Rental_Apply_Equipment_Set__r.Fixture_Set__r.Name , FSD_OneToOneAccessory_Cnt_F__c , Asset__r.WH_location__c , OneToOne_Flag__c , Fixture_QRCode_F__c , Rental_Apply_Equipment_Set__r.Name , Name, Asset__c, Asset__r.Name, Asset__r.SerialNumber, Asset__r.Product_Serial_No__c , Check_lost_Item__c , Inspection_result_after_F__c , Arrival_in_wh__c , CDS_complete__c , Arrival_wh_Result_Agency__c , Check_lost_Item_Final__c , Check_lost_Item_F__c , Internal_Asset_number_c__c , Return_DeliverySlip__c , DeliverySlip__c , Rental_Apply_Equipment_Set__r.Wei_Arrival_in_wh__c , LastModifiedDate , LastModifiedBy.Name , Lost_item_giveup__c , Internal_asset_location__c , Arrival_wh_time__c , Rental_Apply_Equipment_Set__r.First_RAESD__r.Asset__c , Rental_Apply_Equipment_Set__r.First_RAESD__r.Arrival_wh_Result_Agency__c , Rental_Apply_Equipment_Set__r.First_RAESD__r.Asset__r.You_Xiao_Ku_Cun__c , CanAgencyChangeResult__c , SeparateFromMain__c , Arrival_wh_time_Agency_First__c from Rental_Apply_Equipment_Set_Detail__c where Rental_Apply__c =:raId and ((Shipment_request_time2__c <> null and Cancel_Select__c = False )) order by Rental_Apply_Equipment_Set__r.Name, Rental_Apply_Equipment_Set__c, Is_Body__c DESC, Name ]; return raesdList; } private Map getDetailsMap() { List raesdList = getDetails(); Map raesdMap = new Map(); for(Rental_Apply_Equipment_Set_Detail__c raesd:raesdList) { raesdMap.put(raesd.Id, raesd); } return raesdMap; } // 画面初始化 public PageReference init() { done_flg = false; if (raId != null) { List raList = [ SELECT Id , Name , Yi_loaner_arranged__c , demo_purpose2__c , Asset_loaner_start_day__c , Hope_Lonaer_date_Num__c , Campaign_EndDate_F__c , requestNoJoinStr2__c , Root_Rental_Apply__c , ToAgency__c , StockDown_ng_num__c , DeliverySlip__c , Old_Rental_Apply__c , Split_Apply_Reason__c , HP_received_sign_rich__c , Status__c , Old_Rental_Apply__r.Asset_loaner_start_date__c , Old_Rental_Apply__r.HP_received_sign_rich__c , ShelfUp_ng_num__c , RecordType.Name , RecordType.Id , OwnerId FROM Rental_Apply__c WHERE Id=:raId LIMIT 1 ]; if(raList.isEmpty()) { ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '备品借出申请不存在!')); return null; } parentObj = raList[0]; List owners = [SELECT OCM_man_province_Rental__c FROM User WHERE Id=:parentObj.OwnerId LIMIT 1]; if(owners.isEmpty()) { ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '申请者不存在!')); return null; } else { isSameCity = owners[0].OCM_man_province_Rental__c == parentObj.ToAgency__c; } //wangweipeng 2021/09/03 SFDC-C4H4BM start //查询是否是从单,并且从单是否没有上传签收单 if(raList != null && raList.size() > 0 && isSameCity){ String ra_RecordTypeId = DEVELOPERNAMEMAP.get('AgencyRequest').getRecordTypeId();//获取记录类型 ra_RecordTypeId = ra_RecordTypeId.substring(0,15); for(Rental_Apply__c rac : raList){ //备品签收单是否为空 if(String.isBlank(rac.HP_received_sign_rich__c)){ isImportReceiptForm = true;//当前签收单是否上传签收单 //判断是否为办事处的单子,如果是,那么是从单 String recordTypeId = rac.RecordType.Id; recordTypeId = recordTypeId.substring(0,15); if(ra_RecordTypeId == recordTypeId){ //判断原数据单是否为空,为空和不为空的提示信息不一样 if(String.isBlank(rac.Root_Rental_Apply__c)){ isAdvocateFollow = true; } } break; } } } //wangweipeng 2021/09/03 SFDC-C4H4BM end readOnly = parentObj.ShelfUp_ng_num__c == 0; esdList = getEsdInfos(); this.stockupActive = checkCanChangeResult(esdList, esdList); if (esdList.isEmpty()) { ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '备品借出明细不存在!')); return null; } } return null; } //wangweipeng 2021/09/09 SFDC-C4H4BM start //重定向到 public PageReference redirectPag(){ PageReference ref = new Pagereference('/apex/WebToEquipmentSetShippmentReceived'); ref.setRedirect(true); return ref; } //wangweipeng 2021/09/09 SFDC-C4H4BM end /** * @param locations 存放地 * @return 最新的盘点时间 */ private Datetime getLatestInventoryTime(Set locations) { Datetime latestInventoryTime = System.now().addYears(-100); List headers = [ SELECT Id, CreatedDate FROM Inventory_Header__c WHERE Internal_asset_location__c IN:locations // 盘点没有半途而废的 ORDER BY CreatedDate DESC LIMIT 1 ]; if(!headers.isEmpty()) { latestInventoryTime = headers[0].CreatedDate; } return latestInventoryTime; } /** * @description 获取调拨信息 * @param assetIdSet 全部的设备Id * @param earliestStockinTime 回库最早的时间 * @return {设备Id:{调拨类型:数量}} */ private Map> getTransferCount(Set assetIdSet, Datetime earliestStockinTime) { Map> resultMap = new Map>(); AggregateResult[] aggs = [ select Asset__c,TransferType__c , count(id) cnt from TransferApplyDetail__c where Cancel_Select__c = false AND CreatedDate >=: earliestStockinTime // 回库开始后的所有未取消的调拨都要考虑 AND Asset__c IN: assetIdSet group by Asset__c,TransferType__c ]; for(AggregateResult agg:aggs) { Id assetId = (Id) agg.get('Asset__c'); String transferType = String.valueOf(agg.get('TransferType__c')); Integer cnt = Integer.valueOf(agg.get('cnt')); if(!resultMap.containsKey((assetId))) { resultMap.put(assetId, new Map()); } resultMap.get(assetId).put(transferType, cnt); } return resultMap; } private List getEsdInfos() { List esdList1 = new List(); // 备品set明细 List eList = getDetails(); for (Rental_Apply_Equipment_Set_Detail__c esd : eList) { EsdInfo ei = new EsdInfo(esd); // 同城的发货后可编辑 if(isSameCity) { ei.editable = esd.DeliverySlip__c != null && !esd.Lost_item_giveup__c; } // 非同城回寄后可编辑 else { ei.editable = (esd.Return_DeliverySlip__c != null || String.isNotBlank(esd.Check_lost_Item_F__c)) && !esd.Lost_item_giveup__c; } esdList1.add(ei); } return esdList1; } /** * @description 库存及调拨情况检查 * @param esdBase 数据库里明细 * @param esdPage 画面上的明细 * @param transferCountMap {设备Id:{调拨类型:数量}}各设备的调拨类型及数量 * @param otherLinkCountMap {设备Id:{调拨类型:数量}}各设备的背景link数量 * @param linkChangeMap 附属品理论上要建的link * @param resultChangeMap {设备Id:{调拨类型:修改的数量}}用作返回值,存储各设备的变更类型及数量 * */ private void checkCanChangeLinkByTransfer(EsdInfo esdBase, EsdInfo esdPage, Map> transferCountMap, Map> otherLinkCountMap, Map> linkChangeMap, Map> resultChangeMap ) { String assetFieldApiAfter = ''; String transferTypeAfter = ''; String assetFieldApiBefore = ''; String transferTypeBefore = ''; // 建link要以画面为准 switch on esdPage.rec.Arrival_wh_Result_Agency__c { when 'OK' { assetFieldApiAfter = 'You_Xiao_Ku_Cun__c'; transferTypeAfter = '有效库存'; } when '移至报废区' { assetFieldApiAfter = 'Abandoned_RealThing__c'; transferTypeAfter = '待废弃'; } when '待修理' { assetFieldApiAfter = 'CountForRepair__c'; transferTypeAfter = '待修理'; } } switch on esdBase.rec.Arrival_wh_Result_Agency__c { when 'OK' { assetFieldApiBefore = 'You_Xiao_Ku_Cun__c'; transferTypeBefore = '有效库存'; } when '移至报废区' { assetFieldApiBefore = 'Abandoned_RealThing__c'; transferTypeBefore = '待废弃'; } when '待修理' { assetFieldApiBefore = 'CountForRepair__c'; transferTypeBefore = '待修理'; } } // 没有选回库结果的或首次回库不用判 if(String.isBlank(assetFieldApiAfter)) { return ; } if (esdBase.rec.OneToOne_Flag__c) { esdPage.needLink = true; String otoKey = esdBase.rec.Asset__c; if(!linkChangeMap.containsKey(otoKey)) { linkChangeMap.put(otoKey, new Map{'有效库存'=>0, '待废弃' => 0, '待修理' => 0}); } Integer cnt = linkChangeMap.get(otoKey).get(transferTypeAfter) + 1; linkChangeMap.get(otoKey).put(transferTypeAfter, cnt); // 已回库未回库明细都要检查是否可创建link if(esdBase.rec.Rental_Apply_Equipment_Set__r.First_RAESD__r.Arrival_wh_Result_Agency__c == 'OK' && esdBase.rec.Rental_Apply_Equipment_Set__r.First_RAESD__r.Asset__r.You_Xiao_Ku_Cun__c <= 0) { esdPage.needLink = esdBase.rec.Arrival_in_wh__c && !esdBase.rec.SeparateFromMain__c; } else if(transferCountMap.containsKey(esdBase.rec.Rental_Apply_Equipment_Set__r.First_RAESD__r.Asset__c)) { esdPage.needLink = esdBase.rec.Arrival_in_wh__c && !esdBase.rec.SeparateFromMain__c; } else if(transferCountMap.containsKey(esdBase.rec.Asset__c) && transferCountMap.get(esdBase.rec.Asset__c).containsKey(transferTypeBefore) ) { Integer otherLinkCount = 0; if (otherLinkCountMap.containsKey(esdBase.rec.Asset__c) && otherLinkCountMap.get(esdBase.rec.Asset__c).containsKey(transferTypeBefore)) { otherLinkCount = otherLinkCountMap.get(esdBase.rec.Asset__c).get(transferTypeBefore); } Integer changeCount = 0; if (resultChangeMap.containsKey(esdBase.rec.Asset__c) && resultChangeMap.get(esdBase.rec.Asset__c).containsKey(transferTypeBefore)) { changeCount = resultChangeMap.get(esdBase.rec.Asset__c).get(transferTypeBefore); } if(esdBase.rec.Arrival_wh_Result_Agency__c == esdPage.rec.Arrival_wh_Result_Agency__c) { // 先上架5个废弃,然后调拨2个废弃,又修改回库把1个废弃改成其它,则能建link的有3个, esdPage.needLink = cnt <= Integer.valueOf(esdBase.rec.Asset__r.get(assetFieldApiBefore)) - transferCountMap.get(esdBase.rec.Asset__c).get(transferTypeBefore) - changeCount - otherLinkCount ; } } } } /** * @description 库存及调拨情况检查 * @param esdBase 数据库里明细 * @param esdPage 画面上的明细 * @param transferCountMap {设备Id:{调拨类型:数量}}各设备的调拨类型及数量 * @param otherLinkCountMap {设备Id:{调拨类型:数量}}各设备的背景link数量 * @param resultChangeMap {设备Id:{调拨类型:修改的数量}}用作返回值,存储各设备的变更类型及数量 * */ private void checkCanChangeResultByTransfer(EsdInfo esdBase, EsdInfo esdPage, Map> transferCountMap, Map> otherLinkCountMap, Map> resultChangeMap) { String assetFieldApi = ''; String transferType = ''; // 修改结果要以数据库里的结果为准 switch on esdBase.rec.Arrival_wh_Result_Agency__c { when 'OK' { assetFieldApi = 'You_Xiao_Ku_Cun__c'; transferType = '有效库存'; } when '移至报废区' { assetFieldApi = 'Abandoned_RealThing__c'; transferType = '待废弃'; } when '待修理' { assetFieldApi = 'CountForRepair__c'; transferType = '待修理'; } } if(String.isBlank(assetFieldApi)) { return ; } if(!resultChangeMap.containsKey(esdBase.rec.Asset__c)) { resultChangeMap.put(esdBase.rec.Asset__c, new Map()); } Integer cnt = 0; if(resultChangeMap.get(esdBase.rec.Asset__c).containsKey(transferType)) { cnt = resultChangeMap.get(esdBase.rec.Asset__c).get(transferType); } if(esdPage.rec.Arrival_wh_Result_Agency__c != esdBase.rec.Arrival_wh_Result_Agency__c) { resultChangeMap.get(esdBase.rec.Asset__c).put(transferType, cnt + 1); } if(esdBase.rec.Rental_Apply_Equipment_Set__r.First_RAESD__r.Arrival_wh_Result_Agency__c == 'OK' && esdBase.rec.Rental_Apply_Equipment_Set__r.First_RAESD__r.Asset__r.You_Xiao_Ku_Cun__c <= 0 && esdBase.rec.Arrival_in_wh__c && !esdBase.rec.SeparateFromMain__c) { esdBase.canChangeResult = false; esdPage.errorInfo = esdBase.rec.Fixture_Model_No__c + ':配套已被分配,不可修改回库结果'; } else if(transferCountMap.containsKey(esdBase.rec.Rental_Apply_Equipment_Set__r.First_RAESD__r.Asset__c) && esdBase.rec.Arrival_in_wh__c && !esdBase.rec.SeparateFromMain__c) { esdBase.canChangeResult = false; esdPage.errorInfo = esdBase.rec.Fixture_Model_No__c + ':配套已被调拨,不可以修改回库结果'; } else if(Integer.valueOf(esdBase.rec.Asset__r.get(assetFieldApi)) <= 0) { esdBase.canChangeResult = false; esdPage.errorInfo = esdBase.rec.Fixture_Model_No__c + ':保有设备里'+ transferType +'数不足,不可修改回库结果'; } // 变化数量 与 调拨里的数量 + 背景link数量 比较 else if(transferCountMap.containsKey(esdBase.rec.Asset__c) && transferCountMap.get(esdBase.rec.Asset__c).containsKey(transferType)) { Integer available = Integer.valueOf(esdBase.rec.Asset__r.get(assetFieldApi)) - Integer.valueOf(transferCountMap.get(esdBase.rec.Asset__c).get(transferType)); if (otherLinkCountMap.containsKey(esdBase.rec.Asset__c) && otherLinkCountMap.get(esdBase.rec.Asset__c).containsKey(transferType)) { available -= otherLinkCountMap.get(esdBase.rec.Asset__c).get(transferType); } // 所有有效库存/待废弃数/待修理数都被调拨 if(available <= 0) { esdBase.canChangeResult = false; esdPage.errorInfo = esdBase.rec.Fixture_Model_No__c + ':已被调拨,不可修改回库结果'; } // 有效库存/待废弃数/待修理数部分调拨,需要保证修改的数量不能超过库存数减去调拨数 // 例如有效库存有5个,调拨有3个,这个设备在回库画面上有5条借出明细, // 显示时5条都是可编辑的,但至多改动其中2条 else if(resultChangeMap.get(esdBase.rec.Asset__c).get(transferType) > available) { esdPage.errorInfo = esdBase.rec.Fixture_Model_No__c + ':有调拨明细,只可以把' + available + '条' + '从【' + esdBase.rec.Arrival_wh_Result_Agency__c + '】' + '改成其它选项'; } } // 需要保证修改的数量不能超过库存数 // 例如有效库存有2个,这个设备在回库画面上有5条借出明细, // 显示时5条都是可编辑的,但至多改动其中2条 else if(Integer.valueOf(esdBase.rec.Asset__r.get(assetFieldApi)) < resultChangeMap.get(esdBase.rec.Asset__c).get(transferType)) { esdPage.errorInfo = esdBase.rec.Fixture_Model_No__c + ':最多可以把' + Integer.valueOf(esdBase.rec.Asset__r.get(assetFieldApi)) + '条' + '从【' + esdBase.rec.Arrival_wh_Result_Agency__c + '】改成其它选项'; } } /** * @description 对数据库里明细做检查,并将检查结果反映在画面上 * @param esdListBase 数据库里的 * @param esdListPage 画面上的 * @return 回库按钮是否可点击。只要有可以修改的,就返回true * */ private Boolean checkCanChangeResult(List esdListBase, List esdListPage) { Boolean canChange = false; Datetime now = System.now(); Datetime earliestStockinTime = System.now(); Set locations = new Set (); Set assetIdSet = new Set(); // Set assetIdSetChecked = new Set(); // 勾选配套里的 Set updateRas = new Set (); Boolean allEmpty = true; for(Integer i = 0; i < esdListBase.size(); i++ ) { EsdInfo esdBase = esdListBase[i]; EsdInfo esdPage = esdListPage[i]; esdPage.errorInfo = ''; if(esdBase.rec.Id != esdPage.rec.Id) { esdPage.errorInfo = esdBase.rec.Fixture_Model_No__c + '后台数据不存在,请刷新画面!'; } if(esdBase.rec.LastModifiedDate != esdPage.rec.LastModifiedDate) { esdPage.errorInfo = esdBase.rec.Fixture_Model_No__c + '后台数据被 ' + esdBase.rec.LastModifiedBy.Name + ' 修改,请刷新画面!'; } locations.add(esdBase.rec.Internal_asset_location__c); allEmpty = allEmpty && String.isBlank(esdBase.rec.Arrival_wh_Result_Agency__c); assetIdSet.add(esdBase.rec.Asset__c); if(esdPage.rec.Is_Body__c && esdPage.checked) { updateRas.add(esdPage.rec.Rental_Apply_Equipment_Set__c); } if(updateRas.contains(esdPage.rec.Rental_Apply_Equipment_Set__c)) { assetIdSetChecked.add(esdPage.rec.Asset__c); } if(esdBase.rec.Arrival_wh_time_Agency_First__c != null) { if(esdBase.rec.Arrival_wh_time_Agency_First__c < earliestStockinTime) { earliestStockinTime = esdBase.rec.Arrival_wh_time_Agency_First__c; } } } if(allEmpty) { return true; } Datetime latestInventoryTime = getLatestInventoryTime(locations); Map> transferCountMap = getTransferCount(assetIdSet, earliestStockinTime); Map> resultChangeMap = new Map>(); // 要修改的回库结果 Map> otherLinkCountMap = getOtherLinkCount(assetIdSetChecked); Map> linkChangeMap = new Map>(); // 要更新的link for(Integer i = 0; i < esdListBase.size(); i++ ) { EsdInfo esdBase = esdListBase[i]; EsdInfo esdPage = esdListPage[i]; // 是否回库超2天 if(!esdBase.rec.CanAgencyChangeResult__c && esdBase.rec.Arrival_wh_time__c != null) { esdBase.canChangeResult = false; esdPage.errorInfo = '已超过回库后两个工作日,不可修改回库结果'; } // 是否有过盘点 if(String.isNotBlank(esdBase.rec.Arrival_wh_Result_Agency__c) && latestInventoryTime >= esdBase.rec.Arrival_wh_time__c) { esdBase.canChangeResult = false; esdPage.errorInfo = '已开始新的盘点,不可修改回库结果'; } checkCanChangeResultByTransfer(esdBase, esdPage, transferCountMap, otherLinkCountMap, resultChangeMap); canChange = esdBase.canChangeResult || canChange; } // 回库结果修改会影响到设备里的废弃数,必须等全部的变化情况统计完成后,再判断要不要建link for(Integer i = 0; i < esdListBase.size(); i++ ) { EsdInfo esdBase = esdListBase[i]; EsdInfo esdPage = esdListPage[i]; // 已上过架的附属品都有被调拨的可能,都要重新判一次要不要建link if (updateRas.contains(esdBase.rec.Rental_Apply_Equipment_Set__c) && esdBase.rec.OneToOne_Flag__c) { checkCanChangeLinkByTransfer(esdBase, esdPage, transferCountMap, otherLinkCountMap, linkChangeMap, resultChangeMap); } } return canChange; } /** * @description 查出勾选配套里附属品的后台link情况(不包括当前配套已生成的link) * @param assetIdSetChecked 勾选配套里的设备Id * @return {附属品Id:{类型:数量}} * */ private Map> getOtherLinkCount(Set assetIdSetChecked) { List links = [ SELECT Id,Abandoned_RealThing__c,CountForRepair__c,Quantity__c, Accessory_Asset__c FROM Fixture_OneToOne_Link__c WHERE Main_Asset__c NOT IN:assetIdSetChecked AND Accessory_Asset__c IN:assetIdSetChecked AND (Abandoned_RealThing__c > 0 OR CountForRepair__c > 0) ]; Map> resultMap = new Map>(); for(Fixture_OneToOne_Link__c link : links) { if(!resultMap.containsKey(link.Accessory_Asset__c)) { resultMap.put(link.Accessory_Asset__c, new Map{'有效库存' => 0, '待废弃' => 0, '待修理' => 0 }); } Integer fei = intValueOf(link.Abandoned_RealThing__c); Integer xiu = intValueOf(link.CountForRepair__c); Integer you = intValueOf(link.Quantity__c - fei - xiu); resultMap.get(link.Accessory_Asset__c).put('有效库存', fei + resultMap.get(link.Accessory_Asset__c).get('有效库存')); resultMap.get(link.Accessory_Asset__c).put('待废弃', fei + resultMap.get(link.Accessory_Asset__c).get('待废弃')); resultMap.get(link.Accessory_Asset__c).put('待修理', xiu + resultMap.get(link.Accessory_Asset__c).get('待修理')); } return resultMap; } // 检索按钮 public void filter() { for(EsdInfo esd:esdList) { if(stringEquals(esd.lostFinished, lostResult) && stringEquals(esd.cdsFinished, cdsResult)) { esd.hidden = false; } else { esd.hidden = true; } } } /** @param s1 明细字段值 @param s2 画面选择值 @return 一样则返回true, null和'' 也为true @description */ private Boolean stringEquals(String s1, String s2) { // 画面选择值为空时,不用作筛选条件,恒为true if(String.isBlank(s2)) { return true; } else{ return s2.equals(s1); } } // 清除按钮 public void clearFilter() { lostResult = ''; cdsResult = ''; for(EsdInfo esd:esdList) { esd.hidden = false; } } // 回库按钮 public void stockup() { done_flg = false; Datetime now = System.now(); Id userId = Userinfo.getUserId(); Boolean hasChecked = false; Savepoint sp = Database.setSavepoint(); try { List dateList = [SELECT Date__c, After_2_WorkDay__c FROM OlympusCalendar__c WHERE Date__c=:now.date() LIMIT 1]; if(dateList.isEmpty() || dateList[0].After_2_WorkDay__c == null) { ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '日历数据不存在!')); return; } Date afterTwoWorkday = dateList[0].After_2_WorkDay__c; Map updateRaesdMap = new Map(); //Map raesdMap = getDetailsMap(); // 取最新的明细数据 List esdListBase = getEsdInfos(); // 取最新的明细数据做检查 checkCanChangeResult(esdListBase, esdList); Map raesIdMainMap = new Map (); // 一览Id->主体Id, 用于构建一览内的link Set assIdSet = new Set(); // 明细所连的asset,用于加锁 Map newLinkMap = new Map(); // 主Id:附Id->新link for(Integer i = 0; i < esdList.size();i++) { EsdInfo esd = esdList[i]; if((esd.checked || raesIdMainMap.containsKey(esd.rec.Rental_Apply_Equipment_Set__c)) && !esd.hidden) { hasChecked = true; Rental_Apply_Equipment_Set_Detail__c raesd = esdListBase[i].rec; assIdSet.add(raesd.Asset__c); // 回库确认 if(raesd.Arrival_wh_Result_Agency__c != esd.rec.Arrival_wh_Result_Agency__c) { if(String.isBlank(raesd.Check_lost_Item_F__c) || !raesd.CDS_complete__c) { ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, raesd.Fixture_Model_No__c + '未完成欠品确认&CDS,不可回库!')); return; } if(String.isBlank(esd.rec.Arrival_wh_Result_Agency__c)) { ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, raesd.Fixture_Model_No__c + '回库结果不可为空!')); return; } if(String.isNotBlank(esdList[i].errorInfo)) { ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, esdList[i].errorInfo)); return; } raesd.Arrival_wh_Result_Agency__c = esd.rec.Arrival_wh_Result_Agency__c; if(raesd.Arrival_wh_Result_Agency__c == 'OK') { raesd.Inspection_result_after__c = 'OK'; raesd.Inspection_result_after_NG__c = null; raesd.After_Inspection_time__c = now; raesd.Inspection_staff_After__c = userId; } else if(raesd.Arrival_wh_Result_Agency__c == '移至报废区') { raesd.Inspection_result_after__c = 'NG'; raesd.Inspection_result_after_NG__c = '废弃'; raesd.After_Inspection_time__c = now; raesd.Inspection_staff_After__c = userId; } else if(raesd.Arrival_wh_Result_Agency__c == '待修理') { raesd.Inspection_result_after__c = 'NG'; raesd.Inspection_result_after_NG__c = '维修'; raesd.After_Inspection_time__c = now; raesd.Inspection_staff_After__c = userId; } if(!raesd.Arrival_in_wh__c) { raesd.Arrival_in_wh__c = true; raesd.Arrival_wh_time_Agency_First__c = now; raesd.Arrival_wh_After_2_Workday__c = afterTwoWorkday; raesd.Return_wh_chenk_staff__c = userid; } raesd.Arrival_wh_time__c = now; updateRaesdMap.put(raesd.Id, raesd); } if(raesd.OneToOne_Flag__c && raesd.SeparateFromMain__c == esd.needLink) { raesd.SeparateFromMain__c = !esd.needLink; updateRaesdMap.put(raesd.Id, raesd); } // 需要建link的主体 if(raesd.Is_Body__c){ raesIdMainMap.put(esd.rec.Rental_Apply_Equipment_Set__c, raesd); } // 每次回库时都会根据当前回库情况,重新刷一遍 if(raesd.OneToOne_Flag__c) { // 获取主体明细 Rental_Apply_Equipment_Set_Detail__c mainRaesd = null; if(raesIdMainMap.containsKey(raesd.Rental_Apply_Equipment_Set__c)) { mainRaesd = raesIdMainMap.get(raesd.Rental_Apply_Equipment_Set__c); } if(mainRaesd != null) { // 主体和附属品都cds完成,但上架不一致,报错 if(mainRaesd.CDS_complete__c && raesd.CDS_complete__c && mainRaesd.Arrival_in_wh__c != raesd.Arrival_in_wh__c) { ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, mainRaesd.Fixture_Model_No__c + '必须整套上架!')); return; } String key = mainRaesd.Asset__c + ':' + raesd.Asset__c; Fixture_OneToOne_Link__c link; if(newLinkMap.containsKey(key)) { link = newLinkMap.get(key); } else { link = new Fixture_OneToOne_Link__c(Quantity__c=0, CountForRepair__c=0, Abandoned_RealThing__c=0); } // 主体废弃或修理,附属品只要上架就建link if((mainRaesd.Arrival_wh_Result_Agency__c == '移至报废区' || mainRaesd.Arrival_wh_Result_Agency__c == '待修理') && !raesd.SeparateFromMain__c) { link.Quantity__c += 1; // 附属不OK时,占用link的一对一附属品管理数量 switch on raesd.Arrival_wh_Result_Agency__c { when '待修理' { link.CountForRepair__c += 1; } when '移至报废区' { link.Abandoned_RealThing__c += 1; } } } // 主体OK,附属品只有OK才建link else if(mainRaesd.Arrival_wh_Result_Agency__c == 'OK' && raesd.Arrival_wh_Result_Agency__c == 'OK' && !raesd.SeparateFromMain__c) { link.Quantity__c += 1; } // 主体欠品但没放弃,附属品只有OK才建link else if(mainRaesd.Check_lost_Item_F__c == '欠品' && !mainRaesd.Lost_item_giveup__c && raesd.Arrival_wh_Result_Agency__c == 'OK' && !raesd.SeparateFromMain__c) { link.Quantity__c += 1; } else { raesd.SeparateFromMain__c = true; updateRaesdMap.put(raesd.Id, raesd); } newLinkMap.put(key, link); } } } } if(!hasChecked) { ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '未选择操作的一览')); return; } Oly_TriggerHandler.bypass(AssetHandlerCheck.class.getName()); if(!updateRaesdMap.isEmpty()) { List assList = [SELECT Id FROM Asset WHERE Id IN:assIdSet FOR UPDATE]; FixtureUtil.withoutUpdate(updateRaesdMap.values()); //print('更新明细',updateRaesdMap); done_flg = true; } if(!newLinkMap.isEmpty()) { createLinks(newLinkMap); done_flg = true; } Oly_TriggerHandler.clearBypass(AssetHandlerCheck.class.getName()); if(done_flg) { init(); done_flg = true; } //print('更新后Asset',[SELECT Id // , Name // , You_Xiao_Ku_Cun__c // , Abandoned_RealThing__c // , CountForRepair__c // , In_wh_Fu_Shu_Pin_You_Xiao_Ku_Cun_Sum__c // , Ji_Zhong_Guan_Li_Ku_Cun__c // , Rental_Count__c // FROM Asset WHERE Id IN:assIdSet]); //print('更新后link',[ // SELECT Id // , Quantity__c // , In_wh_Fu_Shu_Pin_You_Xiao_Ku_Cun_F__c // , Accessory_Asset__r.Name // , Abandoned_RealThing__c // , CountForRepair__c // , Select_Accessory_Asset_Cnt__c // FROM Fixture_OneToOne_Link__c // WHERE Main_Asset__c IN:assIdSet // AND Accessory_Asset__c IN:assIdSet]); //Database.rollback(sp); } catch (Exception ex) { system.debug('=====' + ex.getMessage()); ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, ex.getMessage())); Database.rollback(sp); done_flg = false; } } /** @description 新建link或向已有的link加数量 @param newLinkMap 主Id:附Id->待新建的link */ private void createLinks(Map newLinkMap) { Set mainIdSet = new Set(); // 收集主体Id for(String otoKey:newLinkMap.keySet()) { String mainId = otoKey.split(':')[0]; mainIdSet.add(mainId); } Map assMap = new Map([ SELECT Id , You_Xiao_Ku_Cun__c , Abandoned_RealThing__c , CountForRepair__c , Last_Reserve_RAES_Detail__r.Rental_Apply__c FROM Asset WHERE Id IN:mainIdSet ]); Set uselessKey = new Set(); // 检查主体保有设备是否可以建link for(String otoKey:newLinkMap.keySet()) { String mainId = otoKey.split(':')[0]; if(!assMap.containsKey(mainId)) { throw new ControllerUtil.myException(mainId + '保有设备不存在!'); } else { Asset ass = assMap.get(mainId); // 主体保有设备有库存时才建link if(ass.Last_Reserve_RAES_Detail__r.Rental_Apply__c != parentObj.Id && intValueOf(ass.You_Xiao_Ku_Cun__c) + intValueOf(ass.Abandoned_RealThing__c) + intValueOf(ass.CountForRepair__c) == 0) { uselessKey.add(otoKey); } } } // 主体没库存时,上架后不用建link for(String otoKey: uselessKey) { newLinkMap.remove(otoKey); } if(newLinkMap.isEmpty()) { return; } Map linkMap = new Map(); // 主Id:附Id->link对象 Map deleteLinkMap = new Map(); // 主Id:附Id->link对象 String linkSql = 'SELECT Quantity__c, Abandoned_RealThing__c, CountForRepair__c, Main_Asset__c, Accessory_Asset__c FROM Fixture_OneToOne_Link__c WHERE '; for(String otoKey:newLinkMap.keySet()) { String mainId = otoKey.split(':')[0]; String acceId = otoKey.split(':')[1]; linkSql += '(Main_Asset__c = \'' + mainId + '\' AND Accessory_Asset__c = \''+acceId+'\') OR'; } linkSql = linkSql.removeEnd('OR'); List matchingLinks = Database.query(linkSql); for(Fixture_OneToOne_Link__c link: matchingLinks) { linkMap.put(link.Main_Asset__c + ':' + link.Accessory_Asset__c, link); } for(String otoKey: newLinkMap.keySet()) { Fixture_OneToOne_Link__c link = new Fixture_OneToOne_Link__c(); // 修改现有link里的数量,如果数量完全一致跳过更新 if(linkMap.containsKey(otoKey)) { link = linkMap.get(otoKey); if(link.Quantity__c != newLinkMap.get(otoKey).Quantity__c || link.Abandoned_RealThing__c != newLinkMap.get(otoKey).Abandoned_RealThing__c || link.CountForRepair__c != newLinkMap.get(otoKey).CountForRepair__c) { link.Quantity__c = newLinkMap.get(otoKey).Quantity__c; link.Abandoned_RealThing__c = newLinkMap.get(otoKey).Abandoned_RealThing__c; link.CountForRepair__c = newLinkMap.get(otoKey).CountForRepair__c; } else { linkMap.remove(otoKey); continue; } } // 新建link else { link.Main_Asset__c = otoKey.split(':')[0]; link.Accessory_Asset__c = otoKey.split(':')[1]; link.Quantity__c = newLinkMap.get(otoKey).Quantity__c; link.Abandoned_RealThing__c = newLinkMap.get(otoKey).Abandoned_RealThing__c; link.CountForRepair__c = newLinkMap.get(otoKey).CountForRepair__c; } if(link.Quantity__c == 0) { if(link.Id != null) { deleteLinkMap.put(otoKey, link); } linkMap.remove(otoKey); } else { linkMap.put(otoKey, link); } } if(!deleteLinkMap.isEmpty()) { FixtureUtil.withoutDelete(deleteLinkMap.values()); } if(!linkMap.isEmpty()) { //print('更新link',linkMap); FixtureUtil.withoutUpsertObjects(linkMap.values()); } } private Integer intValueOf(Decimal d) { if(d == null) { return 0; } return Integer.valueOf(d); } // 欠品确认&CDS按钮 public void lostAndCDS() { done_flg = false; Map updateRaesdMap = new Map(); Map raesdMap = getDetailsMap(); // 取最新的明细数据 Set raesIdSet = new Set(); Boolean hasChecked = false; Datetime now = System.now(); for(EsdInfo esd:esdList) { if((esd.checked || raesIdSet.contains(esd.rec.Rental_Apply_Equipment_Set__c)) && !esd.hidden) { hasChecked = true; if(!raesdMap.containsKey(esd.rec.Id)) { ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, esd.rec.Fixture_Model_No__c + '后台数据不存在,请刷新画面!')); return; } raesIdSet.add(esd.rec.Rental_Apply_Equipment_Set__c); Rental_Apply_Equipment_Set_Detail__c raesd = raesdMap.get(esd.rec.Id); if(raesd.LastModifiedDate != esd.rec.LastModifiedDate) { ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, esd.rec.Fixture_Model_No__c + '后台数据被 ' + raesd.LastModifiedBy.Name + ' 修改,请刷新画面!')); return; } // 欠品最初是空或OK时,修改结果存到最初 if(String.isBlank(raesd.Check_lost_Item__c) || raesd.Check_lost_Item__c == 'OK') { if(esd.lostFinished != raesd.Check_lost_Item__c) { raesd.Check_lost_Item__c = esd.lostFinished; // 同城首次欠品时,记入回寄时间,使状态变成欠品中 if(isSameCity && raesd.Check_lost_Item__c == '欠品' && raesd.Asset_return_time__c == null) { raesd.Asset_return_time__c = now; } } } // 欠品最初是欠品时,修改结果存到最终 else if(esd.lostFinished != raesd.Check_lost_Item_F__c) { if(esd.lostFinished == 'OK' && raesd.Return_DeliverySlip__c == null && !isSameCity) { ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, esd.rec.Fixture_Model_No__c + '未回寄,欠品确认不可选OK')); return; } else { raesd.Check_lost_Item_Final__c = esd.lostFinished; } } // 画面上的CDS与后台不一致时更新 if(!raesd.CDS_complete__c && esd.cdsFinished == 'OK' ) { raesd.CDS_complete__c = true; // 人和时间在trigger里赋值 } else if(raesd.CDS_complete__c && esd.cdsFinished != 'OK') { raesd.CDS_complete__c = false; raesd.CDS_complete_time__c = null; raesd.CDS_staff__c = null; } if (String.isNotBlank(raesd.Check_lost_Item_Final__c)) { if (raesd.Check_lost_Item_Final__c == '欠品' || raesd.Check_lost_Item_Final__c == '消耗' ) { raesd.Return_DeliverySlip__c = null; raesd.CDS_complete__c = false; if (raesd.Check_lost_Item_Final__c == '欠品') raesd.NoItemReturn__c = false; } } else { raesd.Lost_item_check_staff_Final__c = null; raesd.Lost_item_check_time_Final__c = null; if (raesd.Check_lost_Item__c == '欠品' || raesd.Check_lost_Item__c == '消耗' ) { raesd.Return_DeliverySlip__c = null; raesd.CDS_complete__c = false; if (raesd.Check_lost_Item__c == '欠品') raesd.NoItemReturn__c = false; } if (String.isBlank(raesd.Check_lost_Item__c)) { raesd.Lost_item_check_staff__c = null; raesd.Lost_item_check_time__c = null; } } if (raesd.Lost_item_giveup__c && raesd.Check_lost_Item__c == null) { raesd.Check_lost_Item__c = '欠品'; raesd.Return_DeliverySlip__c = null; } updateRaesdMap.put(raesd.Id, raesd); } } if(!hasChecked) { ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '未选择操作的一览')); return; } Savepoint sp = Database.setSavepoint(); try { if(!updateRaesdMap.isEmpty()) { createReturnDelivery(updateRaesdMap); FixtureUtil.withoutUpdate(updateRaesdMap.values()); init(); done_flg = true; //Database.rollback(sp); } } catch (Exception ex) { system.debug('=====' + ex.getMessage()); ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, ex.getMessage())); Database.rollback(sp); } } /** @description 回寄单字段赋值或清空 @param updateRaesdMap 待更新的明细 */ private void createReturnDelivery(Map updateRaesdMap) { Boolean needDummy = false; for(Id raesdId: updateRaesdMap.keySet()) { Rental_Apply_Equipment_Set_Detail__c raesd = updateRaesdMap.get(raesdId); String lost = ''; if(String.isNotBlank(raesd.Check_lost_Item_Final__c)) { lost = raesd.Check_lost_Item_Final__c; } else { lost = raesd.Check_lost_Item__c; } if(lost == 'OK' && raesd.Return_DeliverySlip__c == null && (isSameCity || raesd.NoItemReturn__c)) { needDummy = true; break; } } FixtureDeliverySlip__c slip; Datetime now = System.now(); if(needDummy) { String slipNo = parentObj.Name + '_Dummy'; List slips = [ SELECT Id FROM FixtureDeliverySlip__c WHERE Name =:slipNo AND DeliveryType__c = '回寄' LIMIT 1 ]; if(!slips.isEmpty()) { slip = slips[0]; } else { slip = new FixtureDeliverySlip__c(Name=slipNo , DeliveryType__c = '回寄' , Distributor_method__c = '其他' , DeliveryCompany__c = '其他' , Shippment_loaner_time__c = now , Wh_Staff__c=Userinfo.getUserId()); FixtureUtil.withoutInsert(new List {slip}); } } for(Id raesdId: updateRaesdMap.keySet()) { Rental_Apply_Equipment_Set_Detail__c raesd = updateRaesdMap.get(raesdId); String lost = ''; if(String.isNotBlank(raesd.Check_lost_Item_Final__c)) { lost = raesd.Check_lost_Item_Final__c; } else { lost = raesd.Check_lost_Item__c; } if(lost == 'OK' && raesd.Return_DeliverySlip__c == null && (isSameCity || raesd.NoItemReturn__c)) { raesd.Return_DeliverySlip__c = slip.Id; raesd.Asset_return_time__c = now; updateRaesdMap.put(raesd.Id, raesd); } } } //// 调试用 //private void print(String title, Map m) { // ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Info, title)); // for(String a:m.keyset()) { // ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Info, '' + m.get(a))); // } //} //// 调试用 //private void print(String title, Map m) { // ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Info, title)); // for(Id a:m.keyset()) { // ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Info, '' + m.get(a))); // } //} //// 调试用 //private void print(String title, List l) { // ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Info, title)); // for(Object o:l) { // ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Info, '' + o)); // } //} public class EsdInfo { public Rental_Apply_Equipment_Set_Detail__c rec { get; set; } public Asset rec2 { get; set; } public String errorInfo { get; set; } public String accessorySetId { get; set; } public boolean editable { get; set; } public Boolean checked {get;set;} //public Boolean needsetone { get; set; } public String cdsFinished {get;set;} public String lostFinished {get;set;} public Boolean hidden {get;set;} public Boolean canChangeResult{get;set;} // 是否可修改回库结果 public Boolean needLink{get;set;} // public EsdInfo(Rental_apply_equipment_Set_Detail__c rec) { this.rec = rec; this.editable = false; this.checked = false; this.lostFinished = rec.Check_lost_Item_F__c; this.hidden = false; this.cdsFinished = rec.CDS_complete__c ? 'OK' : ''; this.canChangeResult = true; this.needLink = !rec.Is_Body__c; } } }