global class CreatePassiveTaskBatch implements Database.Batchable, Database.Stateful { //自定义设置是根据当前年度产品生产预计所声明的api与产品名, //因为每年产品生产都有所变更,所以每年在产品生产任务确定后, //都要核对自定义设置中的产品api与产品名 //此batch需要核对的是 PlanMonthAndAmount/PlanMonthAndAmountName/OPD_PlanMonth //自定义设置opd计划月与对应的opd计划数Api SS_Batch_Column_Mapping__c planMonthAndAmount = SS_Batch_Column_Mapping__c.getValues('PlanMonthAndAmount'); //自定义设置opd计划月api与对应的opd计划数名字 SS_Batch_Column_Mapping__c PlanMonthAndAmountName = SS_Batch_Column_Mapping__c.getValues('PlanMonthAndAmountName'); // 报错的询价ID public String logstr = ''; // 报错信息 public String errorstr = ''; public List emailMessages = new List(); public Integer totalCount = 0; // 总件数 public Integer failedCount = 0; // 失败件数 Integer FIELDMAX = 30; //自定义设置opd计划数 List opdNumberList = new List(); //销售本部 public String Salesdepartment_DeptClass; // 2021-06-16 mzy SWAG-C3VA6S 【委托】华东 OPD任务 更改为产品担当派发 public String testId ; // 2021-06-16 mzy SWAG-C3VA6S 【委托】华东 OPD任务 更改为产品担当派发 //定义拼接opd计划月Api的自定义设置 String planMonth = ''; //定义拼接opd计划数Api的自定义设置 String planNumber = ''; //自定义设置opd计划月api与名字Map Map opdPlanMonthMap = new Map(); //opd计划月API与opd计划数Api的Map Map planMonthAndAmountMap = new Map(); //opd计划月api对应的opd计划数名字 Map> PlanMonthAndAmountNameMap = new Map>(); Date dt = Date.today(); string HPID = ''; string departmentID = ''; Boolean isAutoexec = false; //20210203 zh SWAG-BXQDHZ 是否自动执行 //针对于单独某个医院 global CreatePassiveTaskBatch(String TestID) { HPID = TestID; isAutoexec = false; //20210203 zh SWAG-BXQDHZ } //针对于单独某个战略科室 global CreatePassiveTaskBatch(String TestID, boolean a) { departmentID = TestID; isAutoexec = false; //20210203 zh SWAG-BXQDHZ } global CreatePassiveTaskBatch() { } global CreatePassiveTaskBatch(Boolean tempOPD) { isAutoexec = tempOPD; //20210203 zh SWAG-BXQDHZ } // 2021-06-16 mzy SWAG-C3VA6S 【委托】华东 OPD任务 更改为产品担当派发 start //针对于单独某个销售本部 global CreatePassiveTaskBatch(String TestSalesdepartment,String b) { this.Salesdepartment_DeptClass = TestSalesdepartment; this.isAutoexec = false; //20210203 zh SWAG-BXQDHZ } global CreatePassiveTaskBatch(String TestSalesdepartment,String b,string testId) { this.Salesdepartment_DeptClass = TestSalesdepartment; this.testId = testId; this.isAutoexec = false; //20210203 zh SWAG-BXQDHZ } // 2021-06-16 mzy SWAG-C3VA6S 【委托】华东 OPD任务 更改为产品担当派发 end global Database.QueryLocator start(Database.BatchableContext BC) { // 规定年份格式(今年四月份到下一年4月份为一年)(如:今年-1867+p 135p) //Datetime dt; Date dateToday = Date.today(); Date nextmonth = dateToday.addMonths(1); //system.debug('nextmonth' + nextmonth); Integer year = nextmonth.year(); Integer month = nextmonth.month() ; //system.debug('month' + month); if (month < 4) { year = year - 1; } String ThisPeriod = year - 1867 + 'P'; //Integer ThisYear = Integer.valueOf(dt.year()); //String ThisPeriod = ThisYear - 1867 + 'P'; //String CurrentPeriodPaymentAmountBatchTest = data.valueOf(SUBSTR(data,6,7)) + '月'; //String OPD_PlanMonth; //String OPD_Number; //opd计划月api不为空的拼接定义 String planMonthString = ''; String planMonthWhere = ''; //获取自定义设置opd计划月api与opd计划数的名字 for (Integer i = 1; i <= FIELDMAX; i++) { String lpadI = ('00' + i).right(3); String fromColumn = 'From_Column_' + lpadI + '__c'; //system.debug('fromColumn' + fromColumn); // api String apiStr = String.valueOf(PlanMonthAndAmountName.get(fromColumn)); String ssColumn = 'SS_Column_' + lpadI + '__c'; // api对应的名字 String ssApiStr = String.valueOf(PlanMonthAndAmountName.get(ssColumn)); //system.debug('apiStr' + apiStr); // HWAG-BUD4B7 2021.6.2 Start if (!String.isBlank(apiStr) && !String.isBlank(ssApiStr)) { list ppdValue = ssApiStr.split(','); //system.debug('apiStr111' + apiStr + 'ssApiStr' + ssApiStr); //apiStr存计划月api //ppdValue存计划月数的名字 PlanMonthAndAmountNameMap.put(apiStr, ppdValue); } } //获取自定义设置opd计划月api与opd计划数的api for (Integer i = 1; i <= FIELDMAX; i++) { String lpadI = ('00' + i).right(3); String fromColumn = 'From_Column_' + lpadI + '__c'; //system.debug('fromColumn' + fromColumn); String apiStr = String.valueOf(planMonthAndAmount.get(fromColumn)); //system.debug('apiStr' + apiStr); if (!String.isBlank(apiStr)) { String ssColumn = 'SS_Column_' + lpadI + '__c'; String ssApiStr = String.valueOf(planMonthAndAmount.get(ssColumn)); //system.debug('apiStr111' + apiStr + 'ssApiStr' + ssApiStr); planMonthAndAmountMap.put(apiStr, ssApiStr); } } // 遍历计划月api,用来获取opd计划月和opd计划数及计划月不为空的条件 //拼接opd计划月api for (String apiKey : planMonthAndAmountMap.keySet()) { planMonth += ' , ' + apiKey; //拼接opd计划数api planNumber += ' , ' + planMonthAndAmountMap.get(apiKey); //不为空计划月不为空的拼接 planMonthString += apiKey + '!=null or '; } // 计划月不为空的条件 planMonthWhere = planMonthString.substring(0, planMonthString.length() - 3); system.debug('planMonth: ' + planMonth); system.debug('planNumber: ' + planNumber); system.debug('planMonthWhere: ' + planMonthWhere); system.debug('ThisPeriod:' + ThisPeriod); //检索今年全部的目标客户 String soql = 'select id, name , Account__c , Account__r.name, Account__r.ownerid ,Account__r.owner.IsActive,Product_Leader__r.IsActive,Product_Leader__c '; soql += planMonth; soql += planNumber; // 本月暂时不对华东的任务进行派发 soql += ' from Account_Number_of_target__c where ' + ' OCM_Period__c = : ThisPeriod and '; soql += '('; soql += planMonthWhere; soql += ')'; // 检索 计划月不为空,OCSM期 = 规定年份 的目标客户 // select id, name , Account__c , Account__r.name, Account__r.ownerid planMonth planNumber // from Account_Number_of_target__c where OCM_Period__c = : ThisPeriod and apiKey != null; if (string.isNotBlank(HPID)) { soql += ' and Account__r.parentID =: HPID '; } // 针对于单独某个医院(目标客户的母公司 = 医院) // select id, name , Account__c , Account__r.name, Account__r.ownerid planMonth planNumber // from Account_Number_of_target__c where OCM_Period__c = : ThisPeriod and apiKey != null // and Account__r.parentID =: HPID; if (string.isNotBlank(departmentID)) { soql += ' and Account__c =: departmentID '; } // 针对于单独某个战略科室(战略科室=战略科室) // select id, name , Account__c , Account__r.name, Account__r.ownerid planMonth planNumber // from Account_Number_of_target__c where OCM_Period__c = : ThisPeriod and apiKey != null // and Account__c =: departmentID; // 针对于单独某个销售本部 (销售本部 = 销售本部) // 2021-06-16 mzy SWAG-C3VA6S 【委托】华东 OPD任务 更改为产品担当派发 start if (string.isNotBlank(Salesdepartment_DeptClass)){ soql += ' and Account__r.Salesdepartment_DeptClass__c =: Salesdepartment_DeptClass '; } if (String.isNotBlank(testId)){ soql += ' and id =: testId'; } // 2021-06-16 mzy SWAG-C3VA6S 【委托】华东 OPD任务 更改为产品担当派发 end /* SFDC-BVN43P 额外判断,如果不是非要执行,那么如果战略科室所在 * 医院是无效医院,那么就不针对这家战略科室下达任务 start */ if (string.isBlank(HPID) && string.isBlank(departmentID)) { soql += ' and Account__r.Parent.Is_Active__c = \'有効\' '; } // SFDC-BVN43P end //20210311 zh SWAG-BYX9W7 【委托】OPD任务 3月运行 // 除15号(从自定义标签中获取)外 并且 不自动执行时 检索到的目标客户为空 Integer runDay = Integer.valueOf(Label.OPD_RunTime); //20210203 zh SWAG-BXQDHZ start if (Date.today().day() != runDay && isAutoexec == true) { soql = 'select id from Account_Number_of_target__c where Name=\'\' and Name!=\'\' '; } //20210203 zh SWAG-BXQDHZ end system.debug('测试 :' + soql); //初始化,得到想要处理的数据(目标客户) return Database.getQueryLocator(soql); } global void execute(DataBase.BatchableContext BC, List ANOTList) { //system.debug('进入execute'); //任务List List taskList = new List(); List anotAccountIdList = new List(); //科室与opd计划Map Map> anIdAndOpdlanMap = new Map>(); //opd计划月Api与opd计划产品名 SS_Batch_Column_Mapping__c mpdMapping = SS_Batch_Column_Mapping__c.getValues('OPD_PlanMonth'); //获取自定义设置opd计划月api与对应的产品名,将其存入Map中 for (Integer i = 1; i <= FIELDMAX; i++) { String lpadI = ('00' + i).right(3); String fromColumn = 'From_Column_' + lpadI + '__c'; //system.debug('fromColumn' + fromColumn); String apiStr = String.valueOf(mpdMapping.get(fromColumn)); //system.debug('apiStr' + apiStr); if (String.isBlank(apiStr) == false && apiStr != null) { String ssColumn = 'SS_Column_' + lpadI + '__c'; String ssApiStr = String.valueOf(mpdMapping.get(ssColumn)); //system.debug('apiStr111' + apiStr + 'ssApiStr' + ssApiStr); opdPlanMonthMap.put(apiStr, ssApiStr); } } //2.战略客户IdList // 将战略客户转换成字符串(取其前15),存入List中 for (Account_Number_of_target__c anot : ANOTList) { //system.debug(anot.name + ' :' + anot.id); String anotAccount = String.valueOf(anot.Account__c); anotAccountIdList.add(anotAccount.substring(0, 15)); } //OPDPlan__c op = [select OCM_category_ID__c from OPDPlan__c]; //system.debug('op+++++++++++++++++' + op); system.debug('anotAccountIdList:' + anotAccountIdList); // SWAG-BZL93B 改为运行财年的计划中、完毕未报告的OPD计划 start // 原代码 /* Date firstDay = Date.today().toStartOfMonth(); Date nextDate = firstDay.addMonths(1); Date nextTwoDate = firstDay.addMonths(2); List OPDPlanAllList = [select id, PlanProdDetail__c, OCM_category_Name__c, OCM_category_ID__c, OPD_Customers_Target__c, OPDPlan_ImplementDate__c from OPDPlan__c where OCM_category_ID__c in:anotAccountIdList and OPDPlan_ImplementDate__c >= : nextDate and OPDPlan_ImplementDate__c < : nextTwoDate and (Status__c != '取消' or Status__c != '完毕' or Status__c != '草案中')]; */ // 定义Fy开始日和结束日(作为检索opd计划的条件) Integer year = Date.today().year(); Integer month = Date.today().month() ; if (month < 3) { year--; } Date FYfirstDay = date.newInstance(year, 4, 1); Date FYLastDay = FYfirstDay.addMonths(12); // OPD计划实施日期:OPDPlan_ImplementDate__c // 战略科室ID:OCM_category_ID__c // 状态为计划中或完毕未报告 并且 OPD计划实施日期大于等于Fy开始日 并且 小于 结束日 并且 每个战略科室对应的opd计划(opd计划所关联的战略科室被包含在所有战略科室中) List OPDPlanAllList = [select id, PlanProdDetail__c, OCM_category_Name__c, OCM_category_ID__c, OPD_Customers_Target__c, OPDPlan_ImplementDate__c from OPDPlan__c where OCM_category_ID__c in:anotAccountIdList and OPDPlan_ImplementDate__c >= : FYfirstDay and OPDPlan_ImplementDate__c < : FYLastDay and (Status__c = '计划中' or Status__c = '完毕未报告')]; // SWAG-BZL93B 改为运行财年的计划中、完毕未报告的OPD计划 end //3.战略客户下全部的Opd计划 // 1、创建一个存opd计划Id的list // 2、遍历存战略科室Id的list(String) // 3、遍历检索出来的opd计划 // 4、将 战略科室(key)检索出来的opd计划 (value) // 5、将 opd计划存入list(String) system.debug('OPDPlanAllList:' + OPDPlanAllList); for (String opdpId : anotAccountIdList) { list tempOPDList = new List(); for (OPDPlan__c opdp : OPDPlanAllList) { //system.debug('opdpId' + opdpId); //system.debug('opdp.OCM_category_ID__c' + opdp.OCM_category_ID__c); if (opdpId == opdp.OCM_category_ID__c) { // 战略科室与opd计划 tempOPDList.add(opdp); } anIdAndOpdlanMap.put(opdpId, tempOPDList); } } //system.debug('anIdAndOpdlanMap:' + anIdAndOpdlanMap); //List preList = [select name from Plan_Rental_Equipment__c where OPD_Plan__c in: opIdList ]; //6 目标客户 // 遍历目标客户 //遍历opd计划月Api,opd计划月Api(key) 产品名(value) //获取客户opd月值,如果客户opd计划月值为空的话,跳出循环 //opd计划月的值(将其转换成String类型) // 如果 opd计划月的值 不等于空 将 opd计划月的值赋值给(Integer类型的变量) // 如果 opd计划月的值为空 或 opd计划月大于下个月(当前月的值+1) 则跳出循环 // 如果以上条件不满足 for (Account_Number_of_target__c anot : ANOTList) { //产品明细 String producDetail = ''; //opd计划 String ocn = ''; String al = ''; //遍历opd计划月Api,opd计划月Api(key) 产品名(value) for (String planMonthAndAmountMapKey : opdPlanMonthMap.keySet()) { //system.debug( anot.name + '的计划月:' + planMonthAndAmountMapKey); //然后再在这里写对应的opd数是否为空 Boolean anotFlage = true; boolean FlagBl = true; //获取客户opd月值,如果客户opd计划月值为空的话,跳出循环 if (anot.get(planMonthAndAmountMapKey) == null) { continue; } //opd计划月的值(将其转换成String类型) String opdNu = String.valueOf(anot.get(planMonthAndAmountMapKey)); Integer MonthNumber; // 如果 opd计划月的值 不等于空 将 opd计划月的值赋值给(Integer类型的变量) if (!String.isBlank(opdNu)) { // 月份 MonthNumber = Integer.valueOf(opdNu.substring(0, opdNu.length() - 1)); } // opd计划月 if (MonthNumber < 4) { MonthNumber += 12; } // 下个月 Integer dm = datetime.now().month() + 1; if (dm < 4) { dm += 12; } // 如果 opd计划月的值为空 或 opd计划月大于下个月(当前月的值+1) 则跳出循环 if (String.isBlank(opdNu) || MonthNumber > dm) { continue; } else { //opd计划数api数组 String[] opdNumberAmountValue; //符合条件的opd计划月下的opd计划数 String planMonthAndAmountMapValue = ''; //获取opd计划数api,将其以‘,’为分隔符存入list(String)中 planMonthAndAmountMapValue = planMonthAndAmountMap.get(planMonthAndAmountMapKey); opdNumberAmountValue = planMonthAndAmountMapValue.split(','); // 遍历 opd计划数api { // 1、判断对应的opd数是否为空 如果 // 1、不为空 // 1、boolean变量为false // 2、为空 // 1、获取 opd计划 (如果没有,则新创一个opd) // 2、循环比对已存在的计划出借备品信息和理论上存在的计划出借备品信息 // 1、如果 有计划出借备品信息 则 将计划出借备品信息以‘;’为分隔符存入list(String)中 // 1、遍历计划出借备品信息 // 1、得到每一个备品 // 2、得到每一个计划数名字(通过map获取全部的计划数名字,再将其遍历获取单个计划书名字,之后将其备品与计划数名字进行对比,如果相等(表示有对应的opd计划)则跳出循环) // } for (String nav : opdNumberAmountValue) { FlagBl = true; nav = nav == null ? nav : nav.trim(); //system.debug('nav:'+nav); //system.debug('sss:'+anot.get(nav)); // anot.get(nav):客户opd计划数的值 if (!String.isBlank(String.valueOf(anot.get(nav))) && Integer.valueOf(anot.get(nav)) != 0 ) { anotFlage = false; //system.debug('sss:'+anot.get(nav)); } else { //for(String ocnId : anIdAndOpdlanMap.keySet()){ //opd计划 List OPDPlanList = anIdAndOpdlanMap.get( string.valueOf(anot.Account__c).substring(0, 15)); //system.debug('anot.Account__c:' + anot.Account__c); //system.debug('OPDPlanList' + OPDPlanList.get(0)); if (OPDPlanList == null ) { OPDPlanList = new List(); } //system.debug('OPDPlanList' + OPDPlanList.get(0)); //循环比对已存在的计划出借备品信息和理论上存在的计划出借备品信息 for (OPDPlan__c opdp : OPDPlanList) { //system.debug('planMonthAndAmountMapKey:' + planMonthAndAmountMapKey); //system.debug('opdp:' + opdp); //opd计划.计划出借备品信息 String ppd = opdp.PlanProdDetail__c; String[] ppdValue; // 如果 有计划出借备品信息 则 将计划出借备品信息以‘;’为分隔符存入list(String)中 // 1、遍历计划出借备品信息 // 1、得到每一个备品 // 2、得到每一个计划数名字(通过map获取全部的计划数名字,再将其遍历获取单个计划书名字,之后将其备品与计划数名字进行对比,如果相等(表示有对应的opd计划)则跳出循环) if (!String.isBlank(ppd) ) { // 备品 ppdValue = ppd.split(';'); //system.debug('计划出借备品信息' + ppdValue); for (String ppdVa : ppdValue) { //system.debug('nav:'+nav); // 备品 ppdVa = ppdVa.trim().substring(0, ppdVa.trim().length() - 2); //system.debug('ppdVa1:' + ppdVa); // opd计划数的名字,planMonthAndAmountMapKey(opd计划月) list stringList = PlanMonthAndAmountNameMap.get(planMonthAndAmountMapKey); //system.debug('stringList:' + stringList); for (string str : stringList) { //system.debug('str:' + str); // 备品 = 计划数的名字 if (str.equals(ppdVa)) { //system.debug('anotFlage:' + anotFlage); FlagBl = false; anotFlage = false; } } } } //ocn = opdp.OCM_category_Name__c; //al = opdp.Account_Laboratory__c; //} } if (FlagBl = false) { continue; } } } if (anotFlage == false) { continue; } // 将产品名: opd计划月的值 赋值给 产品明细变量上 producDetail += opdPlanMonthMap.get(planMonthAndAmountMapKey) + ':' + opdNu + ';'; } } system.debug( anot.name + '的产品明细:' + producDetail); // 如果产品明细不为空 则任务的 // 被分配者-战略科室的所有人 // 所有人-所有人 // 产品明细-产品明细 // 记录类型-OPD // 任务区分-‘被动任务’ // 任务名称-‘用户拜访:’ + 战略科室名 // 客户-战略科室 // 任务状态2-‘01 分配’ // 将任务添加到list(task__c) if (!string.isBlank(producDetail) && ((anot.Product_Leader__c !=null && anot.Product_Leader__r.IsActive) || (anot.Account__c !=null && anot.Account__r.owner.IsActive))) {//2021-08-30 yjk 增加判断任务对应的用户必须为IsActive ocn = anot.Account__r.name; al = anot.Account__c; task__c newTask = new task__c(); // 被分配者 // 2021-06-16 mzy SWAG-C3VA6S 【委托】华东 OPD任务 更改为产品担当派发 start if(anot.Product_Leader__c != null){ newTask.assignee__c = anot.Product_Leader__c; newTask.ownerid = anot.Product_Leader__c; }else{ newTask.assignee__c = anot.Account__r.ownerid; newTask.ownerid = anot.Account__r.ownerid; } // 2021-06-16 mzy SWAG-C3VA6S 【委托】华东 OPD任务 更改为产品担当派发 end // 产品明细 newTask.ProductDetails__c = producDetail; newTask.RecordTypeId = Schema.SObjectType.task__c.getRecordTypeInfosByDeveloperName().get('OPD').getRecordTypeId(); // 任务区分 newTask.taskDifferent__c = '被动任务'; // 任务名称 newTask.Name = '用户拜访:' + ocn; // 客户 newTask.account__c = al; //newTask.OpportunityId__c = opdp.Id; // 任务状态2 newTask.taskStatus__c = '01 分配'; taskList.add(newTask); } } // 如果list中有任务 则 // 将该任务添加到数据库中 // 计数,添加了几条 // 循环,任务的条数 // 如果没添加成功,将‘被动任务’:该任务 存到日志中,将第几条的报错信息存到错误日志中,计数总共没添加成功几条 // 2021-12-13 yjk 取消OPD任务的派发 // if (taskList.size() > 0) { // Database.SaveResult[] saveResults = Database.insert(taskList, false); // totalCount = + saveResults.size(); // for (Integer i = 0; i < saveResults.size(); i++) { // if (!saveResults.get(i).isSuccess()) { // logstr += '被动任务:' + taskList.get(i).Account__c + ' ,'; // errorstr += saveResults.get(i).getErrors() + '\n'; // failedCount ++; // } // } // } } // 创建日志(用来存添加失败的任务,以及每一条添加失败的信息) global void finish(Database.BatchableContext BC) { BatchIF_Log__c batchIfLog = new BatchIF_Log__c(); batchIfLog.Type__c = 'CreatePassiveTaskBatch'; if (logstr.length() > 60000) { logstr = logstr.substring(0, 60000); } batchIfLog.Log__c = logstr; logstr += '\nCreatePassiveTaskBatchEnd'; if (errorstr.length() > 60000) { batchIfLog.ErrorLog__c = errorstr.substring(0, 60000); } else { batchIfLog.ErrorLog__c = errorstr.substring(0, errorstr.length()); integer i = 0; i++; i++; I++; i++; i++; i++; } insert batchIfLog; emailMessages.add('失败日志ID为:' + batchIfLog.Id); sendFieldEmail(); //2021-07-12 mzy update start SLA定期任务开发 if(!System.Test.isRunningTest() && isAutoexec == true){ Database.executebatch(new CreateNewMaintenanceTaskBatch(true)); } //2021-07-12 mzy update end SLA定期任务开发 } // 发送提醒邮件 // 1、如果战略科室为空 并且 医院为空 则 // 定义两个数组(一个为空,一个存接收邮件者,一个存抄送人)及一个标题 // 如果邮件信息有值 并且 失败总数大于0 则 // 发送失败邮件的内容为:接收人,抄送人,标题,将全部的错误日志显示出来,总数,成功数,失败数 // 如果!Test.isRunningTest,则发送 private void sendFieldEmail() { // HWAG-BUD4B7 2021.6.3 Start if (isAutoexec) { // HWAG-BUD4B7 2021.6.3 End PretechBatchEmailUtil be = new PretechBatchEmailUtil(); String[] toList = new String[] {UserInfo.getUserEmail()}; String title = '创建被动任务失败'; String[] ccList = new String[] {}; if (System.Test.isRunningTest()) { be.successMail('', 1); } if (emailMessages.size() > 0 && failedCount > 0) { be.failedMail(toList, ccList, title, String.join(this.emailMessages, '\n'), totalCount, totalCount - failedCount, failedCount, '', true); if (!System.Test.isRunningTest()) be.send(); } } } }