public without sharing class SSOpportunity2Batch implements Database.Batchable, Database.Stateful { public static Integer FIELDMAX = 200; private final List TEST_ID = null; private BatchIF_Log__c iflog; //带参拍照,根据拍照 public SSOpportunity2Batch(List testId) { TEST_ID = testId; System.debug('TEST_ID=' + TEST_ID); iflog = new BatchIF_Log__c(); iflog.Type__c = 'SSOpportunity2Batch'; iflog.Log__c = 'SSOpportunity2Batch start\n'; iflog.ErrorLog__c = ''; insert iflog; } public static String makeSql(SS_Batch_Column_Mapping__c setting, Set apiTempSet) { apiTempSet.add('Id'); for (Integer i = 1; i <= FIELDMAX; i++) { String fromColumn = 'From_Column_' + ('00' + i).right(3) + '__c'; String apiStr = String.valueOf(setting.get(fromColumn)); if (String.isBlank(apiStr) == false && apiTempSet.contains(apiStr) == false) { apiTempSet.add(apiStr); } } String soql = 'Select ' + String.join(new List(apiTempSet), ',') + ',Opportunity__c,Opportunity__r.Opportunity_No__c ' + ' from ' + setting.Name; return soql; } //搜索拍照表的Sql方法 public static String makeSqlSS(SS_Batch_Column_Mapping__c setting, Set apiTempSet) { apiTempSet.add('Id'); for (Integer i = 1; i <= FIELDMAX; i++) { String fromColumn = 'SS_Column_' + ('00' + i).right(3) + '__c'; String apiStr = String.valueOf(setting.get(fromColumn)); if (String.isBlank(apiStr) == false && apiTempSet.contains(apiStr) == false) { //不搜索 “自定义设置”中 ,询价2自己本身的字段 if (apiStr.startsWith('Opportunity2__r.')){ break; } apiTempSet.add(apiStr); } } String soql = 'Select ' + String.join(new List(apiTempSet), ',')+ ',Opportunity_No__c ' + ' from ' + setting.SS_TableName__c; return soql; } public static Object getValue(SObject sobj, String field) { List fieldPathList = field.split('\\.'); Object rtn = null; for (Integer i = 0; i < fieldPathList.size(); i++) { String fieldPath = fieldPathList[i]; if (i == fieldPathList.size() - 1) { rtn = sobj.get(fieldPath); System.debug(rtn + '= sobj.get(' + fieldPath + ')'); } else { sobj = sobj.getSObject(fieldPath); if (sobj == null) { break; } System.debug(sobj + '= sobj.getSObject(' + fieldPath + ')'); } } return rtn; } //start方法里 查询<询价2>的数据(自定义设置左侧字段) public Database.QueryLocator start(Database.BatchableContext BC) { SS_Batch_Column_Mapping__c oppMapping = SS_Batch_Column_Mapping__c.getValues('Opportunity2__c'); Set apiTempSet = new Set(); apiTempSet.add('StageName__c'); for (Integer i = 1; i <= FIELDMAX; i++) { String lpadI = ('00' + i).right(3); String fromColumn = 'From_Column_' + lpadI + '__c'; String apiStr = String.valueOf(oppMapping.get(fromColumn)); if (String.isBlank(apiStr) == false) { String ssColumn = 'SS_Column_' + lpadI + '__c'; String ssApiStr = String.valueOf(oppMapping.get(ssColumn)); if (ssApiStr.startsWith('Opportunity2__r.')) { // 商談の項目を更新、変更があるかどうか判断するため、元データも取得 //为了判断商谈的项目是否有更新、变更,也要获取原始数据 System.debug('ssApiStr=' + ssApiStr + ', substring(16)=' + ssApiStr.substring(16)); apiTempSet.add(ssApiStr.substring(16)); } } } String soql = makeSql(oppMapping, apiTempSet); if (TEST_ID <> null) { soql += ' where Id IN: TEST_ID'; } else { // CHAN-AUE3TB Batch SSOpportunity的执行数据筛选 // 20230414 DB202304001752 start Date nowDay = Date.today(); nowDay = nowDay.addDays(-15); Integer iyear = nowDay.year()-1; if (nowDay.month() < 4) { iyear -= 1; } // Date thisYd = Date.valueOf(iyear + '-4-1'); Date thisYd = Date.valueOf(iyear + '-10-1'); // 20230414 DB202304001752 end soql += ' where StageName__c = \'询价\' or StageName__c = \'注残\' or StageName__c = \'发货\' or ((StageName__c = \'完毕\' or StageName__c = \'取消\' or StageName__c = \'失单\') and Opportunity__r.SFDCLast_Process_Date__c >= :thisYd)'; soql += ' or (StageName__c = \'完毕\' and Opportunity__r.Shipping_Finished_Day_Func__c >= :thisYd)'; } System.debug('soql=' + soql); return Database.getQueryLocator(soql); } public void execute(Database.BatchableContext BC, List oppList) { System.debug('start里初始List-oppList=' + oppList); //oppNoList 询价2 对应的询价的询价编码集合 List oppNoList = new List(); for (Opportunity2__c opp2 : oppList){ oppNoList.add(opp2.Opportunity__r.Opportunity_No__c); } System.debug('询价编码List-oppNoList=' + oppNoList); //查询SS拍照表 start SS_Batch_Column_Mapping__c oppMapping1 = SS_Batch_Column_Mapping__c.getValues('Opportunity2__c'); Set apiTempSet = new Set(); apiTempSet.add('StageName__c'); for (Integer i = 1; i <= FIELDMAX; i++) { String lpadI = ('00' + i).right(3); String fromColumn = 'From_Column_' + lpadI + '__c'; String apiStr = String.valueOf(oppMapping1.get(fromColumn)); if (String.isBlank(apiStr) == false) { String ssColumn = 'SS_Column_' + lpadI + '__c'; String ssApiStr = String.valueOf(oppMapping1.get(ssColumn)); if (ssApiStr.startsWith('Opportunity2__r.')) { // 商談の項目を更新、変更があるかどうか判断するため、元データも取得 //为了判断商谈的项目是否有更新、变更,也要获取原始数据 System.debug('ssApiStr=' + ssApiStr + ', substring(16)=' + ssApiStr.substring(16)); apiTempSet.add(ssApiStr.substring(16)); } } } String soql = makeSqlSS(oppMapping1, apiTempSet); //判断条件,SS拍照表的“考核月”字段在当月(thisto当月1日,thisto1下月1日) // 20240101 LHJ 修复年度切换 Start // Date nowDay = Date.today(); // Integer toyear = nowDay.year(); // Integer toMon = nowDay.month() - 1; // Integer toMon1 = nowDay.month(); // Date thisto = Date.valueOf(toyear + '-' + toMon +'-1'); // Date thisto1 = Date.valueOf(toyear + '-' + toMon1 +'-1'); Date nowDay = Date.today(); Integer toyear ; Integer toyear1 = nowDay.year(); Integer toMon ; Integer toMon1 = nowDay.month(); if(nowDay.month() == 1) { toyear = nowDay.year() - 1; toMon = 12; } else { toyear = nowDay.year(); toMon = nowDay.month() - 1; } Date thisto = Date.valueOf(toyear + '-' + toMon +'-1'); Date thisto1 = Date.valueOf(toyear1 + '-' + toMon1 +'-1'); // 20240101 LHJ 修复年度切换 End soql += ' where Evaluation_date__c >= :thisto And Evaluation_date__c < :thisto1 and Opportunity_No__c in :oppNoList'; System.debug('SS+soql=' + soql); List insSSOppList1 = Database.query(soql); System.debug('SS+insSSOppList1=' + insSSOppList1); //查询SS拍照表 end //Map(询价编码,拍照表) 根据询价编码对应 Map SSnumMap = new Map(); for(SObject SS : insSSOppList1){ SSnumMap.put(String.ValueOf(SS.get('Opportunity_No__c')),SS); } System.debug('SS+SSnumMap=' + SSnumMap); List updSelfList = new List(); List insSSOppList = new List(); //oppMapping(自定义设置的all),ssOppType(拍照表名),insSSOpp(Map拿到的SS拍照表数据) SS_Batch_Column_Mapping__c oppMapping = SS_Batch_Column_Mapping__c.getValues('Opportunity2__c'); Schema.SObjectType ssOppType = Schema.getGlobalDescribe().get(String.valueOf(oppMapping.get('SS_TableName__c'))); for (Opportunity2__c opp2 : oppList) { Boolean updSelfFlg = false; SObject insSSOpp = SSnumMap.get(opp2.Opportunity__r.Opportunity_No__c); for (Integer i = 1; i <= FIELDMAX; i++) { String lpadI = ('00' + i).right(3); String fromColumn = 'From_Column_' + lpadI + '__c'; String apiStr = String.valueOf(oppMapping.get(fromColumn)); if (String.isBlank(apiStr) == false) { String ssColumn = 'SS_Column_' + lpadI + '__c'; String ssApiStr = String.valueOf(oppMapping.get(ssColumn)); if (ssApiStr.startsWith('Opportunity2__r.')) { // 商談の項目を更新、変更があるかどうか判断する if(apiStr.startsWith('Opportunity__r.')){ if(apiStr == 'Opportunity__r.ImportDemonstration_state__c'){ if (opp2.get(ssApiStr.substring(16)) != opp2.Opportunity__r.ImportDemonstration_state__c){ opp2.put(ssApiStr.substring(16), opp2.Opportunity__r.ImportDemonstration_state__c); updSelfFlg = true; } }else if(apiStr == 'Opportunity__r.Amount_Without_Tax_Thousand_F__c'){ if (opp2.get(ssApiStr.substring(16)) != opp2.Opportunity__r.Amount_Without_Tax_Thousand_F__c){ opp2.put(ssApiStr.substring(16), opp2.Opportunity__r.Amount_Without_Tax_Thousand_F__c); updSelfFlg = true; } } } else if (opp2.get(ssApiStr.substring(16)) != opp2.get(apiStr)) { try { opp2.put(ssApiStr.substring(16), opp2.get(apiStr)); updSelfFlg = true; } catch (Exception e) { iflog.ErrorLog__c = 'ERROR [' + apiStr + '] => [' + ssApiStr + ']' + e.getMessage() + '\n'; } } } else { try { insSSOpp.put(ssApiStr, getValue(opp2, apiStr)); } catch (Exception e) { iflog.ErrorLog__c = 'ERROR1 ' + String.valueOf(oppMapping.get('SS_TableName__c')) + ' [' + apiStr + '] => [' + ssApiStr + ']' + e.getMessage() + '\n'; } } // try { // insSSOpp.put(ssApiStr, getValue(opp2, apiStr)); // } catch (Exception e) { // iflog.ErrorLog__c = 'ERROR2 ' + String.valueOf(oppMapping.get('SS_TableName__c')) + ' [' + apiStr + '] => [' + ssApiStr + ']' + e.getMessage() + '\n'; // } } } if (updSelfFlg) { updSelfList.add(opp2); } if (opp2.StageName__c == '询价' || opp2.StageName__c == '注残' || opp2.StageName__c == '发货' || opp2.StageName__c == '完毕' || opp2.StageName__c == '取消' || opp2.StageName__c == '失单') { if(insSSOpp != null){ insSSOppList.add(insSSOpp); } } } if (Oly_TriggerHandler.isBypassed('PowerBIBaseHandler') == false) { Oly_TriggerHandler.bypass('PowerBIBaseHandler'); } // エラーをlogに書き出す if (updSelfList.size() > 0) { System.debug('updSelfList:' + updSelfList); // SWAG-CE55BX 预测优化 start StaticParameter.EscapeOppandStaTrigger = true; // SWAG-CE55BX 预测优化 end Database.SaveResult[] lsr = Database.update(updSelfList, false); List reuseUpdateList = new List(); for (Integer tIdx = 0; tIdx < lsr.size(); tIdx++) { Database.SaveResult sr = lsr[tIdx]; System.debug('sr.isSuccess:' + sr.isSuccess()); if (!sr.isSuccess()) { //wangweipeng 20210618 获取没有update的数据 reuseUpdateList.add(updSelfList[tIdx]); } } //wangweipeng 20210618 如果update失败,重复更新,最多3次,如果失败记录日志 start if(reuseUpdateList != null && reuseUpdateList.size() > 0){ reuseUpdate(reuseUpdateList,1); } //wangweipeng 20210618 如果update失败,重复更新,最多3次,如果失败记录日志 end } System.debug('更新List==insSSOppList=' + insSSOppList); System.debug('更新List==insSSOppList.size()=' + insSSOppList.size()); if(insSSOppList.size() > 0 ){ Database.SaveResult[] lsr2 = Database.update(insSSOppList, false); for (Integer tIdx = 0; tIdx < lsr2.size(); tIdx++) { Database.SaveResult sr = lsr2[tIdx]; if (!sr.isSuccess()) { Database.Error emsg = sr.getErrors()[0]; //update by rentx 2020-10-27 start if (!String.valueOf(emsg.getStatusCode()).contains('INACTIVE_OWNER_OR_USER')) { iflog.ErrorLog__c += 'ERROR ' + insSSOppList[tIdx].get('Opportunity_No__c') + ' SS_opp:' + emsg + '\n'; } //update by rentx 2020-10-27 end // iflog.ErrorLog__c += 'ERROR ' + insSSOppList[tIdx].get('Opportunity_No__c') + ' SS_opp:' + emsg + '\n'; } } } } public void finish(Database.BatchableContext BC) { // if (Test.isRunningTest() == false && TEST_ID == null) { // Database.executeBatch(new SSBackorderBatch(null), 100); // } iflog.Log__c += '\nSSOpportunity2Batch end'; String tmp = iflog.ErrorLog__c; if (tmp.length() > 65000) { tmp = tmp.substring(0, 65000); tmp += ' ...have more lines...'; iflog.ErrorLog__c = tmp; } update iflog; } //wangweipeng 20210618 如果update失败,重复更新,最多3次,如果失败记录日志 start //参数:updSelfList 要重新插入的数据 indexUpdate 第几次插入 public void reuseUpdate(List updSelfList,Integer indexUpdate){ System.debug('这是此方法走的第:'+indexUpdate+' 次了。'); // SWAG-CE55BX 预测优化 start StaticParameter.EscapeOppandStaTrigger = true; // SWAG-CE55BX 预测优化 end Database.SaveResult[] lsr = Database.update(updSelfList, false); List reuseUpdateList = new List(); for (Integer tIdx = 0; tIdx < lsr.size(); tIdx++) { Database.SaveResult sr = lsr[tIdx]; if (!sr.isSuccess()) { if(indexUpdate >= 3){ Database.Error emsg = sr.getErrors()[0]; //update by Gzw 2020-10-30 start if (!String.valueOf(emsg.getStatusCode()).contains('INACTIVE_OWNER_OR_USER')) { iflog.ErrorLog__c += 'ERROR ' + updSelfList[tIdx].Id + ' Opportunity2__c:' + emsg + '\n'; } // iflog.ErrorLog__c += 'ERROR ' + updSelfList[tIdx].Opportunity_No__c + ' Opportunity2__c:' + emsg + '\n'; //update by Gzw 2020-10-30 end }else{ //获取没有update的数据 reuseUpdateList.add(updSelfList[tIdx]); } } } if(indexUpdate < 3){ indexUpdate ++; if(reuseUpdateList != null && reuseUpdateList.size() > 0){ reuseUpdate(reuseUpdateList,indexUpdate); } } } //wangweipeng 20210618 如果update失败,重复更新,最多3次,如果失败记录日志 end }