/**备品智能化
|
* 2023-12-28 Add by dzk
|
* 计划外的OPD根据当前日期与拍照日,判断按照上月还是当月排序
|
* 获取下月14号——下下月13号,符合条件的OPD计划状态为计划中的备品申请数据
|
*/
|
global class OPDAutomaticSortBeforeBatch implements Database.Batchable<sObject> {
|
private final List<String> sdcName = null;
|
private BatchIF_Log__c iflog;
|
private Date specialDate;
|
private Boolean allOutofPlan = false;
|
// 2024-01-24 ssm 增加一个判断,在月末倒数第二个工作日的时候执行上月排序拷贝操作 start
|
private Boolean executeCopyToBefore = false;
|
// 2024-01-24 ssm 增加一个判断,在月末倒数第二个工作日的时候执行上月排序拷贝操作 end
|
|
global OPDAutomaticSortBeforeBatch(Boolean exe){
|
// 2024-01-24 ssm 增加一个判断,在月末倒数第二个工作日的时候执行上月排序拷贝操作 start
|
this.executeCopyToBefore = exe;
|
// 2024-01-24 ssm 增加一个判断,在月末倒数第二个工作日的时候执行上月排序拷贝操作 end
|
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<String> 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 OPDAutomaticSortBeforeBatch(Boolean allOP, Date spDate) {
|
this.allOutofPlan = allOP;
|
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<opp2AuxiliarySort__c> 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<String,Integer> provinceSortMap = new Map<String,Integer>();
|
// 获取符合条件的时间的已排序OPD计划最大排队序号
|
// 这里的话要检索自动排序或非自动排序但备品已分配的最大序号
|
// 上线后优化
|
// 1.增加排序号不为空的判断
|
// 2.增加计划外的OPD被取消的判断,状态取消也作为序号最大值的判断条件之一
|
// 20240115 ssm 为处理历史数据方便,增加所有计划外手动重新排队分支 start
|
String orderquery = 'SELECT Id, Name, OPDLendSort__c FROM OPDPlan__c ';
|
orderquery += 'WHERE OPDPlanOCM_man_province_Rental__c = \'' + opp2AuxiliarySortList[0].Name + '\' ';
|
orderquery += 'AND OPDPlan_ImplementDate__c >= :startDate ';
|
orderquery += 'AND OPDPlan_ImplementDate__c <= :endDate ';
|
orderquery += 'AND OPDLendSort__c != null ';
|
// 20240227 ssm 备品可视化补充 start
|
// 上月残留的就不进排序队列了,序号也不用
|
orderquery += 'AND Last_Month_Untreated__c = false ';
|
// 20240227 ssm 备品可视化补充 end
|
if (this.allOutofPlan) {
|
orderquery += 'AND If_AutoSort__c = 1 ';
|
} else {
|
// 2024-02-01 ssm 增加非上月残留的条件 start
|
// 上月残留的OPD计划就不再重新排序以及占用序号了
|
// orderquery += 'AND (If_AutoSort__c = 1 OR (If_AutoSort__c = 0 AND (Bollowdate__c != null OR Status__c = \'取消\'))) ';
|
orderquery += 'AND (If_AutoSort__c = 1 OR (If_AutoSort__c = 0 AND (Bollowdate__c != null OR Status__c = \'取消\'))) ';
|
// 2024-02-01 ssm 增加非上月残留的条件 end
|
}
|
orderquery += 'ORDER BY OPDLendSort__c DESC LIMIT 1 ';
|
List<OPDPlan__c> beforeOPDPlanList = Database.query(orderquery);
|
// List<OPDPlan__c> 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 OPDLendSort__c != null
|
// AND (If_AutoSort__c = 1 OR (If_AutoSort__c = 0 AND (Bollowdate__c != null OR Status__c = '取消')))
|
// ORDER BY OPDLendSort__c DESC LIMIT 1];
|
// 20240115 ssm 为处理历史数据方便,增加所有计划外手动重新排队分支 end
|
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 + '\'';
|
// 20240115 ssm 为处理历史数据方便,增加所有计划外手动重新排队分支 start
|
if (this.allOutofPlan) {
|
soql01 += ' and Status__c != \'草案中\' and Status__c != \'审批中\' ';
|
} else {
|
soql01 += ' and (Status__c = \'计划中\' OR (Status__c in (\'完毕未报告\', \'待提交报告\', \'完毕\') and OPDLendSort__c = null))';
|
}
|
// 20240115 ssm 为处理历史数据方便,增加所有计划外手动重新排队分支 end
|
// soql01 += ' and OPDPlan_ImplementDate__c >=: startDate ' ;
|
soql01 += ' and OPDPlan_ImplementDate__c <=: endDate ';
|
// 2024-02-01 ssm 计划外进入条件调整 start
|
// 考虑创建日和审批日不相同的情况,用审批日更合理一些。对象上增加审批通过日,在批准过程最终批准时增加赋值。
|
soql01 += ' and (CreatedDate >=: penultimateDateTime ';
|
soql01 += ' or ApprovePassed__c >= :penultimateDate) ';
|
// 2024-02-01 ssm 增加非上月残留的条件 end
|
soql01 += ' and AccountType__c = \'学会会议\' ';
|
// 2024-02-01 ssm 增加非上月残留的条件 start
|
// 重新排序时也增加相应判断
|
soql01 += ' and Last_Month_Untreated__c = false ';
|
// 2024-02-01 ssm 增加非上月残留的条件 end
|
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 + '\'';
|
// 20240115 ssm 为处理历史数据方便,增加所有计划外手动重新排队分支 start
|
if (this.allOutofPlan) {
|
soql02 += ' and Status__c != \'草案中\' and Status__c != \'审批中\' ';
|
} else {
|
soql02 += ' and (Status__c = \'计划中\' OR (Status__c in (\'完毕未报告\', \'待提交报告\', \'完毕\') and OPDLendSort__c = null))';
|
}
|
// 20240115 ssm 为处理历史数据方便,增加所有计划外手动重新排队分支 end
|
// soql02 += ' and OPDPlan_ImplementDate__c >=: startDate ' ;
|
soql02 += ' and OPDPlan_ImplementDate__c <=: endDate ';
|
// 2024-02-01 ssm 计划外进入条件调整 start
|
// 考虑创建日和审批日不相同的情况,用审批日更合理一些。对象上增加审批通过日,在批准过程最终批准时增加赋值。
|
soql02 += ' and (CreatedDate >=: penultimateDateTime ';
|
soql02 += ' or ApprovePassed__c >= :penultimateDate) ';
|
// 2024-02-01 ssm 增加非上月残留的条件 end
|
soql02 += ' and AccountType__c = \'医院\' ';
|
// 2024-02-01 ssm 增加非上月残留的条件 start
|
// 重新排序时也增加相应判断
|
soql02 += ' and Last_Month_Untreated__c = false ';
|
// 2024-02-01 ssm 增加非上月残留的条件 end
|
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<OPDPlan__c> tempList01 = Database.query(soql+soql01);
|
List<OPDPlan__c> 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<OPDPlan__c> opdUpdateList = new List<OPDPlan__c>();
|
// 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;
|
|
// 备品可视化 计划外OPD计算OPD排序No处理
|
// 2024-01-24 ssm 增加一个判断,在月末倒数第二个工作日的时候执行上月排序拷贝操作 start
|
// 增加一个代参的构造方法,在备品计划外排序完成后更新OPD上的上月残留标记
|
// Database.executebatch(new RentalAutomaticSortBeforeBatch(), 1);
|
Database.executebatch(new RentalAutomaticSortBeforeBatch(executeCopyToBefore), 1);
|
// 2024-01-24 ssm 增加一个判断,在月末倒数第二个工作日的时候执行上月排序拷贝操作 end
|
}
|
|
// 获取倒数第二个工作日
|
public Date getPenultimateWorkDayOfMonth(Date metaDate) {
|
// 获取待查日期+1月的第一天
|
Date firstDayOfNextMonth = metaDate.addMonths(1).toStartOfMonth();
|
// 此表会维护一个工作日的日历 其中排除掉了周末及节假日 此处通过倒叙排序加limit 2 只拿到倒数第二个工作日
|
List<OlympusCalendar__c> 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;
|
}
|
}
|