public with sharing class MonthEndAutoJudgeNotUpdateBatch implements Database.Batchable, Database.Stateful { public final List TEST_ID = null; private BatchIF_Log__c iflog; // 当前年月 private Integer yearInteger = Date.today().year(); private Integer monInteger = Date.today().month(); public MonthEndAutoJudgeNotUpdateBatch(){} /** * * * @param testId 测试的Id 集合 * @param flag 用于筛选数据的条件 */ public MonthEndAutoJudgeNotUpdateBatch(List testId) { TEST_ID = testId; System.debug('TEST_ID=' + TEST_ID); iflog = new BatchIF_Log__c(); iflog.Type__c = 'MonthEndAutoJudgeNotUpdateBatch'; iflog.Log__c = 'MonthEndAutoJudgeNotUpdateBatch start\n'; iflog.ErrorLog__c = ''; insert iflog; } /** * startには、queryを実行、引合全件 */ public Database.QueryLocator start(Database.BatchableContext BC) { System.debug('start===='); String staSql = 'SELECT id,Name,Owner__c,CreatedDate,Special_Apply_Reason__c,'; staSql += ' Shipping_Scheduled_Date__c,DeliveryDate__c,DeliveryStatus__c,'; staSql += ' PaymentStatus__c,Monthly_forecast_shipping__c,NM_forecast_shipping__c,'; staSql += ' End_User_contract__c,ContractReceivedDate__c FROM Statu_Achievements__c'; staSql += ' where (( OverviewStatus__c <> \'无效合同\' and (OverviewStatus__c <> \'订单完成\' or (SS_backorderID__c <> null and OverviewStatus_SS_IsEqual__c = false))) or Forecast_Equal__c=false) '; // 当前月的第一个工作日 +1便于做判断 Date firstWorkDate = getFirstWorkDayOfMonth().addDays(1); // 当前月的最后五个工作日中最小的那天 Date minOfLastFiveWorkDate = getLastWorkDay(); // 付款状态 List paymentStatus = new List(); paymentStatus.add('尾款完成'); paymentStatus.add('100%预付完成'); paymentStatus.add('不需付款'); paymentStatus.add('尾款支付'); // 排除预测发货日为null的数据 // 第一个工作日记录的预测对象的注残 // 最后五个工作日前,提交用户合同并付全款 staSql += ' AND Shipping_Scheduled_Date__c <> null' + ' AND ContractReceivedDate__c < :minOfLastFiveWorkDate' + ' AND End_User_contract__c = \'已提交\'' + ' AND PaymentStatus__c IN :paymentStatus'; // 如果给定id值,跑指定id的数据 if (TEST_ID != null && TEST_ID.size() > 0) { if (!Test.isRunningTest()) { staSql += ' AND CreatedDate < :firstWorkDate AND id IN :TEST_ID '; } else { staSql += ' AND id IN :TEST_ID'; } // 如果没有给定值,默认跑全部数据,如果在正式环境还需添加创建日期的条件 } else { if (!Test.isRunningTest()) { staSql += ' AND CreatedDate < :firstWorkDate '; } } // System.debug('staSql=' + staSql); return Database.getQueryLocator(staSql); } public void execute(Database.BatchableContext BC, List staList) { // System.debug('stalist=' + staList.size()); // 迭代所有数据 for (Statu_Achievements__c sa : staList) { // 有本月发货预测的标记 if ('本月发货预测'.equals(sa.Monthly_forecast_shipping__c)) { // 本月没有发货 if (!('部分交付'.equals(sa.DeliveryStatus__c)) && !('已完全交付'.equals(sa.DeliveryStatus__c)) && sa.DeliveryDate__c == null) { clearMonthlyForecastShipping(sa); } // 如果发货了 if (sa.DeliveryDate__c != null && !String.isBlank(sa.DeliveryStatus__c) && !('未交付'.equals(sa.DeliveryStatus__c))) { // 但发货日不在本年本月 或者发货日根本不在本年 删除本月预测 if ((sa.DeliveryDate__c.year() == yearInteger && sa.DeliveryDate__c.month() != monInteger) || sa.DeliveryDate__c.year() != yearInteger) { clearMonthlyForecastShipping(sa); } } } // 如果符合本月预测的时间但没有做本月发货预测的标记 if (sa.Shipping_Scheduled_Date__c.year() == yearInteger && sa.Shipping_Scheduled_Date__c.month() == monInteger) { // 如果之前做过次月预测的标记删除 clearNMForecastShipping(sa); // 已发货 if (!String.isBlank(sa.DeliveryStatus__c) && !('未交付'.equals(sa.DeliveryStatus__c))) { // 已发货后说明有发货日期,查看是否本月发货 如果是本月发货添加发货标记 if (sa.DeliveryDate__c.year() == yearInteger && sa.DeliveryDate__c.month() == monInteger) { // 添加本月发货预测 if (String.isBlank(sa.Monthly_forecast_shipping__c)){ sa.Monthly_forecast_shipping__c = '本月发货预测'; // System.debug('添加本月'); iflog.Log__c += 'Name: '+sa.Name+' 添加本月发货预测\n'; sa.Special_Apply_Reason__c += ' 系统自动,添加本月发货预测'; } } } } // 有次月发货预测标记 或者时间是次月预测 if ('次月发货预测'.equals(sa.NM_forecast_shipping__c) || isNMForecastShipping(sa)) { // 并且在本月完成全部发货 if ('已完全交付'.equals(sa.DeliveryStatus__c) && sa.DeliveryDate__c.year() == yearInteger && sa.DeliveryDate__c.month() == monInteger) { clearMonthlyForecastShipping(sa); clearNMForecastShipping(sa); } // 如果发货了 if (sa.DeliveryDate__c != null && !String.isBlank(sa.DeliveryStatus__c) && !('未交付'.equals(sa.DeliveryStatus__c))) { // 但发货日不在本年本月 或者发货日根本不在本年 删除次月预测 if ((sa.DeliveryDate__c.year() == yearInteger && sa.DeliveryDate__c.month() != monInteger) || sa.DeliveryDate__c.year() != yearInteger) { clearNMForecastShipping(sa); } } } // 当月没有完成全部发货 if (!('已完全交付'.equals(sa.DeliveryStatus__c))) { // 如果月份是12月 // 次月为 下一年的一月份 // 如果没有次月发货预测的标记 判断是否符合条件 if (isNMForecastShipping(sa)) { // 添加次月时无论如何删除掉本月 clearMonthlyForecastShipping(sa); if (String.isBlank(sa.NM_forecast_shipping__c)) { sa.NM_forecast_shipping__c = '次月发货预测'; // System.debug('添加次月'); iflog.Log__c += 'Name: '+sa.Name+' 添加次月发货预测\n'; sa.Special_Apply_Reason__c += ' 系统自动,添加次月发货预测'; } // 如果不是次月预测 但有标记 删除该标记 } else { clearNMForecastShipping(sa); } } } // 不会做修改 // Database.update(staList); } public void finish(Database.BatchableContext BC) { iflog.Log__c += 'MonthEndAutoJudgeNotUpdateBatch 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; } /** * 删除本月发货预测 * @param sa */ public void clearMonthlyForecastShipping(Statu_Achievements__c sa) { if (!String.isBlank(sa.Monthly_forecast_shipping__c)) { sa.Monthly_forecast_shipping__c = null; // System.debug('删除 本月'); iflog.Log__c += 'Name: '+sa.Name+' 删除本月发货预测\n'; sa.Special_Apply_Reason__c += ' 系统自动,删除本月发货预测'; } } /** * 删除次月发货预测 * * @param sa */ public void clearNMForecastShipping(Statu_Achievements__c sa) { if (!String.isBlank(sa.NM_forecast_shipping__c)) { sa.NM_forecast_shipping__c = null; System.debug('删除 次月'); iflog.Log__c += 'Name: '+sa.Name+' 删除次月发货预测\n'; sa.Special_Apply_Reason__c += ' 系统自动,删除次月发货预测'; } } /** * 判断是否是 次月预测 * * @param sa * * @return */ public boolean isNMForecastShipping(Statu_Achievements__c sa) { return (sa.Shipping_Scheduled_Date__c.year() == yearInteger && sa.Shipping_Scheduled_Date__c.month() == monInteger + 1) || (sa.Shipping_Scheduled_Date__c.year() == yearInteger + 1 && sa.Shipping_Scheduled_Date__c.month() == 1 && monInteger == 12); } /** * 获取当前月份的第一个工作日 * * @return */ public Date getFirstWorkDayOfMonth() { // 获取当前月份的第一天 Date firstDayOfMonth = Date.today().toStartOfMonth(); // 将月份推到下一个月 Date nextMonth = Date.newInstance(firstDayOfMonth.year(), firstDayOfMonth.month() + 1, 1); // 获取当前月份最后一天 // System.debug('lastDay:' + nextMonth.addDays(-1)); Date lastDayOfMonth = nextMonth.addDays(-1); // 此表会维护一个工作日的日历 其中排除掉了周末及节假日 此处通过排序加limit 1 只拿到第一个工作日 List olympusCalendarDate = [ Select Date__c From OlympusCalendar__c Where Date__c >= :firstDayOfMonth And Date__c <= :lastDayOfMonth And IsWorkDay__c = 1 ORDER BY Date__c LIMIT 1 ]; Date firstWorkDayOfMonth = null; if (olympusCalendarDate.size() > 0) { firstWorkDayOfMonth = olympusCalendarDate.get(0).Date__c; } // System.debug('firstWorkDayOfMonth' + firstWorkDayOfMonth); return firstWorkDayOfMonth; } /** * 获取最后五个工作日中的最小的那天 * * @return */ public Date getLastWorkDay() { // 获取当前月份的第一天 Date firstDayOfMonth = Date.today().toStartOfMonth(); // 将月份推到下一个月 Date nextMonth = Date.newInstance(firstDayOfMonth.year(), firstDayOfMonth.month() + 1, 1); // 获取当前月份最后一天 // System.debug('lastDay:' + nextMonth.addDays(-1)); Date lastDayOfMonth = nextMonth.addDays(-1); // 此表会维护一个工作日的日历 其中排除掉了周末及节假日 此处通过排序加limit 5 拿到最后五个工作日 List olympusCalendarDates = [ Select Date__c From OlympusCalendar__c Where Date__c >= :firstDayOfMonth And Date__c <= :lastDayOfMonth And IsWorkDay__c = 1 ORDER BY Date__c DESC LIMIT 5 ]; // System.debug('List :' + olympusCalendarDates); Date result; if (olympusCalendarDates.size() > 0) { result = olympusCalendarDates.get(olympusCalendarDates.size() - 1).Date__c; // System.debug('result' + result); } return result; } }