/**
|
* 每月销量Batch的副本,用于临时处理指定月的月销量
|
* Author:shashiming
|
* Date:2023-04-03
|
*/
|
|
global without sharing class ProductMonthlySalesCountCopyBatch implements Database.Batchable<sObject>, Database.Stateful {
|
//统计产品月销量 精琢技术 tcm 2021-10-11 start
|
|
/* tcm
|
//by_tcm 测试代码 start
|
//如编码错误请删除前面的空格
|
①生成所有12月月销量的数据(前提是产品的生成12月月销量标识得为true,默认204传输过来的时候为true):
|
Database.executeBatch(new ProductMonthlySalesCountCopyBatch(true));
|
②生成所有当前月月销量的1条数据
|
Database.executeBatch(new ProductMonthlySalesCountCopyBatch());
|
③生成指定很多产品的12月月销量的数据
|
List<String> idList = new List<String>();
|
//添加指定的产品的id
|
idList.add('');//eg:dList.add('01t10000002P5yiAAC');
|
Database.executeBatch(new ProductMonthlySalesCountCopyBatch(idList), 20);
|
④生成指定某个产品的12月月销量的数据
|
//下面的'' 引号里面放入指定的产品id
|
Database.executeBatch(new ProductMonthlySalesCountCopyBatch(''), 20); //eg:Database.executeBatch(new ProductMonthlySalesCountCopyBatch('01t10000002P5yiAAC'), 20);
|
⑤生成指定很多产品的当前月月销量的数据
|
List<String> idList = new List<String>();
|
//添加指定的产品的id
|
idList.add('');//eg:dList.add('01t10000002P5yiAAC');
|
Database.executeBatch(new ProductMonthlySalesCountCopyBatch(idList,true), 20);
|
⑥生成指定某个产品的当前月月销量的数据
|
//下面的'' 引号里面放入指定的产品id
|
Database.executeBatch(new ProductMonthlySalesCountCopyBatch('',true), 20); //eg:Database.executeBatch(new ProductMonthlySalesCountCopyBatch('01t10000002P5yiAAC',true), 20);
|
|
//sql验证生成结果
|
select id, ProductM__c, Product2Model__c, CurrentDate__c, MonthSales__c,Earliest_Shipping__c,GenerationMonths__c from ProductMonthlySales__c order by Product2Model__c, CurrentDate__c
|
// by_tcm 测试代码 end
|
*/
|
|
//错误邮件 start
|
|
// 报错的询价ID
|
public String logstr = '';
|
// 报错信息
|
public String errorstr = '';
|
// 总件数
|
public Integer totalCount = 0;
|
// 失败件数
|
public Integer failedCount = 0;
|
|
// 生成月销量起始时间
|
public Date productDate = Date.valueOf(Label.Product_Date);
|
|
// 邮件信息
|
public List<String> emailMessages = new List<String>();
|
|
//错误邮件 end
|
|
//状态 存放应执行的方法
|
Integer status=0;
|
//存放方法传进来的产品ID
|
List<String> proList = new List<String>();
|
|
// 统计日期
|
public Date staticDate = Date.today();
|
|
//生成所有产品本月的月销量 status=0
|
global ProductMonthlySalesCountCopyBatch(){
|
}
|
|
// 生成所有产品指定月的月销量 status=0 staticStart 指定月的最后一天
|
global ProductMonthlySalesCountCopyBatch(Date staticStart){
|
this.staticDate = staticStart;
|
}
|
|
//生成所有产品12个月的月销量 status=3
|
global ProductMonthlySalesCountCopyBatch(Boolean all){
|
this.status=3;
|
}
|
|
//指定List<产品>生成12个月以内的月销量(上月月底 往前推12个月) status=1
|
global ProductMonthlySalesCountCopyBatch(List<String> pro2List){
|
this.proList.addAll(pro2List);
|
this.status=1;
|
}
|
//指定单个产品ID 生成12个月以内的月销量(上月月底 往前推12个月) status=1
|
global ProductMonthlySalesCountCopyBatch(String pro2Id){
|
this.proList.add(pro2Id);
|
this.status=1;
|
}
|
|
// 生成List<> Id 本月的月销量 status=2
|
global ProductMonthlySalesCountCopyBatch(List<String> pro2List,Boolean oneMonth){
|
this.proList.addAll(pro2List);
|
this.status=2;
|
}
|
// 生成单个Id 本月的月销量 status=2
|
global ProductMonthlySalesCountCopyBatch(String pro2Id,Boolean oneMonth){
|
this.proList.add(pro2Id);
|
this.status=2;
|
}
|
|
global Database.QueryLocator start(Database.BatchableContext bc){
|
// by_tcm 查产品 没有停产的 && 预计停止日期 != null
|
String sql='select id,ProductCode,Correspond_Code__c,Correspond_ProductCode__c,M_BC_Stop_manufacure__c,ProductMonthlySalesFlag__c from Product2 where M_BC_Stop_manufacure__c !=null and SFDA_Status__c!=\'停止\'';
|
// 如果执行的方法是指定Id的
|
if (status==1||status==2) {
|
sql+=' and id in :proList ';
|
}
|
// 如果执行的方法是生成12个月的
|
if (status==3||status==1) {
|
sql+=' and ProductMonthlySalesFlag__c = true';
|
}
|
return Database.getQueryLocator(sql);
|
}
|
|
global void execute(Database.BatchableContext BC, List<Product2> rowDataList) {
|
//产品去重-----------------start
|
// 新旧产品ID存入Map<> allproMap start
|
Map<String,Product2> oldproMap=new Map<String,Product2>();
|
Map<String,Product2> newproMap=new Map<String,Product2>();
|
Map<String,Product2> allproMap=new Map<String,Product2>();
|
|
// 筛选旧产品
|
for(Product2 product : rowDataList) {
|
oldproMap.put(product.id,product);
|
}
|
|
// 筛选新产品
|
for(Product2 product : rowDataList) {
|
// 如果对应的新code不等于空
|
if(product.Correspond_Code__c!=null) {
|
// 如果旧产品Map 不包含 对应的新code ,则存入新产品Map
|
if(!oldproMap.containsKey(product.Correspond_Code__c)) {
|
newproMap.put(product.Correspond_Code__c,product);
|
}
|
}
|
}
|
// 合并数据
|
allproMap.putAll(oldproMap);
|
allproMap.putAll(newproMap);
|
// 新旧产品ID存入Map<...> allproMap end
|
|
// 新旧产品ID存入List<> strprodids start
|
List<Product2> rowListold = new List<Product2>();
|
List<Product2> rowListnew = new List<Product2>();
|
List<String> strprodids = new List<String>();
|
// List<旧产品>
|
for(Product2 product : oldproMap.values()) {
|
rowListold.add(product);
|
strprodids.add(product.Id);
|
}
|
// List<新产品>
|
for(Product2 product : newproMap.values()) {
|
rowListnew.add(product);
|
strprodids.add(product.Correspond_Code__c);
|
}
|
// 新旧产品ID存入strprodids end
|
//产品去重--------------end
|
|
//查询保有设备--------------start
|
// by_tcm 通过上边没停产 去重后 的List<ID> strprodids 查询保有设备 &&发货日期 != null
|
List<Asset> AssetList =[select Id,Product2Id,Posting_Date__c,RecordType.DeveloperName from Asset where Product2Id IN :strprodids and Posting_Date__c!=null and RecordType.DeveloperName !='Shipment' and Posting_Date__c>=:productDate order by Posting_Date__c desc];
|
// 设置要生成的月份数 (循环保有设备查找产品最早发货日) start
|
Map<String,Integer> cntMonthMap=new Map<String,Integer>();
|
for (Asset ass : AssetList) {
|
Product2 pdt=allproMap.get(ass.Product2Id);
|
Date endDate = this.staticDate;
|
Date startDate=ass.Posting_Date__c;
|
Integer countMonths= startDate.monthsBetween(endDate);
|
//如果执行的方法是生成1个月的,应生成月=1
|
if (this.status==0||this.status==2) {
|
countMonths=1;
|
}
|
// 如果月份大于12,设置12
|
else if(countMonths>12) {
|
countMonths=12;
|
}
|
cntMonthMap.put(ass.Product2Id,countMonths);
|
}
|
// 设置要生成的月份数 (循环保有设备查找产品最早发货日) end
|
//查询保有设备--------------end
|
|
// by_tcm 查询月销量 where id in strprodids ProductMonthlySalescMap 月销量
|
List<ProductMonthlySales__c> ProductMonthlySalescList =[select id,Name__c, MonthSales__c, CurrentMonth__c, CurrentDate__c, CurrentYear__c, ProductM__c, Product2Model__c,Name,Earliest_Shipping__c,GenerationMonths__c from ProductMonthlySales__c where ProductM__r.id in :strprodids];
|
|
List<ProductMonthlySales__c> productmonthold = new List<ProductMonthlySales__c>();
|
List<ProductMonthlySales__c> productmonthnew = new List<ProductMonthlySales__c>();
|
//如果旧产品不为空,调用方法
|
if(rowListold!=null) {
|
productmonthold = createMonthlySales(rowListold,AssetList,0,cntMonthMap,this.status,ProductMonthlySalescList,this.staticDate);
|
}
|
//如果新产品不为空,调用方法
|
if(rowListnew!=null) {
|
productmonthnew= createMonthlySales(rowListnew,AssetList,1,cntMonthMap,this.status,ProductMonthlySalescList,this.staticDate);
|
}
|
// 合并
|
productmonthold.addAll(productmonthnew);
|
|
//select产品月销量去重------start
|
Map<String,ProductMonthlySales__c> ProductMonthlySalescMap = new Map<String,ProductMonthlySales__c>();
|
for(ProductMonthlySales__c pms :ProductMonthlySalescList) {
|
ProductMonthlySalescMap.put(pms.Name,pms);
|
}
|
//select产品月销量去重------end
|
|
//新产品月销量去重-------start
|
for(ProductMonthlySales__c prdm : productmonthold) {
|
ProductMonthlySalescMap.put(prdm.Name,prdm);
|
// ProductMonthlySalescMap.put('ahaha',prdm);
|
}
|
|
//新产品月销量去重-------end
|
|
List<ProductMonthlySales__c> newProductMonthlySalescList=new List<ProductMonthlySales__c>();
|
// //去重后转List start
|
// for (ProductMonthlySales__c prdm : ProductMonthlySalescMap.values()) {
|
// newProductMonthlySalescList.add(prdm);
|
// newProductMonthlySalescList.add(prdm);
|
// }
|
// //去重后转List start
|
Map<String,String> keyProId=new Map<String,String>();
|
if(productmonthold!=null) {
|
Database.UpsertResult[] results = Database.upsert(ProductMonthlySalescMap.values(),ProductMonthlySales__c.Name__c,false);
|
totalCount=results.size();
|
for(Integer i = 0; i < totalCount; i++) {
|
if(!results[i].isSuccess()) {
|
for (Database.Error err : results[i].getErrors()) {
|
String message = '产品月销量 : 产品ID为: '+ ProductMonthlySalescMap.values()[i].ProductM__c + ' ; ' + err.getStatusCode() + '; '+ err.getFields() + ' ; '+ err.getMessage();
|
failedCount++;
|
keyProId.put(ProductMonthlySalescMap.values()[i].ProductM__c,message);
|
}
|
}
|
}
|
String cacheText='';
|
for (String errorst: keyProId.values()) {
|
cacheText+=errorst+'\n';
|
}
|
errorstr=cacheText;
|
}
|
// 把 生成12月销量标识 设置为false start
|
// 数据去重
|
Map<String,Asset> pro2Map =new Map<String,Asset>();
|
for (Asset aset : AssetList) {
|
pro2Map.put(aset.Product2Id,aset);
|
}
|
// 批量修改数据
|
List<Product2> updatePmsfcss =new List<Product2>();
|
for (Asset updatePmsfcs : pro2Map.values()) {
|
Product2 pro2=new Product2();
|
pro2.Id=updatePmsfcs.Product2Id;
|
pro2.CalMonthSalesFLG__c=true;
|
if (this.status==3||this.status==1) {
|
pro2.ProductMonthlySalesFlag__c=false;
|
}
|
updatePmsfcss.add(pro2);
|
}
|
update updatePmsfcss;
|
// 把 生成12月销量标识、 设置为false end
|
}
|
|
private static List<ProductMonthlySales__c> createMonthlySales(List<Product2> rowList,List<Asset> AssetList,Integer flag,Map<String,Integer> countMonthsMap,Integer status,List<ProductMonthlySales__c> ProductMonthlySalescList, Date staticStartDate) {
|
|
List<ProductMonthlySales__c> productmonth = new List<ProductMonthlySales__c>();
|
// 循环产品
|
for(Product2 product : rowList) {
|
//生成当月时,应生成月数量是否有变化,如有,更新产品12个月的应生成月数量数据 Map<Id,状态>
|
Map<String,Integer> countStatus = new Map<String,Integer>();
|
//同上,储存应生成月数量 Map<Id,数量>
|
Map<String,Integer> countMonthss=new Map<String,Integer>();
|
//应生成月
|
Integer countMonths=12;
|
//发货日期
|
Date postDate = staticStartDate;
|
|
// 给ID code 赋值 start
|
String Id;
|
String Code;
|
if(flag==0) {
|
//产品ID
|
Id=product.Id;
|
//产品代码
|
Code=product.ProductCode;
|
}else if(flag==1) {
|
//对应的新CODE
|
Id=product.Correspond_Code__c;
|
//对应的新CODE的产品代码
|
Code=product.Correspond_ProductCode__c;
|
}
|
// 给ID code 赋值 end
|
//存无数据的(0) Map<year_month,数量>
|
Map<String,Integer> AssetcountMap = new Map<String,Integer>();
|
//存无数据的(0) Map<year_month,数量>
|
Map<String,Integer> AstcountMap = new Map<String,Integer>();
|
//临时存日期用
|
Date starDate;
|
|
if(countMonthsMap.containsKey(Id)) {
|
//应生成月
|
Integer cntMonths =-countMonthsMap.get(Id);
|
// by_tcm 预计结束日期/现在日期
|
Date dates = staticStartDate;
|
//如果预计结束日<今天 减掉相差的月数 => 数据0的生成量
|
if (product.M_BC_Stop_manufacure__c<dates) {
|
dates=product.M_BC_Stop_manufacure__c;
|
cntMonths -= staticStartDate.monthsBetween(dates);
|
}
|
// by_tcm 预计开始日期
|
Date datefirst=dates.addMonths(cntMonths);
|
// by_tcm 开始年
|
Integer yearfirst=datefirst.year();
|
// by_tcm 开始月
|
Integer monthfirst=datefirst.month();
|
// by_tcm 停止年
|
Integer yearlast=dates.year();
|
// by_tcm 停止月
|
Integer monthlast=dates.month();
|
// by_tcm 拼接结束日期
|
Date lastdate = Date.newInstance(yearlast,monthlast,0);
|
// by_tcm 拼接开始日期
|
Date firstdate = Date.newInstance(yearfirst,monthfirst,1);
|
//如果生成一个月数据,生成当月数据(非上月)
|
if (status==0||status==2) {
|
// 开始日/结束日
|
lastdate=lastdate.addMonths(1);
|
firstdate=firstdate.addMonths(1);
|
}
|
// by_tcm 添加初始销量数据为0 start
|
for (Integer i = 0; i < -cntMonths; i++) {
|
starDate=firstdate.addMonths(i);
|
if(starDate<lastdate) {
|
Integer month=starDate.month();
|
Integer year=starDate.year();
|
String year_month=year+'_'+month;
|
AstcountMap.put(year_month, 0);
|
}
|
}
|
// by_tcm 添加初始销量数据为0 end
|
|
// by_tcm 添加有销量的数据 start
|
for(Asset ass : AssetList) {
|
// by_tcm AssetList = 所有保有设备ID
|
if (Id==ass.Product2Id) {
|
// by_tcm 在日期区间内 拼接发货日期 year_month start
|
system.debug('firstdate等于'+firstdate);
|
system.debug('lastdate等于'+lastdate);
|
if(firstdate<ass.Posting_Date__c&&ass.Posting_Date__c<lastdate) {
|
Integer month=ass.Posting_Date__c.month();
|
Integer year=ass.Posting_Date__c.year();
|
String year_month=year+'_'+month;
|
|
Integer i = 1;
|
// 如果日期存在,数量+1
|
if(AssetcountMap.containsKey(year_month)) {
|
i = AssetcountMap.get(year_month);
|
i++;
|
AssetcountMap.put(year_month,i);
|
}else{
|
AssetcountMap.put(year_month,i);
|
}
|
}
|
// by_tcm 在日期区间内 拼接发货日期 year_month end
|
|
//取最早发货日和应生成月 start
|
if (ass.Posting_Date__c<lastdate) {
|
//最早发货日
|
if(postDate>ass.Posting_Date__c /*&&ass.Posting_Date__c.year()!=1900*/) {
|
postDate=ass.Posting_Date__c;
|
}
|
|
//取应生成月 start
|
if (status==0||status==2) {
|
//应生成月
|
countMonths=ass.Posting_Date__c.monthsBetween(lastdate);
|
//如果应生成月<12,应生成月+1
|
if (countMonths < 12) {
|
countMonths++;
|
}else {
|
countMonths=12;
|
}
|
countStatus.put(Id, 1);
|
countMonthss.put(Id, countMonths);
|
}else {
|
//应生成月
|
countMonths=ass.Posting_Date__c.monthsBetween(dates);
|
if (countMonths > 12) {
|
countMonths=12;
|
}
|
}
|
//取应生成月 end
|
}
|
//取最早发货日和应生成月 start
|
}
|
}
|
// by_tcm 添加有销量的数据 end
|
|
//合并数据 start
|
AstcountMap.putAll(AssetcountMap);
|
AssetcountMap=AstcountMap;
|
//合并数据 end
|
}
|
|
for (String key : AssetcountMap.keySet()) {
|
// 年
|
Integer yearss;
|
// 月
|
Integer monthss;
|
String month='';
|
if (key!=null) {
|
//拆分year_month中的年_月
|
List<String> year_month=key.split('_');
|
yearss = Integer.valueOf(year_month[0]);
|
monthss = Integer.valueOf(year_month[1]);
|
}
|
ProductMonthlySales__c pmsc=new ProductMonthlySales__c();
|
//如果是新产品Id,不储存新产品ID的应生成月
|
if (flag==0) {
|
//应生成月
|
pmsc.GenerationMonths__c=countMonths;
|
}
|
// 月
|
month=String.valueOf(monthss);
|
if(monthss<10) {
|
month='0'+monthss;
|
}
|
// 发货日期
|
pmsc.Earliest_Shipping__c=postDate;
|
// 月销售量
|
pmsc.MonthSales__c = AssetcountMap.get(key);
|
// 当前日期
|
pmsc.CurrentDate__c = Date.newInstance(yearss,monthss,1);
|
// 产品Id
|
pmsc.ProductM__c = Id;
|
// 产品型号
|
pmsc.Product2Model__c = Code;
|
// 产品月销量名称
|
pmsc.Name = Code+':'+yearss+month;
|
//作为name唯一Key
|
pmsc.Name__c=pmsc.Name;
|
productmonth.add(pmsc);
|
}
|
// //数据(应生成月)发生变化,更新数据
|
// if (countStatus.containsKey(Id)&&countStatus.get(Id)==1) {
|
// if (flag==0) {
|
// for (ProductMonthlySales__c pdmsList : ProductMonthlySalescList) {
|
// if(pdmsList.ProductM__c==Id) {
|
// pdmsList.GenerationMonths__c=countMonthss.get(Id);
|
// }
|
// }
|
// }
|
// }
|
}
|
// by_tcm 返回产品月销量数据 List<ProductMonthlySales__c> productmonth
|
return productmonth;
|
}
|
global void finish(Database.BatchableContext BC){
|
BatchIF_Log__c batchIfLog = new BatchIF_Log__c();
|
batchIfLog.Type__c = 'ProductMonthlySalesCountCopyBatch';
|
if (logstr.length() > 60000) {
|
logstr = logstr.substring(0, 60000);
|
}
|
batchIfLog.Log__c = logstr;
|
logstr += '\nBatchProductMonthlySalesCountEnd';
|
if (errorstr.length() > 60000) {
|
batchIfLog.ErrorLog__c = errorstr.substring(0, 60000);
|
} else {
|
batchIfLog.ErrorLog__c = errorstr.substring(0, errorstr.length());
|
}
|
insert batchIfLog;
|
emailMessages.add('失败日志ID为:' + batchIfLog.Id);
|
sendFieldEmail();
|
}
|
// 发送提醒邮件
|
private void sendFieldEmail() {
|
system.debug('进入sendFieldEmail');
|
PretechBatchEmailUtil be = new PretechBatchEmailUtil();
|
String[] toList = new String[] {UserInfo.getUserEmail()};
|
// String[] toList = new String[] {'tangchengming@prec-tech.com' /*,'wangqingli@prec-tech.com'*/};
|
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,'',false);
|
if(!Test.isRunningTest())
|
be.send();
|
}
|
}
|
}
|
//统计产品月销量 精琢技术 tcm 2021-10-11 end
|