/**备品智能化 * 2023-12-28 Add by dzk * 计划外的OPD根据当前日期与拍照日,判断按照上月还是当月排序 * 获取下月14号——下下月13号,符合条件的OPD计划状态为计划中的备品申请数据 */ global class OPDAutomaticSortBeforeBatch implements Database.Batchable { private final List sdcName = null; private BatchIF_Log__c iflog; private Date specialDate; global OPDAutomaticSortBeforeBatch(){ this.iflog = new BatchIF_Log__c(); this.iflog.Type__c = 'OPDAutomaticSortBeforeBatch'; this.iflog.Log__c = 'OPDAutomaticSortBeforeBatch start\n'; this.iflog.ErrorLog__c = ''; insert this.iflog; } global OPDAutomaticSortBeforeBatch(List str){ this.sdcName = str; this.iflog = new BatchIF_Log__c(); this.iflog.Type__c = 'OPDAutomaticSortBeforeBatch'; this.iflog.Log__c = 'OPDAutomaticSortBeforeBatch start\n'; this.iflog.ErrorLog__c = ''; insert this.iflog; } global OPDAutomaticSortBeforeBatch(Date spDate) { this.specialDate = spDate; this.iflog = new BatchIF_Log__c(); this.iflog.Type__c = 'OPDAutomaticSortBeforeBatch'; this.iflog.Log__c = 'OPDAutomaticSortBeforeBatch start\n'; this.iflog.ErrorLog__c = ''; insert this.iflog; } global Database.QueryLocator start(Database.BatchableContext BC){ String sql = 'SELECT Id,Name,type__c FROM opp2AuxiliarySort__c '; sql += 'WHERE (type__c = 1 OR type__c = 11) '; if(sdcName <> null){ sql += 'AND Name IN :sdcName '; } sql += ' ORDER BY type__c'; System.debug('=sql='+sql); return Database.getQueryLocator(sql); } global void execute(Database.BatchableContext BC, List opp2AuxiliarySortList) { try{ // 获取当前日期 Date toDate = this.specialDate != null ? this.specialDate : Date.today(); // 获取当前月的拍照日 Date penultimateDate = getPenultimateWorkDayOfMonth(toDate); // 判断当前日期与拍照日的关系 // 今天大于当月拍照日 -> 当月拍照日 // 今天小于等于当月拍照日 -> 上月拍照日 penultimateDate = toDate > penultimateDate ? penultimateDate : getPenultimateWorkDayOfMonth(toDate.addMonths(-1)); // 根据拍照日确认计划实施日范围 // 获取从次月14日至再次月13日的日期 Date startDate = penultimateDate == Date.newInstance(2023, 12, 28) ? Date.newInstance(2024,1,1) : penultimateDate.addMonths(1).toStartOfMonth().addDays(13); Date endDate = penultimateDate.addMonths(2).toStartOfMonth().addDays(12); Map provinceSortMap = new Map(); // 获取符合条件的时间的已排序OPD计划最大排队序号 // 这里的话要检索自动排序或非自动排序但备品已分配的最大序号 List beforeOPDPlanList = [SELECT Id, Name, OPDLendSort__c FROM OPDPlan__c WHERE OPDPlanOCM_man_province_Rental__c =: opp2AuxiliarySortList[0].Name AND OPDPlan_ImplementDate__c >=: startDate AND OPDPlan_ImplementDate__c <=: endDate AND (If_AutoSort__c = 1 OR (If_AutoSort__c = 0 AND Bollowdate__c != null)) ORDER BY OPDLendSort__c DESC LIMIT 1]; iflog.Log__c += 'last sort: ' + beforeOPDPlanList != null && beforeOPDPlanList.size() > 0 ? beforeOPDPlanList[0].OPDLendSort__c : 0; // 获取符合条件的已排序的OPD计划数据 DateTime penultimateDateTime = DateTime.newInstance(penultimateDate, Time.newInstance(0, 0, 0, 0)); penultimateDateTime = penultimateDateTime.addHours(8); String soql = 'SELECT Id,SortDate__c,OPDPlanOCM_man_province_Rental__c,OPDLendSort__c,OPDLendSortDraft__c,SortOperator__c FROM OPDPlan__c '; //拼接SQL AccountType__c不一样 两种排序规则 String soql01 = ' WHERE OPDPlanOCM_man_province_Rental__c = \'' + opp2AuxiliarySortList[0].Name + '\''; soql01 += ' and Status__c = \'计划中\' '; // soql01 += ' and OPDPlan_ImplementDate__c >=: startDate ' ; soql01 += ' and OPDPlan_ImplementDate__c <=: endDate '; soql01 += ' and CreatedDate >=: penultimateDateTime '; soql01 += ' and AccountType__c = \'学会会议\' '; soql01 += ' and If_AutoSort__c != 1 '; soql01 += ' order by OPDPlan_ImplementDate__c ASC,CreatedDate ASC '; String soql02 = ' WHERE OPDPlanOCM_man_province_Rental__c = \'' + opp2AuxiliarySortList[0].Name + '\''; soql02 += ' and Status__c = \'计划中\' '; // soql02 += ' and OPDPlan_ImplementDate__c >=: startDate ' ; soql02 += ' and OPDPlan_ImplementDate__c <=: endDate '; soql02 += ' and CreatedDate >=: penultimateDateTime '; soql02 += ' and AccountType__c = \'医院\' '; soql02 += ' and If_AutoSort__c != 1 '; // 通过再申请生成的OPD计划 优先度最高,排在最前面 soql02 += ' order by Reapply__c DESC nulls last, OPDPlan_ImplementDate__c ASC, if_HaveEquipment__c ASC,'; soql02 += ' if_Newest_HaveOpportunity__c DESC nulls last ,if_OPDTarget__c DESC nulls last,if_HaveSalestarget__c DESC nulls last'; //分别查询结果后拼接 在遍历排序赋值 List tempList01 = Database.query(soql+soql01); List tempList02 = Database.query(soql+soql02); tempList01.addAll(tempList02); // 省份与排序 for(OPDPlan__c opdbefore : tempList01){ if(beforeOPDPlanList == null || beforeOPDPlanList.size() == 0 || beforeOPDPlanList[0].OPDLendSort__c == null){ provinceSortMap.put(opdbefore.OPDPlanOCM_man_province_Rental__c, 0); }else{ provinceSortMap.put(opdbefore.OPDPlanOCM_man_province_Rental__c, Integer.valueOf(beforeOPDPlanList[0].OPDLendSort__c)); } } // 获取符合条件的OPD计划下的出借备品申请 List opdUpdateList = new List(); // for(OPDPlan__c opdp : sortedOPDList) { for(OPDPlan__c opdp : tempList01) { String opdProvince = opdp.OPDPlanOCM_man_province_Rental__c; opdp.OPDLendSort__c = provinceSortMap.get(opdProvince) + 1; opdp.OPDLendSortDraft__c = provinceSortMap.get(opdProvince) + 1; provinceSortMap.put(opdProvince, Integer.valueOf(opdp.OPDLendSort__c)); opdp.SortDate__c = Date.today(); opdp.SortOperator__c = userInfo.getUserId(); opdp.If_AutoSort__c = 0; opdUpdateList.add(opdp); } // if (sortedOPDList != null && sortedOPDList.size() > 0) { // update sortedOPDList; // } if (opdUpdateList != null && opdUpdateList.size() > 0) { update opdUpdateList; } }catch(Exception ex){ iflog.ErrorLog__c = ex.getLineNumber()+' 行错误 : '+ex.getMessage(); return; } } global void finish(Database.BatchableContext BC) { iflog.Log__c += '\nOPDAutomaticSortBeforeBatch end' ; String tmp = iflog.ErrorLog__c; if (tmp != null && tmp.length() > 65000) { tmp = tmp.substring(0, 65000); tmp += ' ...have more lines...'; iflog.ErrorLog__c = tmp; } update iflog; } // 获取倒数第二个工作日 public Date getPenultimateWorkDayOfMonth(Date metaDate) { // 获取待查日期+1月的第一天 Date firstDayOfNextMonth = metaDate.addMonths(1).toStartOfMonth(); // 此表会维护一个工作日的日历 其中排除掉了周末及节假日 此处通过倒叙排序加limit 2 只拿到倒数第二个工作日 List olympusCalendarDate = [ Select Date__c From OlympusCalendar__c Where Date__c < :firstDayOfNextMonth And IsWorkDay__c = 1 ORDER BY Date__c DESC LIMIT 2 ]; Date firstWorkDayOfMonth = metaDate; if (olympusCalendarDate != null && olympusCalendarDate.size() > 1) { firstWorkDayOfMonth = olympusCalendarDate.get(1).Date__c; } return firstWorkDayOfMonth; } //add by allen 拆分部署ali生产 public void testMock(){ Integer i = 0; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; i++; } }