global without sharing class AssetMaintainManualBatch implements Database.Batchable<sObject>, Database.Stateful {
|
global Id AssetMaintainHeaderId;
|
global List<String> errorList = new List<String>();
|
global List<String> warningList = new List<String>();
|
global Integer allCount = 0;
|
global Integer doneCount = 0;
|
global Boolean needCheck;
|
global Operation op;
|
global Integer round; // 跑几次
|
global Set<Id> abandonFailedIdSet = new Set<Id>(); // 废弃失败的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<String> 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<AssetMaintainDetail__c> amdList1) {
|
Set<Id> amhSet = new Set<Id>();
|
// for(AssetMaintainHeader__c amh:amhList){
|
// amhSet.add(amh.Id);
|
// }
|
List<AssetMaintainDetail__c> 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<Id> assetIdSet = new Set<Id>();
|
for(AssetMaintainDetail__c amd: amdList){
|
assetIdSet.add(amd.Asset__c);
|
}
|
Map<Id, Asset> assetMap = new Map<Id, Asset>([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<Fixture_OneToOne_Link__c> 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<Id, List<Fixture_OneToOne_Link__c>> assetLinksMap = new Map<Id, List<Fixture_OneToOne_Link__c>>();
|
for(Fixture_OneToOne_Link__c link:linkList){
|
if(!assetLinksMap.containsKey(link.Main_Asset__c)){
|
assetLinksMap.put(link.Main_Asset__c, new List<Fixture_OneToOne_Link__c>());
|
}
|
if(!assetLinksMap.containsKey(link.Accessory_Asset__c)){
|
assetLinksMap.put(link.Accessory_Asset__c, new List<Fixture_OneToOne_Link__c>());
|
}
|
assetLinksMap.get(link.Main_Asset__c).add(link);
|
assetLinksMap.get(link.Accessory_Asset__c).add(link);
|
}
|
List<String> checkErrorList = new List<String> ();
|
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<Id, Fixture_OneToOne_Link__c> updateLinks = new Map<Id, Fixture_OneToOne_Link__c>();
|
Map<Id, Fixture_OneToOne_Link__c> deleteLinks = new Map<Id, Fixture_OneToOne_Link__c>();
|
List<AssetMaintainDetail__c> amdUpdateList = new List<AssetMaintainDetail__c>();
|
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<AssetMaintainDetail__c> 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<Fixture_OneToOne_Link__c> 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<AssetMaintainHeader__c> 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<AssetMaintainDetail__c> 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<Id> assetIdSet = new Set<Id>();
|
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<AssetMaintainDetail__c> amdList, Set<Id> assetIdSet, String maintainType, Operation op){
|
Map<Id, Asset> assetMap = new Map<Id, Asset>([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<Fixture_OneToOne_Link__c> 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<Id, List<Fixture_OneToOne_Link__c>> assetLinksMap = new Map<Id, List<Fixture_OneToOne_Link__c>>();
|
for(Fixture_OneToOne_Link__c link:linkList){
|
if(!assetLinksMap.containsKey(link.Main_Asset__c)){
|
assetLinksMap.put(link.Main_Asset__c, new List<Fixture_OneToOne_Link__c>());
|
}
|
if(!assetLinksMap.containsKey(link.Accessory_Asset__c)){
|
assetLinksMap.put(link.Accessory_Asset__c, new List<Fixture_OneToOne_Link__c>());
|
}
|
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<AssetMaintainDetail__c> amdList, Map<Id, Asset> assetMap,
|
Map<Id, List<Fixture_OneToOne_Link__c>> assetLinksMap,
|
String maintainType, Operation op) {
|
return checkAllDetailAndAsset(amdList, assetMap, assetLinksMap, maintainType, op, new Set<Id>());
|
}
|
/**
|
@description 检查维护单明细数量是否合法
|
@param amdList 维护单明细列表
|
@param assetMap 维护单明细对应的Map <AssetId, Asset>
|
@param assetLinksMap 保有设备相关的一对一link <AssetId, link列表>
|
@param maintainType 维护类型
|
@param op 为哪种操作而做检查
|
@param abandonFailedIdSet 储存检查不过的assetId,用作返回值
|
@return 错误列表
|
*/
|
public static LogBean checkAllDetailAndAsset(List<AssetMaintainDetail__c> amdList, Map<Id, Asset> assetMap,
|
Map<Id, List<Fixture_OneToOne_Link__c>> assetLinksMap,
|
String maintainType, Operation op,
|
Set<Id> abandonFailedIdSet) {
|
List<String> errorList = new List<String>();
|
List<String> warningList = new List<String>();
|
// 总维护数
|
Map<Id, Integer> assetMaintainMap = new Map<Id, Integer>();
|
// 总废弃数
|
Map<Id, Integer> assetAbandonMap = new Map<Id, Integer>();
|
// 总断开数
|
Map<String, Integer> linkDisconnectMap = new Map<String, Integer>();
|
// 收集主体设备Id,如果主体和附属品在同一单中,附属品的断开数会被无视
|
Set<Id> mainIdSet = new Set<Id>();
|
// 需要忽略检查的主体
|
Set<Id> ignoreMainIdSet = new Set<Id>();
|
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<String> errorList;
|
public List<String> warningList;
|
public LogBean() {
|
this.errorList = new List<String>();
|
this.warningList = new List<String>();
|
}
|
public LogBean(List<String> errors, List<String> warnings) {
|
this.errorList = errors;
|
this.warningList = warnings;
|
}
|
}
|
}
|