global without sharing class AssetMaintainManualBatch implements Database.Batchable, Database.Stateful { global Id AssetMaintainHeaderId; global List errorList = new List(); global List warningList = new List(); global Integer allCount = 0; global Integer doneCount = 0; global Boolean needCheck; global Operation op; global Integer round; // 跑几次 global Set abandonFailedIdSet = new Set(); // 废弃失败的assetId global enum Operation { FROZEN, // 提交后冻结 UNFROZEN, // 取消,驳回,回调时解冻 PROCESS, // 更新asset ABANDON // 废弃 } // 一次只跑一个维护单 /** @description @param AssetMaintainHeaderId 维护单Id @param needCheck 是否要在batch中做数量检查 */ global AssetMaintainManualBatch(Id AssetMaintainHeaderId, Boolean needCheck) { this.AssetMaintainHeaderId = AssetMaintainHeaderId; this.needCheck = needCheck; this.op = Operation.PROCESS; this.round = 4; // 默认总共跑4次 } /** @description @param AssetMaintainHeaderId 维护单Id @param needCheck 是否要在batch中做数量检查 @param op 为哪种操作而做检查 */ global AssetMaintainManualBatch(Id AssetMaintainHeaderId, Boolean needCheck, Operation op) { this.AssetMaintainHeaderId = AssetMaintainHeaderId; this.needCheck = needCheck; this.op = op; this.round = 4; // 默认总共跑4次 } /** @description @param AssetMaintainHeaderId 维护单Id @param needCheck 是否要在batch中做数量检查 @param op 为哪种操作而做检查 @param round 最多共跑几次,其中第1次必跑,如果因为lock没跑成功就接着跑,直到总次数达到round */ global AssetMaintainManualBatch(Id AssetMaintainHeaderId, Boolean needCheck, Operation op, Integer round) { this.AssetMaintainHeaderId = AssetMaintainHeaderId; this.needCheck = needCheck; this.op = op; this.round = round; } global Database.QueryLocator start(Database.BatchableContext bc) { String query = 'SELECT Id' + ' , Fixture_Model_No__c' + ' , MaintainType__c' + ' , MaintainCount__c' + ' , DisconnectCount__c' + ' , AbandonCount__c' + ' , Asset__c' + ' , Batch_Status__c' + ' , Is_OneToOne_Accessory__c' + ' , OneToOne_Main__c' + ' FROM AssetMaintainDetail__c' + ' WHERE AssetMaintainHeader__c = :AssetMaintainHeaderId' + ' AND Batch_Status__c != \'完成\''; // 只有废弃才会把能维护的先维护掉 if (this.op != Operation.ABANDON && this.needCheck) { LogBean bean = AssetMaintainManualBatch.checkAllDetailAndAsset(this.AssetMaintainHeaderId, this.op); List errList = bean.errorList; System.debug(errList); if (errList.size() > 0) { query += ' AND Id = null'; errorList = errList; } warningList = bean.warningList; } return Database.getQueryLocator(query); } global void execute(Database.BatchableContext BC, List amdList1) { Set amhSet = new Set(); // for(AssetMaintainHeader__c amh:amhList){ // amhSet.add(amh.Id); // } List amdList = [SELECT Id , Fixture_Model_No__c , MaintainType__c , MaintainCount__c , DisconnectCount__c , AbandonCount__c , Asset__c , Batch_Status__c , Is_OneToOne_Accessory__c , OneToOne_Main__c , AssetMaintainHeader__r.Submit_Time__c , AssetMaintainHeader__r.Approved_Time__c FROM AssetMaintainDetail__c WHERE Id =: amdList1 AND Batch_Status__c!='完成' FOR UPDATE]; if(amdList.size() == 0){ return; } allCount += amdList.size(); Savepoint sp = Database.setSavepoint(); try { Set assetIdSet = new Set(); for(AssetMaintainDetail__c amd: amdList){ assetIdSet.add(amd.Asset__c); } Map assetMap = new Map([SELECT Id , Abandoned_Inventory__c , Internal_Asset_number__c , Fixture_Model_No_F__c , Abandoned_RealThing__c , Frozen_Quantity__c , You_Xiao_Ku_Cun__c , Manage_type__c , In_wh_Fu_Shu_Pin_You_Xiao_Ku_Cun_Sum__c , Ji_Zhong_Guan_Li_Ku_Cun__c , Quantity , Main_OneToOne__c , Consumable_Guaranteen_end__c , MaintainCount_For_Processing__c FROM Asset WHERE Id IN: assetIdSet FOR UPDATE]); List linkList = [SELECT Id , Quantity__c , Main_Asset__c , Accessory_Asset__c FROM Fixture_OneToOne_Link__c WHERE Main_Asset__c IN:assetMap.keySet() OR Accessory_Asset__c IN:assetMap.keySet() FOR UPDATE ]; Map> assetLinksMap = new Map>(); for(Fixture_OneToOne_Link__c link:linkList){ if(!assetLinksMap.containsKey(link.Main_Asset__c)){ assetLinksMap.put(link.Main_Asset__c, new List()); } if(!assetLinksMap.containsKey(link.Accessory_Asset__c)){ assetLinksMap.put(link.Accessory_Asset__c, new List()); } assetLinksMap.get(link.Main_Asset__c).add(link); assetLinksMap.get(link.Accessory_Asset__c).add(link); } List checkErrorList = new List (); if(this.needCheck){ checkErrorList = checkAllDetailAndAsset(amdList, assetMap, assetLinksMap, amdList[0].MaintainType__c, this.op, this.abandonFailedIdSet).errorList; } if(checkErrorList.size() > 0) { // 只有废弃才会把能维护的先维护掉 if(this.op != Operation.ABANDON) { throw new ControllerUtil.myException(String.join(checkErrorList, '\n')); } else { errorList.addAll(checkErrorList); } } Map updateLinks = new Map(); Map deleteLinks = new Map(); List amdUpdateList = new List(); Datetime now = System.now(); for(AssetMaintainDetail__c amd: amdList){ Asset ass = assetMap.get(amd.Asset__c); switch on amd.MaintainType__c{ when '断念找回(断念取消)'{ ass.Giveup_Return__c = '断念找回'; ass.Abandoned_Inventory__c = intValueOf(ass.Abandoned_Inventory__c) - intValueOf(amd.MaintainCount__c); ass.MaintainCount_For_Processing__c = intValueOf(ass.MaintainCount_For_Processing__c) - intValueOf(amd.MaintainCount__c) ; ass.Status = '使用中'; amd.Batch_Status__c = '完成'; amd.MaintainedTime__c = now; } when '断念找回(重新登录)'{ ass.Quantity = intValueOf(ass.Quantity) + intValueOf(amd.MaintainCount__c); ass.ChangeQuantityReason__c = '断念找回'; ass.MaintainCount_For_Processing__c = intValueOf(ass.MaintainCount_For_Processing__c) - intValueOf(amd.MaintainCount__c) ; ass.Status = '使用中'; amd.Batch_Status__c = '完成'; amd.MaintainedTime__c = now; } when '解冻' { ass.Frozen_Quantity__c = intValueOf(ass.Frozen_Quantity__c) - intValueOf(amd.MaintainCount__c); ass.Status = '使用中'; ass.MaintainCount_For_Processing__c = intValueOf(ass.MaintainCount_For_Processing__c) - intValueOf(amd.MaintainCount__c) ; ass.Freeze_sign__c = ass.Frozen_Quantity__c >= ass.Quantity; amd.Batch_Status__c = '完成'; amd.MaintainedTime__c = now; } when '冻结'{ ass.Frozen_Quantity__c = intValueOf(ass.Frozen_Quantity__c) + intValueOf(amd.MaintainCount__c); ass.MaintainCount_For_Processing__c = intValueOf(ass.MaintainCount_For_Processing__c) - intValueOf(amd.MaintainCount__c) ; // 个体 一对一主体 删掉和所有附属品的link if(ass.Manage_type__c=='个体管理' && ass.Main_OneToOne__c && assetLinksMap.containsKey(ass.Id)){ ass.Fixture_OneToOne_Link__c = null; ass.Main_OneToOne__c = false; for (Fixture_OneToOne_Link__c link :assetLinksMap.get(ass.Id)) { if (link.Main_Asset__c == ass.Id) { deleteLinks.put(link.Id, link); } } } // 个体 一对一附属品 删掉和主体的link if(ass.Manage_type__c=='个体管理' && assetLinksMap.containsKey(ass.Id)){ ass.Fixture_OneToOne_Link__c = null; for (Fixture_OneToOne_Link__c link :assetLinksMap.get(ass.Id)) { if (link.Accessory_Asset__c == ass.Id) { deleteLinks.put(link.Id, link); } } } // 数量 一对一附属品 link里减去断开数,减到0就删掉 if(ass.Manage_type__c=='数量管理' && assetLinksMap.containsKey(ass.Id) && intValueOf(amd.DisconnectCount__c) > 0){ for(Fixture_OneToOne_Link__c link :assetLinksMap.get(ass.Id)){ if(link.Accessory_Asset__c == ass.Id && link.Main_Asset__c == amd.OneToOne_Main__c){ link.Quantity__c = intValueOf(link.Quantity__c) - intValueOf(amd.DisconnectCount__c); if(link.Quantity__c <= 0){ deleteLinks.put(link.Id, link); if (updateLinks.containsKey(link.Id)) { updateLinks.remove(link.Id); } } else{ updateLinks.put(link.Id, link); } } } } ass.Status = '使用中'; ass.Freeze_sign__c = ass.Frozen_Quantity__c >= ass.Quantity; amd.Batch_Status__c = '完成'; amd.MaintainedTime__c = now; } when '实物报废'{ if(this.op == Operation.UNFROZEN){ ass.MaintainCount_For_Processing__c = intValueOf(ass.MaintainCount_For_Processing__c) - intValueOf(amd.MaintainCount__c) ; } // 批准时操作 else if(this.op == Operation.PROCESS && amd.Batch_Status__c == '未处理'){ ass.Abandoned_RealThing__c = intValueOf(ass.Abandoned_RealThing__c) + intValueOf(amd.MaintainCount__c); ass.MaintainCount_For_Processing__c = intValueOf(ass.MaintainCount_For_Processing__c) - intValueOf(amd.MaintainCount__c) ; // 个体 一对一主体 删除和所有附属品的link if(ass.Manage_type__c=='个体管理' && ass.Main_OneToOne__c && assetLinksMap.containsKey(ass.Id)){ ass.Fixture_OneToOne_Link__c = null; ass.Main_OneToOne__c = false; for(Fixture_OneToOne_Link__c link :assetLinksMap.get(ass.Id)){ if(link.Main_Asset__c == ass.Id){ deleteLinks.put(link.Id, link); } } } // 个体 一对一附属品 删掉和主体的link if(ass.Manage_type__c=='个体管理' && assetLinksMap.containsKey(ass.Id)){ ass.Fixture_OneToOne_Link__c = null; for(Fixture_OneToOne_Link__c link :assetLinksMap.get(ass.Id)){ if(link.Accessory_Asset__c == ass.Id){ deleteLinks.put(link.Id, link); } } } // 数量 一对一附属品 link里减去断开数,减到0删掉 if(ass.Manage_type__c=='数量管理' && assetLinksMap.containsKey(ass.Id)){ for(Fixture_OneToOne_Link__c link :assetLinksMap.get(ass.Id)){ if(link.Accessory_Asset__c == ass.Id && link.Main_Asset__c == amd.OneToOne_Main__c){ link.Quantity__c = intValueOf(link.Quantity__c) - intValueOf(amd.DisconnectCount__c); if(link.Quantity__c <= 0) { deleteLinks.put(link.Id, link); if(updateLinks.containsKey(link.Id)){ updateLinks.remove(link.Id); } } else{ updateLinks.put(link.Id, link); } } } } if(ass.Abandoned_RealThing__c >= ass.Quantity){ ass.Status = '待报废'; } else{ ass.Status = '使用中'; } amd.Batch_Status__c = '处理中'; amd.MaintainedTime__c = now; } // 废弃时的操作 else if(this.op == Operation.ABANDON && amd.Batch_Status__c == '处理中') { if (this.abandonFailedIdSet.contains(amd.Asset__c)) { continue; } ass.Abandoned_RealThing__c = intValueOf(ass.Abandoned_RealThing__c) - intValueOf(amd.AbandonCount__c); ass.Quantity = intValueOf(ass.Quantity) - intValueOf(amd.AbandonCount__c); ass.ChangeQuantityReason__c = '废弃'; if (ass.Manage_type__c == '个体管理') { ass.Status = ass.Quantity <= 0 ? FixtureUtil.assetStatusMap.get(FixtureUtil.AssetStatus.Fei_Qi.ordinal()) : '使用中'; } else{ if(ass.Consumable_Guaranteen_end__c == null || ass.Consumable_Guaranteen_end__c>System.today()){ ass.Status = '使用中'; } else { ass.Status = ass.Quantity <= 0 ? FixtureUtil.assetStatusMap.get(FixtureUtil.AssetStatus.Fei_Qi.ordinal()) : '使用中'; } } amd.Batch_Status__c = '完成'; amd.AbandonedTime__c = now; } } } amdUpdateList.add(amd); } if (!amdUpdateList.isEmpty()) { update amdUpdateList; // 只有维修单都维护完了才会更新维护单状态 List amdListf = [SELECT Id , Fixture_Model_No__c , MaintainType__c , MaintainCount__c , DisconnectCount__c , AbandonCount__c , Asset__c , OneToOne_Main__c , AssetMaintainHeader__r.Status__c FROM AssetMaintainDetail__c WHERE AssetMaintainHeader__c =: AssetMaintainHeaderId AND Batch_Status__c != '完成']; if (amdUpdateList.size() == amdList.size() && amdListf.size() == 0) { if(amdUpdateList[0].Batch_Status__c == '完成'){ AssetMaintainHeader__c ah = new AssetMaintainHeader__c(Id = this.AssetMaintainHeaderId); ah.Status__c = '已完成'; update ah; } } } if (!deleteLinks.isEmpty()) { List deleteList = [ SELECT Id FROM Fixture_OneToOne_Link__c WHERE Id IN: deleteLinks.keySet() ]; if (!deleteList.isEmpty()) { delete deleteList; } } if (!updateLinks.isEmpty()) { update updateLinks.values(); } if (!assetMap.isEmpty()) { update assetMap.values(); } doneCount += amdUpdateList.size(); } catch (Exception e) { Database.rollback(sp); for(String errorMsg: e.getMessage().split('\n')) { errorList.add(errorMsg + '\n' + e.getStackTraceString()); } System.debug(LoggingLevel.ERROR, e.getMessage() + '\n' + e.getStackTraceString()); } } global void finish(Database.BatchableContext BC) { this.round -= 1; // 当所有错误都是lock引起时才要重跑 Boolean lockFailure = errorList.size() > 0; for(String errorMsg :this.errorList){ if (!errorMsg.contains('Record Currently Unavailable') && !errorMsg.contains('记录当前不可用') && !errorMsg.contains('レコードは現在利用できません')) { lockFailure = false; break; } } if (lockFailure && this.round > 0 && allCount > 0) { AssetMaintainManualBatch bat = new AssetMaintainManualBatch(this.AssetMaintainHeaderId, this.needCheck, this.op, this.round); Database.executeBatch(bat, Integer.valueOf(System.Label.AssetMaintainManualBatchSize)); } else { BatchEmailUtil be = new BatchEmailUtil(); String[] toList = new String[]{}; String[] ccList = new String[]{}; User u = [SELECT Id,Email from User where Id = :UserInfo.getUserId()]; toList.add(u.Email); for (Consum_Apply_Meta__mdt camd : [SELECT Id , Key__c , ValueLong__c FROM Consum_Apply_Meta__mdt WHERE Package__c = 'AssetMaintainManualBatch' AND Key__c = 'ErrorMailAddress' ORDER BY Key__c]) { for(String email:camd.ValueLong__c.split(',')){ if (!toList.contains(email)) { ccList.add(email); } } } List amhList = [SELECT Name , MaintainType__c , Batch_Processing__c FROM AssetMaintainHeader__c WHERE Id =:this.AssetMaintainHeaderId]; String title = ''; String text = ''; switch on this.op{ when PROCESS{ text = '保有设备相关字段修改'; } when FROZEN{ text = '保有设备冻结'; } when UNFROZEN{ text = '保有设备解冻'; } when ABANDON{ text = '保有设备废弃'; } } if(!amhList.isEmpty()){ title += 'Batch 数据维护单 ' + amhList[0].Name + ' ' +amhList[0].MaintainType__c + ' '; if(amhList[0].Batch_Processing__c) { amhList[0].Batch_Processing__c = false; update amhList[0]; } } if (allCount != doneCount || errorList.size() > 0) { for (OrgWideEmailAddress tmpEmailObj : [SELECT Id, Address, DisplayName FROM OrgWideEmailAddress WHERE DisplayName like 'BatchNotify']) { ccList.add(tmpEmailObj.Address); } for (Consum_Apply_Meta__mdt camd : [SELECT Id , Key__c , ValueLong__c FROM Consum_Apply_Meta__mdt WHERE Package__c = 'AssetMaintainAutoBatch' AND Key__c = 'ErrorMailAddress' ORDER BY Key__c]) { for(String email:camd.ValueLong__c.split(',')) { if (!toList.contains(email) && !ccList.contains(email)) { ccList.add(email); } } } text += '失败\n'+String.join(this.errorList, '\n'); be.failedMail(toList, ccList, title, text, allCount, doneCount, errorList.size()); be.send(); } else if (this.op != Operation.ABANDON){ // 废弃成功时有workflow发邮件,这里不用发 text += '成功\n'; for(String log : warningList) { text += log + '\n'; } be.successMail(toList, ccList, title, allCount, text); be.send(); } } } /** @description 检查维护单下的明细中数量是否合法 @param AssetMaintainHeaderId 维护单Id @param op 为哪种操作而做检查 @return 错误列表 */ public static LogBean checkAllDetailAndAsset(Id AssetMaintainHeaderId, Operation op){ List amdList = [SELECT Id , Fixture_Model_No__c , MaintainType__c , MaintainCount__c , DisconnectCount__c , AbandonCount__c , Asset__c , OneToOne_Main__c , AssetMaintainHeader__r.Status__c , AssetMaintainHeader__r.Submit_Time__c , AssetMaintainHeader__r.Approved_Time__c FROM AssetMaintainDetail__c WHERE AssetMaintainHeader__c =: AssetMaintainHeaderId AND Batch_Status__c != '完成']; if(amdList.size() > 0){ Set assetIdSet = new Set(); for(AssetMaintainDetail__c amd:amdList){ assetIdSet.add(amd.Asset__c); } return checkAllDetailAndAsset(amdList, assetIdSet, amdList[0].MaintainType__c, op); } LogBean lb = new LogBean(); lb.errorList.add('没有维护明细'); return lb; } /** @description 检查维护单明细数量是否合法 @param amdList 维护单明细列表 @param assetIdSet 维护单明细对应的AssetId Set @param maintainType 维护类型 @param op 为哪种操作而做检查 @return 错误列表 */ public static LogBean checkAllDetailAndAsset(List amdList, Set assetIdSet, String maintainType, Operation op){ Map assetMap = new Map([SELECT Id , Abandoned_Inventory__c , Internal_Asset_number__c , Fixture_Model_No_F__c , Abandoned_RealThing__c , Frozen_Quantity__c , You_Xiao_Ku_Cun__c , Manage_type__c , In_wh_Fu_Shu_Pin_You_Xiao_Ku_Cun_Sum__c , Ji_Zhong_Guan_Li_Ku_Cun__c , Quantity , MaintainCount_For_Processing__c , Main_OneToOne__c FROM Asset WHERE Id IN: assetIdSet FOR UPDATE]); List linkList = [SELECT Id , Quantity__c , Main_Asset__c , Accessory_Asset__c FROM Fixture_OneToOne_Link__c WHERE Main_Asset__c IN:assetMap.keySet() OR Accessory_Asset__c IN:assetMap.keySet() FOR UPDATE ]; Map> assetLinksMap = new Map>(); for(Fixture_OneToOne_Link__c link:linkList){ if(!assetLinksMap.containsKey(link.Main_Asset__c)){ assetLinksMap.put(link.Main_Asset__c, new List()); } if(!assetLinksMap.containsKey(link.Accessory_Asset__c)){ assetLinksMap.put(link.Accessory_Asset__c, new List()); } assetLinksMap.get(link.Main_Asset__c).add(link); assetLinksMap.get(link.Accessory_Asset__c).add(link); } return checkAllDetailAndAsset(amdList, assetMap, assetLinksMap, maintainType, op); } public static LogBean checkAllDetailAndAsset(List amdList, Map assetMap, Map> assetLinksMap, String maintainType, Operation op) { return checkAllDetailAndAsset(amdList, assetMap, assetLinksMap, maintainType, op, new Set()); } /** @description 检查维护单明细数量是否合法 @param amdList 维护单明细列表 @param assetMap 维护单明细对应的Map @param assetLinksMap 保有设备相关的一对一link @param maintainType 维护类型 @param op 为哪种操作而做检查 @param abandonFailedIdSet 储存检查不过的assetId,用作返回值 @return 错误列表 */ public static LogBean checkAllDetailAndAsset(List amdList, Map assetMap, Map> assetLinksMap, String maintainType, Operation op, Set abandonFailedIdSet) { List errorList = new List(); List warningList = new List(); // 总维护数 Map assetMaintainMap = new Map(); // 总废弃数 Map assetAbandonMap = new Map(); // 总断开数 Map linkDisconnectMap = new Map(); // 收集主体设备Id,如果主体和附属品在同一单中,附属品的断开数会被无视 Set mainIdSet = new Set(); // 需要忽略检查的主体 Set ignoreMainIdSet = new Set(); Datetime submitTime = null; Datetime approveTime = null; // 重新查出需要更新的Asset for(AssetMaintainDetail__c amd:amdList){ if(amd.AssetMaintainHeader__r.Submit_Time__c != null && submitTime == null) { submitTime = amd.AssetMaintainHeader__r.Submit_Time__c; } if(amd.AssetMaintainHeader__r.Approved_Time__c != null && approveTime == null) { approveTime = amd.AssetMaintainHeader__r.Approved_Time__c; } if(!assetMap.containsKey(amd.Asset__c)){ errorList.add(amd.Fixture_Model_No__c + '保有设备不存在或不可以更新'); } if(assetMap.get(amd.Asset__c).Main_OneToOne__c) { mainIdSet.add(amd.Asset__c); } Integer t = assetMaintainMap.containsKey(amd.Asset__c)?assetMaintainMap.get(amd.Asset__c):0; assetMaintainMap.put(amd.Asset__c, t + intValueOf(amd.MaintainCount__c)); t = assetAbandonMap.containsKey(amd.Asset__c)?assetAbandonMap.get(amd.Asset__c):0; assetAbandonMap.put(amd.Asset__c, t + intValueOf(amd.AbandonCount__c)); } for(AssetMaintainDetail__c amd:amdList){ // 检查一对一主体是否与明细的asset有link if (op != Operation.ABANDON && amd.OneToOne_Main__c != null) { Boolean assetMainAvailable = false; if (assetLinksMap.containsKey(amd.Asset__c)) { for (Fixture_OneToOne_Link__c link:assetLinksMap.get(amd.Asset__c)) { if (amd.OneToOne_Main__c == link.Main_Asset__c) { assetMainAvailable = true; break; } } } if (!assetMainAvailable) { // 实物报废审批后,link不存在就不做检查 if(approveTime != null && submitTime != null && maintainType == '实物报废') { warningList.add(amd.Fixture_Model_No__c + '与【一对一主体选择】的link已断开,不做link检查'); ignoreMainIdSet.add(amd.OneToOne_Main__c); } else { errorList.add(amd.Fixture_Model_No__c + '【一对一主体选择】不正确'); } } } // 一对一附属品Asset可能同时对不同的主体有不同的断开数 if(!ignoreMainIdSet.contains(amd.OneToOne_Main__c)) { String linkName = amd.Asset__c + ':' + amd.OneToOne_Main__c; Integer t = linkDisconnectMap.containsKey(linkName)?linkDisconnectMap.get(linkName):0; linkDisconnectMap.put(linkName, t + intValueOf(amd.DisconnectCount__c)); } } for(Id assetId:assetMap.keySet()){ Asset ass = assetMap.get(assetId); Integer maintainCount = assetMaintainMap.containsKey(assetId)?assetMaintainMap.get(assetId):0; Integer abandonCount = assetAbandonMap.containsKey(assetId)?assetAbandonMap.get(assetId):0; switch on maintainType{ when '断念找回(断念取消)'{ // 维护数量<=待废弃数(丢失/盘亏) if(maintainCount > intValueOf(ass.Abandoned_Inventory__c)){ errorList.add(ass.Fixture_Model_No_F__c + '【维护数量】不可超过【待废弃数(丢失/盘亏)】'); } // 必须是非固定资产 if(String.isNotBlank(ass.Internal_Asset_number__c)){ errorList.add(ass.Fixture_Model_No_F__c + '固定资产不可断念找回'); } } when '断念找回(重新登录)'{ // 必须是非固定资产 if(String.isNotBlank(ass.Internal_Asset_number__c)){ errorList.add(ass.Fixture_Model_No_F__c + '固定资产不可断念找回'); } } when '冻结'{ // 维护数量<=有效库存 if(maintainCount > ass.You_Xiao_Ku_Cun__c){ errorList.add(ass.Fixture_Model_No_F__c + '【维护数量】不可超过【有效库存】'); } Integer allDisconnectCount = 0; // 一对一附属品:断开数量<=主体选择对应的一对一Link表.一对一附属品管理数量 if(assetLinksMap.containsKey(assetId)) { for(Fixture_OneToOne_Link__c link : assetLinksMap.get(assetId)){ String linkName = link.Accessory_Asset__c + ':' + link.Main_Asset__c; Integer disconnectCount = 0; // 主体的断开数恒为0 if(mainIdSet.contains(assetId)) { disconnectCount = 0; } // 附属品所连的主体在同一单里,断开数为全部 else if (mainIdSet.contains(link.Main_Asset__c)) { disconnectCount = intValueOf(link.Quantity__c); } // 主体不在同一单里,则断开数来自用户填写 else { disconnectCount = linkDisconnectMap.containsKey(linkName)?linkDisconnectMap.get(linkName):0; if(disconnectCount > link.Quantity__c){ errorList.add(ass.Fixture_Model_No_F__c + '【断开数量】不可超过一对一Link的【数量】'); } } allDisconnectCount += disconnectCount; } } // 维护数量-断开数量<=集中管理库存 if(maintainCount - allDisconnectCount > ass.Ji_Zhong_Guan_Li_Ku_Cun__c) { errorList.add(ass.Fixture_Model_No_F__c + '【维护数量】-【断开数量】不可超过【集中管理库存】'); } // 断开数量<=上架的附属品有效库存_合计 if(allDisconnectCount > ass.In_wh_Fu_Shu_Pin_You_Xiao_Ku_Cun_Sum__c){ errorList.add(ass.Fixture_Model_No_F__c + '【断开数量】不可超过【上架的附属品有效库存_合计】'); } } when '解冻'{ // 维护数量<=冻结数 if(maintainCount > intValueOf(ass.Frozen_Quantity__c)) { errorList.add(ass.Fixture_Model_No_F__c + '【维护数量】不可超过【冻结数】'); } } when '实物报废'{ Integer allDisconnectCount = 0; // 提交申请时检查 if(op == Operation.FROZEN){ // 维护数量<=有效库存 if(maintainCount > ass.You_Xiao_Ku_Cun__c){ errorList.add(ass.Fixture_Model_No_F__c + '【维护数量】不可超过【有效库存】'); } // 一对一附属品:断开数量<=主体选择对应的一对一Link表.一对一附属品管理数量 if(assetLinksMap.containsKey(assetId)) { for(Fixture_OneToOne_Link__c link : assetLinksMap.get(assetId)){ String linkName = link.Accessory_Asset__c + ':' + link.Main_Asset__c; Integer disconnectCount = 0; // 主体的断开数恒为0 if(mainIdSet.contains(assetId)) { disconnectCount = 0; } // 附属品所连的主体在同一单里,断开数为全部 else if (mainIdSet.contains(link.Main_Asset__c)) { disconnectCount = intValueOf(link.Quantity__c); } // 主体不在同一单里,则断开数来自用户填写 else { disconnectCount = linkDisconnectMap.containsKey(linkName)?linkDisconnectMap.get(linkName):0; if(disconnectCount > link.Quantity__c){ errorList.add(ass.Fixture_Model_No_F__c + '【断开数量】不可超过一对一Link的【数量】'); } } allDisconnectCount += disconnectCount; } } // 维护数量-断开数量<=集中管理库存 if(maintainCount - allDisconnectCount>ass.Ji_Zhong_Guan_Li_Ku_Cun__c){ errorList.add(ass.Fixture_Model_No_F__c + '【维护数量】-【断开数量】不可超过【集中管理库存】'); } // 断开数量<=上架的附属品有效库存_合计 if(allDisconnectCount > ass.In_wh_Fu_Shu_Pin_You_Xiao_Ku_Cun_Sum__c){ errorList.add(ass.Fixture_Model_No_F__c + '【断开数量】不可超过【上架的附属品有效库存_合计】'); } } // 提交申请后【有效库存】和【集中管理库存】会移到【待处理维护数】里,批准时检查要把【待处理维护数】算进来 if(op == Operation.PROCESS){ // 维护数量<=有效库存 if(maintainCount > ass.You_Xiao_Ku_Cun__c + intValueOf(ass.MaintainCount_For_Processing__c)) { errorList.add(ass.Fixture_Model_No_F__c + '【维护数量】不可超过【有效库存】+【待处理维护数】'); } // 一对一附属品:断开数量<=主体选择对应的一对一Link表.一对一附属品管理数量 if(assetLinksMap.containsKey(assetId) && !ass.Main_OneToOne__c){ for(Fixture_OneToOne_Link__c link : assetLinksMap.get(assetId)){ String linkName = link.Accessory_Asset__c + ':' + link.Main_Asset__c; Integer disconnectCount = 0; // 主体的断开数恒为0 if(mainIdSet.contains(assetId)) { disconnectCount = 0; } // 附属品所连的主体在同一单里,断开数为全部 else if (mainIdSet.contains(link.Main_Asset__c)) { disconnectCount = intValueOf(link.Quantity__c); } // 主体不在同一单里,则断开数来自用户填写 else { disconnectCount = linkDisconnectMap.containsKey(linkName)?linkDisconnectMap.get(linkName):0; if(disconnectCount > link.Quantity__c){ errorList.add(ass.Fixture_Model_No_F__c + '【断开数量】不可超过一对一Link的【数量】'); } } allDisconnectCount += disconnectCount; } } // 维护数量-断开数量<=集中管理库存 if(maintainCount - allDisconnectCount > ass.Ji_Zhong_Guan_Li_Ku_Cun__c + intValueOf(ass.MaintainCount_For_Processing__c)) { errorList.add(ass.Fixture_Model_No_F__c + '【维护数量】-【断开数量】不可超过【集中管理库存】+【报废冻结数】'); } // 断开数量<=上架的附属品有效库存_合计 if(allDisconnectCount > ass.In_wh_Fu_Shu_Pin_You_Xiao_Ku_Cun_Sum__c){ errorList.add(ass.Fixture_Model_No_F__c + '【断开数量】不可超过【上架的附属品有效库存_合计】'); } } // 废弃时检查 if(op == Operation.ABANDON) { // 废弃数量<=待废弃数(实物) if(abandonCount > intValueOf(ass.Abandoned_RealThing__c)) { errorList.add(ass.Fixture_Model_No_F__c + '【废弃数量】不可超过【待废弃数(实物)】'); abandonFailedIdSet.add(ass.Id); } } // 所有节点都检查 废弃数量 <= 数量 if(abandonCount>ass.Quantity){ errorList.add(ass.Fixture_Model_No_F__c + '【废弃数量】不可超过【数量】'); abandonFailedIdSet.add(ass.Id); } // 废弃数量 <= 维护数量 + 待废弃数(实物) if (abandonCount > maintainCount + intValueOf(ass.Abandoned_RealThing__c)) { errorList.add(ass.Fixture_Model_No_F__c + '【废弃数量】不可超过【维护数量】+【待废弃数(实物)】'); abandonFailedIdSet.add(ass.Id); } } } } return new LogBean(errorList, warningList); } private static Integer intValueOf(Decimal d) { if(d == null || d < 0) { return 0; } return Integer.valueOf(d); } public class LogBean { public List errorList; public List warningList; public LogBean() { this.errorList = new List(); this.warningList = new List(); } public LogBean(List errors, List warnings) { this.errorList = errors; this.warningList = warnings; } } }