global class InventoryReportDetailArchiveBatch implements Database.Batchable, Database.Stateful { private Inventory_Header__c ih_new = new Inventory_Header__c(); private String docBodyAsset = ''; // TODO 5M と batch heap size 問題 // private String docBodyRaesd = ''; // TODO 5M と batch heap size 問題 private String docBodyDiushi = ''; // TODO 5M と batch heap size 問題 private String docBodyRepair = ''; // TODO 5M と batch heap size 問題 private Set defaultAssetField; private Set defaultRaesdField; private Set defaultRepairField; private List cListAssetField = new List(); private List cListRaesdField = new List(); private List cListRepairField = new List(); private Map fieldAPIName = new Map(); private Set defaultTasdField;//20210603 you 1650 private List cListTasdField = new List();//20210603 you 1650 private String docBodyTasdDiushi = ''; //20210603 you 1650 private String docBodyTransfer = ''; //20210604 you 1650 global List emailMessages; global Integer totalCount = 0; // 总件数 (Inventory_Detail__c (Sync_Asset_Record_Flag__c = true)) global Integer failedCount = 0; @TestVisible private static List messagesForTest; /** * 批准后, Trigger 会来调 */ global InventoryReportDetailArchiveBatch(Inventory_Header__c ih_new) { this.emailMessages = new List(); this.ih_new = ih_new; } global Database.QueryLocator start(Database.BatchableContext bc) { bp3_Setting__c conf = bp3_Setting__c.getOrgDefaults(); if (String.isBlank(conf.InventoryDetailArchiveFolder__c)) { this.emailMessages.add('未设置CSV保存文件夹,不能开始Batch'); failedCount = 0; return Database.getQueryLocator([SELECT Id FROM Inventory_Detail__c LIMIT 0]); } Inventory_Batch_Mapping__mdt columns; List keyList; defaultAssetField = new Set(); defaultRaesdField = new Set(); defaultRepairField = new Set(); defaultTasdField = new Set();//20210603 you 1650 columns = [select From_Columns__c, Inventory_Columns__c from Inventory_Batch_Mapping__mdt where DeveloperName = 'Asset']; keyList = columns.Inventory_Columns__c.split(','); keyList.addAll(new List { 'Inventory_Zaiku_Count_Jia__c', 'Inventory_Shipan_Count_Jia__c', 'Inventory_Weixiu_Count_Jia__c', 'Inventory_Chujie_Count_Jia__c', 'Inventory_Daibaofei_Diushi_Count_Jia__c', 'Inventory_Quantity_Jia__c', 'Inventory_Profit_Quantity__c', 'Inventory_Loss_Quantity__c', 'Inventory_Deviation_Jia__c', 'Inventory_Remarks__c', 'Inventory_Diaobo_Count_Jia__c'//20210603 you 1650 }); for (Integer i = 0; i < keyList.size(); i++) { if (!defaultAssetField.contains(keyList[i])) { cListAssetField.add(keyList[i]); } defaultAssetField.add(keyList[i]); } columns = [select From_Columns__c, Inventory_Columns__c from Inventory_Batch_Mapping__mdt where DeveloperName = 'Repair']; keyList = columns.Inventory_Columns__c.split(','); for (Integer i = 0; i < keyList.size(); i++) { if (!defaultRepairField.contains(keyList[i])) { cListRepairField.add(keyList[i]); } defaultRepairField.add(keyList[i]); } columns = [select From_Columns__c, Inventory_Columns__c from Inventory_Batch_Mapping__mdt where DeveloperName = 'RAESD']; keyList = columns.Inventory_Columns__c.split(','); for (Integer i = 0; i < keyList.size(); i++) { if (!defaultRaesdField.contains(keyList[i])) { cListRaesdField.add(keyList[i]); } defaultRaesdField.add(keyList[i]); } //20210603 you 1650 columns = [select From_Columns__c, Inventory_Columns__c from Inventory_Batch_Mapping__mdt where DeveloperName = 'TASD']; keyList = columns.Inventory_Columns__c.split(','); for (Integer i = 0; i < keyList.size(); i++) { if (!defaultTasdField.contains(keyList[i])) { cListTasdField.add(keyList[i]); } defaultTasdField.add(keyList[i]); } //获取label String objectType ='Inventory_Detail__c'; Map schemaMap = Schema.getGlobalDescribe(); Schema.SObjectType leadSchema = schemaMap.get(objectType); Map fieldMap = leadSchema.getDescribe().fields.getMap(); for(String fieldName : fieldMap.keySet()){ fieldAPIName.put(fieldName, fieldMap.get(fieldName).getDescribe().getLabel()); } Id ih_new_Id = ih_new.Id; String querysql = 'select ' + String.join(new List(defaultAssetField), ', ') + ' from Inventory_Detail__c ' + 'where Sync_Asset_Record_Flag__c = true' + ' and Inventory_Header__c = :ih_new_Id'; return Database.getQueryLocator(querysql); } global void execute(Database.BatchableContext BC, List syncAssetList) { totalCount += syncAssetList.size(); System.debug('========='+syncAssetList.size()); try { String executeBodyAsset = ''; // TODO 5M と batch heap size 問題 // String executeBodyRaesd = ''; // TODO 5M と batch heap size 問題 String executeBodyDiushi = ''; // TODO 5M と batch heap size 問題 String executeBodyRepair = ''; // TODO 5M と batch heap size 問題 String executeBodyTasdDiushi = ''; //20210603 you 1650 String executeBodyTransfer = ''; //20210604 you 1650 String querysql; List assetIds = new List(); for (Inventory_Detail__c idc : syncAssetList) { assetIds.add(idc.Asset__c); } Id ih_new_Id = ih_new.Id; List statusArList = [ SELECT Asset_Status__c status, sum(Amount__c) quantity , sum(Inventory_Count__c) invShipanCount, Asset__c assetId , sum(Inventory_Deviation__c) deviaCount , sum(Sync_Asset_Frozen_Quantity__c) lossCount , sum(Sync_Asset_Profit_Quantity__c) profitCount FROM Inventory_Detail__c WHERE Asset__c in :assetIds AND Inventory_Header__c = :ih_new_Id AND Inventory_Time__c <> null GROUP BY Asset_Status__c, Asset__c]; //system.debug(statusArList); Map assetCountMap = new Map(); for (AggregateResult ar : statusArList) { InventoryReportDetailController.StatusCount statusCount = new InventoryReportDetailController.StatusCount(0); Integer amount = (Integer.valueOf(ar.get('quantity')) == null) ? 0 : Integer.valueOf(ar.get('quantity')); // 应盘数 Integer acAmount = (Integer.valueOf(ar.get('invShipanCount')) == null) ? 0 : Integer.valueOf(ar.get('invShipanCount')); // 实盘数 Integer wuchaAmount = (Integer.valueOf(ar.get('deviaCount')) == null) ? 0 : Integer.valueOf(ar.get('deviaCount')); // 盘点误差(盘盈/盘亏) Integer lossAmount = (Integer.valueOf(ar.get('lossCount')) == null) ? 0 : Integer.valueOf(ar.get('lossCount')); // 盘点误差(盘盈/盘亏) Integer profitAmount = (Integer.valueOf(ar.get('profitCount')) == null) ? 0 : Integer.valueOf(ar.get('profitCount')); // 盘点误差(盘盈/盘亏) Id assId = String.valueof(ar.get('assetId')); if (assetCountMap.containsKey(assId)) { statusCount = assetCountMap.get(assId); } if (ar.get('status') == '在库') { statusCount.zaikuNum += amount; } else if (ar.get('status') == '维修中') { statusCount.weixiuNum += amount; // 应盘维修中 } else if (ar.get('status') == '出借中') { statusCount.chujieNum += amount; // 应盘出借中 } else if (ar.get('status') == '丢失') { statusCount.diushiNum += amount; // 应盘丢失 } else if (ar.get('status') == '冻结') { statusCount.zaikuNum += amount; // 盘点在库数='在库'应盘数+'冻结'应盘数 }else if (ar.get('status') == '调拨中') {//20210903 you 1650 应盘调拨中 statusCount.diaoboNum += amount; } statusCount.quantity += amount; // 应盘数量 statusCount.shipanNum += acAmount; // 实盘 statusCount.wuchaNum += wuchaAmount; // 盘点误差(盘盈/盘亏) statusCount.panyinNum += profitAmount; statusCount.pankuiNum += lossAmount; assetCountMap.put(assId, statusCount); } system.debug('syncAssetList==='+syncAssetList.size()); system.debug('assetCountMap==='+assetCountMap); for (Inventory_Detail__c idc : syncAssetList) { InventoryReportDetailController.StatusCount eachSCount = assetCountMap.get(idc.Asset__c); system.debug(idc.Asset__c+'eachSCount==='+eachSCount); if (eachSCount != null) { idc.Inventory_Zaiku_Count_Jia__c = eachSCount.zaikuNum; idc.Inventory_Shipan_Count_Jia__c = eachSCount.shipanNum; idc.Inventory_Weixiu_Count_Jia__c = eachSCount.weixiuNum; idc.Inventory_Chujie_Count_Jia__c = eachSCount.chujieNum; idc.Inventory_Daibaofei_Diushi_Count_Jia__c = eachSCount.diushiNum; idc.Inventory_Quantity_Jia__c = eachSCount.quantity; idc.Inventory_Deviation_Jia__c = eachSCount.wuchaNum; idc.Inventory_Profit_Quantity__c = eachSCount.panyinNum; idc.Inventory_Loss_Quantity__c = eachSCount.pankuiNum; idc.Inventory_Diaobo_Count_Jia__c = eachSCount.diaoboNum;//20210603 you 1650 executeBodyAsset += setDocBodyObject(idc, 'Asset', false); } } //借出明细 // querysql = 'select ' + String.join(new List(defaultRaesdField), ', ') // + ' from Inventory_Detail__c where Asset__c IN :assetIds and Asset_Status__c = \'出借中\''; // for (Inventory_Detail__c dl : Database.query(querysql)) { // executeBodyRaesd += setDocBodyObject(dl, 'Raesd', false); // } //丢失借出明细 备品 querysql = 'select ' + String.join(new List(defaultRaesdField), ', ') + ' from Inventory_Detail__c where Asset__c IN :assetIds and Inventory_Header__c = :ih_new_Id and Asset_Status__c = \'丢失借出明细\''; for (Inventory_Detail__c dl : Database.query(querysql)) { executeBodyDiushi += setDocBodyObject(dl, 'Lost', false); } //丢失调拨明细 调拨 20210603 you 1650 querysql = 'select ' + String.join(new List(defaultTasdField), ', ') + ' from Inventory_Detail__c where Asset__c IN :assetIds and Inventory_Header__c = :ih_new_Id and Asset_Status__c = \'丢失调拨明细\''; for (Inventory_Detail__c tads : Database.query(querysql)) { executeBodyTasdDiushi += setDocBodyObject(tads, 'TransferLost', false); } //调拨中 20210604 you 1650 querysql = 'select ' + String.join(new List(defaultTasdField), ', ') + ' from Inventory_Detail__c where Asset__c IN :assetIds and Inventory_Header__c = :ih_new_Id and Asset_Status__c = \'调拨中\''; for (Inventory_Detail__c tra : Database.query(querysql)) { executeBodyTransfer += setDocBodyObject(tra, 'Transfer', false); } //修理id querysql = 'select ' + String.join(new List(defaultRepairField), ', ') + ' from Inventory_Detail__c where Asset__c IN :assetIds and Inventory_Header__c = :ih_new_Id and Asset_Status__c = \'维修中\''; for (Inventory_Detail__c rp : Database.query(querysql)) { executeBodyRepair += setDocBodyObject(rp, 'Repair', false); } docBodyAsset += executeBodyAsset; // docBodyRaesd += executeBodyRaesd; docBodyDiushi += executeBodyDiushi; docBodyRepair += executeBodyRepair; docBodyTasdDiushi += executeBodyTasdDiushi;//20210603 you 1650 docBodyTransfer += executeBodyTransfer;//20210604 you 1650 } catch (Exception e) { failedCount += syncAssetList.size(); System.debug(LoggingLevel.ERROR, e.getMessage() + '\n' + e.getStackTraceString()); this.emailMessages.add(e.getMessage() + '\n' + e.getStackTraceString()); } } private String setDocBodyObject(sObject obj, String typeStr, boolean label) { List toCol; if (typeStr == 'Asset') { toCol = cListAssetField; } else if (typeStr == 'Repair') { toCol = cListRepairField; } else if (typeStr == 'Lost') { //20210603 you 1650 toCol = cListRaesdField; }else if (typeStr == 'Transfer') { //20210604 you 1650 toCol = cListTasdField; } else { toCol = cListTasdField;//20210603 you 1650 } Schema.SObjectType targetType = Inventory_Detail__c.sObjectType; Schema.DescribeSObjectResult sobjResult = targetType.getDescribe(); Map m = sobjResult.fields.getMap(); String docBody = ''; for (Integer i = 0; i < toCol.size(); i++) { List cols = toCol[i].split('\\.'); if (obj == null) { if (label) { docBody += fieldAPIName.get(toCol[i].toLowerCase()).escapeCsv(); } else { docBody += toCol[i].escapeCsv(); } } else { Object val = CreateRelationListPagingCmpCtrl.getObjectValue(obj, cols); if (val != null) { Schema.DescribeFieldResult descField = m.get(toCol[i].toLowerCase().replace('__r.name','__c')).getDescribe(); if(descField.getType() == DisplayType.DATETIME && String.isNotBlank('' + val)){ docBody += (''+((Datetime) val).addHours(8)).escapeCsv(); } else{ docBody += ('' + val).escapeCsv(); } } } // 加 , 和 行末 的换行 if (i < toCol.size() - 1) { docBody += ','; } else { docBody += '\r\n'; } } return docBody; } public Document getArchiveFilenameForUpsert(String typeStr, Inventory_Header__c ih_new) { bp3_Setting__c conf = bp3_Setting__c.getOrgDefaults(); Id folderId = conf.InventoryDetailArchiveFolder__c; String filename = ih_new.Inventory_Start_Date__c.year() + ('' + ih_new.Inventory_Start_Date__c.month()).leftPad(2, '0') + '_' + ih_new.Internal_asset_location__c + '_' + typeStr + '.csv'; Document ret = null; List retList = [SELECT Id , Name , FolderId , Body FROM Document WHERE FolderId = :folderId AND Name =:filename]; if (retList.size() > 0) { ret = retList[0]; } if (ret == null) { ret = new Document(); ret.Name = filename; ret.FolderId = folderId; ret.Type = 'csv'; insert ret; } String docBody = setDocBodyObject(null, typeStr, false); docBody += setDocBodyObject(null, typeStr, true); ret.Body = Blob.valueOf(docBody); return ret; } global void finish(Database.BatchableContext BC) { Integer csvCount = 5; // 总件数 (CSV) 20210726 you 1650 Integer nullCsvCount = 0;//数据不存在 Integer failedCsvCount = 0;//真的失败了 if (docBodyAsset == '') { nullCsvCount++; this.emailMessages.add('Asset无数据'); } else { Document assetDoc = getArchiveFilenameForUpsert('Asset', ih_new); assetDoc.Body = Blob.valueOf(assetDoc.Body.toString() + docBodyAsset); Database.SaveResult saveResult = Database.update(assetDoc, false); if (!saveResult.isSuccess()) failedCsvCount++; this.emailMessages = FixtureUtil.setSaveError(new List{saveResult}, Document.sObjectType, new List{assetDoc}, this.emailMessages); } if (docBodyRepair == '') { nullCsvCount++; this.emailMessages.add('Repair无数据'); } else { Document repairDoc = getArchiveFilenameForUpsert('Repair', ih_new); repairDoc.Body = Blob.valueOf(repairDoc.Body.toString() + docBodyRepair); Database.SaveResult saveResult = Database.update(repairDoc, false); if (!saveResult.isSuccess()) failedCsvCount++; this.emailMessages = FixtureUtil.setSaveError(new List{saveResult}, Document.sObjectType, new List{repairDoc}, this.emailMessages); } // if (docBodyRaesd == '') { // failedCsvCount++; // this.emailMessages.add('Raesd数据不存在'); // } else { // Document raesdDoc = getArchiveFilenameForUpsert('Raesd', ih_new); // raesdDoc.Body = Blob.valueOf(raesdDoc.Body.toString() + docBodyRaesd); // Database.SaveResult saveResult = Database.update(raesdDoc, false); // if (!saveResult.isSuccess()) failedCsvCount++; // this.emailMessages = FixtureUtil.setSaveError(new List{saveResult}, Document.sObjectType, new List{raesdDoc}, this.emailMessages); // } if (docBodyDiushi == '') { nullCsvCount++; this.emailMessages.add('RaesdLost无数据'); } else { Document lostDoc = getArchiveFilenameForUpsert('Lost', ih_new); lostDoc.Body = Blob.valueOf(lostDoc.Body.toString() + docBodyDiushi); Database.SaveResult saveResult = Database.update(lostDoc, false); if (!saveResult.isSuccess()) failedCsvCount++; this.emailMessages = FixtureUtil.setSaveError(new List{saveResult}, Document.sObjectType, new List{lostDoc}, this.emailMessages); } system.debug('docBodyTasdDiushi=='+docBodyTasdDiushi); //20210603 you 1650 start if (docBodyTasdDiushi == '') { nullCsvCount++; this.emailMessages.add('TransferLost无数据'); } else { Document lostDoc = getArchiveFilenameForUpsert('TransferLost', ih_new); lostDoc.Body = Blob.valueOf(lostDoc.Body.toString() + docBodyTasdDiushi); Database.SaveResult saveResult = Database.update(lostDoc, false); if (!saveResult.isSuccess()) failedCsvCount++; this.emailMessages = FixtureUtil.setSaveError(new List{saveResult}, Document.sObjectType, new List{lostDoc}, this.emailMessages); } if (docBodyTransfer == '') { nullCsvCount++; this.emailMessages.add('Transfer无数据'); } else { Document lostDoc = getArchiveFilenameForUpsert('Transfer', ih_new); lostDoc.Body = Blob.valueOf(lostDoc.Body.toString() + docBodyTransfer); Database.SaveResult saveResult = Database.update(lostDoc, false); if (!saveResult.isSuccess()) failedCsvCount++; this.emailMessages = FixtureUtil.setSaveError(new List{saveResult}, Document.sObjectType, new List{lostDoc}, this.emailMessages); } //20210603 you 1650 end // TODO wwf email InventoryReportDetailArchiveBatch.messagesForTest = this.emailMessages; // 发 mail BatchEmailUtil be = new BatchEmailUtil(); String[] toList = new String[]{}; String title = '存档盘点CSV数据'; String[] ccList = new String[]{}; Inventory_Header__c iheader = [select Id, Inventory_Status__c, Name, Internal_asset_location__c, Inventory_Start_Date__c from Inventory_Header__c where Id = :ih_new.Id]; String text = '盘点报告书编号:' + iheader.Name + ' 盘点地点:' + iheader.Internal_asset_location__c + ' 盘点开始日:' + iheader.Inventory_Start_Date__c; text += '\n处理对象'+totalCount + '件 保有设备(同期的 盘点明细)'; text += '\n处理失败'+failedCount + '件 保有设备(同期的 盘点明细)'; //if(this.emailMessages.size() == 0){ if(failedCsvCount==0){ toList.add(UserInfo.getUserEmail()); //be.successMail(toList,ccList, title, csvCount, text); be.successMail(toList,ccList, title, String.join(this.emailMessages, '\n'), csvCount,nullCsvCount, text); }else{ for(String email : System.Label.Inventory_Result_Email.split(',')){ ccList.add(email); } be.failedMail(toList, ccList, title, String.join(this.emailMessages, '\n'), csvCount, csvCount - failedCsvCount-nullCsvCount,nullCsvCount, failedCsvCount,''); } be.send(); } }