global class InventoryReportDtlArcRaesdBatch implements Database.Batchable, Database.Stateful { private Inventory_Header__c ih_new = new Inventory_Header__c(); private String docBodyRaesd = ''; private Integer docBodyRaesdBlobSize = 0; private Id folderId = System.Label.InventoryFolder; private Boolean falg = false; //保存或更新标识 private Set defaultAssetField; private Set defaultRaesdField; private List cListAssetField = new List(); private List cListRaesdField = new List(); private Map fieldAPIName = new Map(); global List emailMessages; global Integer totalCount = 0; // 跨Batch 总件数 global Integer totalCountDone = 0; // 跨Batch 成功件数 global Integer executeCount = 0; // batch内的 总件数 global Integer executeCountDone = 0; // batch内的 成功件数 global Integer failedCount = 0; // batch内的 失败件数 global Integer fileNo; // 生成多个文件时,文件名尾部追加序号 private boolean overSizeFlg = false; // 当execute是否执行flag(false执行,true不执行) @TestVisible private static List messagesForTest; /** * 批准后, Trigger 会来调 */ global InventoryReportDtlArcRaesdBatch(Inventory_Header__c ih_new ,Integer fileNo, Integer totalCount, Integer totalCountDone) { this.emailMessages = new List(); this.ih_new = ih_new; this.fileNo = fileNo; this.totalCount = totalCount; this.totalCountDone = totalCountDone; } global Database.QueryLocator start(Database.BatchableContext bc) { // bp3_Setting__c conf = bp3_Setting__c.getOrgDefaults(); if (String.isBlank(folderId)) { 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(); 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' }); 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 = '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]); } //获取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; List assetIds = new List(); String idcQuerysql = 'select ' + String.join(new List(defaultAssetField), ', ') + ' from Inventory_Detail__c' + ' where Sync_Asset_Record_Flag__c = true' + ' and Inventory_Header__c = :ih_new_Id'; for (Inventory_Detail__c idc : Database.query(idcQuerysql)) { assetIds.add(idc.Asset__c); } String querysql = 'select ' + String.join(new List(defaultRaesdField), ', ') + ', Exported__c' + ' from Inventory_Detail__c where Asset__c IN :assetIds and Inventory_Header__c = :ih_new_Id and Asset_Status__c = \'出借中\'' + ' and Exported__c = false'; System.debug('InventoryReportDtlArcRaesdBatch Start 2>>>>>'); return Database.getQueryLocator(querysql); } global void execute(Database.BatchableContext BC, List raesdList) { // flag为true时,跳过execute处理 if (true == overSizeFlg) { //System.abortJob(BC.getJobId()); return; } executeCount += raesdList.size(); Integer DOC_MAX_SIZE = Integer.valueOf(System.Label.DocumentFileSize_KB.replaceAll(',', '')) * 1000; // 1024 ? 1000 ? 暂时用 1000 了 Savepoint sp = Database.setSavepoint(); try { List inventoryLst = new List(); String executeBodyRaesd = ''; // 借出明细 for (Integer i = 0; i < raesdList.size(); i++) { Inventory_Detail__c dl = raesdList[i]; String dummyRaesd = setDocBodyObject(dl, 'Raesd', false); Integer dummyRaesdSize = Blob.valueOf(dummyRaesd).size(); // 当前字符串大小未超过 DOC_MAX_SIZE if (dummyRaesdSize <= DOC_MAX_SIZE - docBodyRaesdBlobSize) { executeCountDone++; executeBodyRaesd += dummyRaesd; docBodyRaesdBlobSize += dummyRaesdSize; // 处理完毕对象Exported字段置true dl.Exported__c = true; inventoryLst.add(dl); } // 当前字符串大小超过 DOC_MAX_SIZE else { overSizeFlg = true; if (0 == fileNo) { fileNo++; } executeCount = executeCount - raesdList.size(); executeCount = executeCount + i; break; } } docBodyRaesd += executeBodyRaesd; system.debug('###executeCount : ' + executeCount); system.debug('###executeCountDone : ' + executeCountDone); // 处理完毕对象update update inventoryLst; } catch (Exception e) { Database.rollback(sp); failedCount += raesdList.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 == 'Raesd') { toCol = cListRaesdField; } 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 getArchiveFilenameForInsert(String typeStr, Inventory_Header__c ih_new, Integer fileNo) { // bp3_Setting__c conf = bp3_Setting__c.getOrgDefaults(); // Id folderId = conf.InventoryDetailArchiveFolder__c; // String fileNoStr = ''; // if (fileNo != 0) { // fileNoStr = '_' + String.valueOf(fileNo); // } // 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 + fileNoStr + '.csv'; // Document 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; // } //20231017 ymh 修改文档存储 start public ContentVersion getArchiveFilenameForInsert(String typeStr, Inventory_Header__c ih_new, Integer fileNo) { bp3_Setting__c conf = bp3_Setting__c.getOrgDefaults(); String fileNoStr = ''; if (fileNo != 0) { fileNoStr = '_' + String.valueOf(fileNo); } 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 + fileNoStr + '.csv'; String docBody = setDocBodyObject(null, typeStr, false); docBody += setDocBodyObject(null, typeStr, true); ContentVersion version = null; //20231103 ymh 修改优化sql查询 start List verlist = [SELECT Id, Title, VersionData,ContentDocumentId,IsMajorVersion FROM ContentVersion WHERE Title =:filename and FirstPublishLocationId =:folderId]; // List verlist = [SELECT Id, Title, VersionData,ContentDocumentId,IsMajorVersion FROM ContentVersion WHERE Title =:filename]; System.debug('verList是否存在----------->>>>>'+verlist); if( verlist.size() > 0 ){ version = verlist[0]; falg = true; // List linkList = [SELECT ContentDocumentId FROM ContentDocumentLink WHERE ContentDocumentId =:verlist[0].ContentDocumentId]; // if( linkList.size() > 0 ){ // version = verlist[0]; // falg = true; // } //20231103 ymh 修改优化sql查询 start }else{ version = new ContentVersion(); version.Title = filename; version.VersionData = Blob.valueOf(docBody); version.PathOnClient = filename+'.csv'; } return version; } public String insertContentDocumentLink(String versionId){ ContentVersion version = [select ContentDocumentId from ContentVersion where Id =: versionId]; String res=''; System.debug('存入link----------->>>>>'+version.ContentDocumentId); try{ ContentDocumentLink link = new ContentDocumentLink(); link.ContentDocumentId = version.ContentDocumentId; link.LinkedEntityId = folderId; link.ShareType = 'I'; link.Visibility = 'AllUsers'; StaticParameter.ContentDocumentLink = false; insert link; System.debug('link最后保存-------------'+link); res ='1'; }catch(Exception e){ res ='0'; return res; } return res; } global void finish(Database.BatchableContext BC) { if (docBodyRaesd == '') { this.emailMessages.add('Raesd数据不存在'); } else { if (this.emailMessages.size() == 0 && executeCount == executeCountDone) { // Document raesdDoc = getArchiveFilenameForInsert('Raesd', ih_new, fileNo); // raesdDoc.Body = Blob.valueOf(raesdDoc.Body.toString() + docBodyRaesd); // Database.SaveResult saveResult = Database.update(raesdDoc, false); ContentVersion raesdVersion; try{ raesdVersion = getArchiveFilenameForInsert('Raesd', ih_new, fileNo); raesdVersion.VersionData = Blob.valueOf(raesdVersion.VersionData.toString() + docBodyRaesd); }catch(Exception e){ System.debug(LoggingLevel.ERROR, e.getMessage() + '\n' + e.getStackTraceString()); this.emailMessages.add(e.getMessage() + '\n' + e.getStackTraceString()); } Database.SaveResult saveResult; String res ; if(falg){ // csv文件存在 update saveResult = Database.update(raesdVersion, false); }else{ //csv文件不存在 insert saveResult = Database.insert(raesdVersion, false); res = insertContentDocumentLink(raesdVersion.Id); } if (!saveResult.isSuccess() || res =='0') { failedCount = executeCountDone; // Docuemnt 都算成 fail this.emailMessages = FixtureUtil.setSaveError(new List{saveResult}, ContentVersion.sObjectType, new List{raesdVersion}, this.emailMessages); } //20231017 ymh 修改文档存储 end } totalCount += executeCount; totalCountDone += executeCountDone; // flag为true(字符串大小超过9.9M),且未发生错误时再次执行batch if (true == overSizeFlg && this.emailMessages.size() == 0 && executeCount == executeCountDone) { fileNo++; InventoryReportDtlArcRaesdBatch raesdBatch = new InventoryReportDtlArcRaesdBatch(ih_new, fileNo, totalCount, totalCountDone); Database.executeBatch(raesdBatch); } else { // TODO wwf email InventoryReportDtlArcRaesdBatch.messagesForTest = this.emailMessages; // 发 mail BatchEmailUtil be = new BatchEmailUtil(); String[] toList = new String[]{}; String title = '存档盘点CSV 盘点明细 #' + fileNo + ' '; if (false == overSizeFlg) { title += '最后 '; } 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; if(this.emailMessages.size() == 0 && totalCount == totalCountDone) { toList.add(UserInfo.getUserEmail()); be.successMail(toList, ccList, title, totalCountDone, text); } else { for(String email : System.Label.Inventory_Result_Email.split(',')){ ccList.add(email); } be.failedMail(toList, ccList, title, String.join(this.emailMessages, '\n'), totalCount, totalCountDone, failedCount, text); } be.send(); } } } }