高章伟
2022-02-18 8b5f4c6c281cfa548f92de52c8021e37aa81901e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
global class CreatePassiveTaskBatch1 implements Database.Batchable<sObject>, Database.Stateful  {
    // 报错的询价ID
    public String logstr = '';
    // 报错信息
    public String errorstr = '';
    public List<String> emailMessages = new List<String>();
    public Integer AllCount = 0; // 总件数
    public Integer failedCount = 0; // 失败件数
    Integer FIELDMAX = 30;
    Boolean isAutoexec = false; //20210203 zh SWAG-BXQDHZ 是否自动执行
    String HPId;
    String dePart;
    //针对于单独某个医院
    global CreatePassiveTaskBatch1(String AccountId) {
        HPId = AccountId;
        isAutoexec = false;
    }
    //针对于单独某个战略科室
    global CreatePassiveTaskBatch1(String AccountId, boolean a) {
        dePart = AccountId;
        isAutoexec = false;
    }
    global CreatePassiveTaskBatch1() {
    }
    global CreatePassiveTaskBatch1(boolean temp) {
        isAutoexec = temp;
    }
    // opd计划月api与opd计划数的名字
    SS_Batch_Column_Mapping__c PlanMonthAndAmountName = SS_Batch_Column_Mapping__c.getValues('PlanMonthAndAmountName');
    Map<String , List<String>> PlanMonthAndAmountNameMap = new Map<String , List<String>>();
    // opd计划月api与opd计划数的api
    SS_Batch_Column_Mapping__c PlanMonthAndAmount = SS_Batch_Column_Mapping__c.getValues('PlanMonthAndAmount');
    Map<String , String> PlanMonthAndAmountMap = new Map<String , String>();
 
    global Database.QueryLocator start(Database.BatchableContext BC) {
        // 规定年份格式(今年四月份到下一年4月份为一年)(如:今年-1867+p 135p)
        // 这个月
        Date TodayMonth = Date.Today();
        // 下个月
        Date NextMonth = TodayMonth.addMonths(1);
        // 将其转换为integer类型
        Integer year = NextMonth.year();
        Integer month = NextMonth.month();
        // 今年四月份到下一年4月份为一年
        if (month < 4) {
            year = year - 1;
        }
        // 今年-1867+p 135p
        String ShangYear = year - 1867 + 'P';
 
        // 获取自定义设置opd计划月api与opd计划数的名字
        // 循环获取
        for (Integer i = 0; i <= FIELDMAX; i++ ) {
            // 拼字段
            String spil = ('00' + 'i').right(3);
            // 获取opd计划月api
            String planMonthApi = String.valueOf(PlanMonthAndAmountName.get('From_Column_' + spil + '__c')) ;
            // 获取opd计划数的名字
            String planNumberName = String.valueOf(PlanMonthAndAmountName.get('SS_Column_' + spil + '__c'));
            // 判断以上不为空
            if (String.isNotBlank(planMonthApi) && String.isNotBlank(planNumberName)) {
                // 计划数的值(名字)将其用逗号做分割符,存在
                List<String> PlanNumberNameList = planNumberName.split(',');
                // 将opd计划月api作为key,opd计划数的名字作为value,存入Map中
                PlanMonthAndAmountNameMap.put(planMonthApi, PlanNumberNameList);
            }
        }
        // 获取自定义设置opd计划月api与opd计划数的api
        for (Integer i = 0; i <= FIELDMAX ; i++) {
            String spil = ('00' + 'i').right(3);
            // 获取opd计划月api
            String planMonthApi = String.valueOf(PlanMonthAndAmountName.get('From_Column_' + spil + '__c')) ;
            // 获取opd计划数的Api
            String planNumberApi = String.valueOf(PlanMonthAndAmountName.get('SS_Column_' + spil + '__c'));
            if (String.isNotBlank(planMonthApi) && String.isNotBlank(planNumberApi)) {
                // 将opd计划月api作为key,opd计划数的api作为value,存入Map中
                PlanMonthAndAmountMap.put(planMonthApi, planNumberApi);
            }
        }
        String planMonth;
        String planNumberName;
        String planMonthStr;
        // 遍历计划月api,用来获取opd计划月和opd计划数及计划月不为空的条件(拼接opd计划月api)
        for (String apiStr : PlanMonthAndAmountNameMap.keySet()) {
            // 拼opd计划月api
            planMonth = ',' + apiStr;
            // 拼opd计划数名字
            planNumberName = ',' + PlanMonthAndAmountNameMap.get(apiStr);
            // 不为空计划月不为空的拼接
            planMonthStr = apiStr + '!=null or ';
        }
        // 计划月不为空的条件
        String planMonthNu = planMonthStr.substring(0, planMonthStr.length() - 3);
        // 检索今年全部的目标客户
        // 检索 计划月不为空,OCSM期 = 规定年份 的目标客户
        String Acc = 'select Id ,name,account__c,account__r.OwnerId,account__r.Name,account__r.ParentId';
        Acc += planMonth;
        Acc += planNumberName;
        Acc += 'From Account_Number_of_target__c where OCM_Period__c = : ThisPeriod and';
        Acc += '(';
        Acc += 'planMonthNu';
        Acc += ')';
        // 针对于单独某个医院(目标客户的母公司 = 医院)
        if (String.isNotBlank(HPId)) {
            Acc += 'and account__r.ParentId =: HPId';
        }
        // 针对于单独某个战略科室(战略科室=战略科室)
        if (String.isNotBlank(dePart)) {
            Acc += ' and account__c = : dePart';
        }
        // 额外判断,如果不是非要执行,那么如果战略科室所在医院是无效医院,那么就不针对这家战略科室下达任务
        if (String.isBlank(dePart) && String.isBlank(HPId)) {
            Acc += 'and account__r.Parent.Is_Active__c = \'有効\'  ';
        }
        // 除15号(从自定义标签中获取)外 并且 不自动执行时 检索到的目标客户为空
        Integer runday = Integer.valueOf(Label.OPD_RunTime);
        if (Date.today().day() != runday && isAutoexec == true) {
            Acc = 'select Id From Account_Number_of_target__c where Name=\'\' and Name!=\'\'';
        }
        // 初始化,得到想要处理的数据(目标客户)
        return DataBase.getQueryLocator(Acc);
    }
 
    global void execute(Database.BatchableContext BC, List<Account_Number_of_target__c> AccList) {
        // opd计划月api与对应的产品名
        //任务List
        List<task__c> taskList =  new List<task__c>();
        SS_Batch_Column_Mapping__c OPDPlanMonth = SS_Batch_Column_Mapping__c.getValues('OPD_PlanMonth');
        Map<String , String> OPDPlanMonthMap = new Map<String , String>();
        //获取自定义设置opd计划月api与对应的产品名,将其存入Map中
        for (Integer i = 0 ; i <= FIELDMAX ; i++) {
            String spil = ('00' + 'i').right(3);
            String planMonth = String.valueOf(OPDPlanMonth.get('From_Column_' + spil + '__c'));
            String chanPin = String.valueOf(OPDPlanMonth.get('SS_Column_' + spil + '__c'));
            if (String.isNotBlank(planMonth) && String.isNotBlank(chanPin)) {
                OPDPlanMonthMap.put(planMonth, chanPin);
            }
        }
        // 遍历目标客户   将战略科室转换成字符串(取其前15),存入List中
        List<String> anotAccList = new List<String>();
        for (Account_Number_of_target__c anot : AccList) {
            anotAccList.add(String.valueOf(anot.Account__c).substring(0, 15));
        }
        // 定义Fy开始日和结束日(作为检索opd计划的条件)
        Integer monthday = date.today().month();
        Integer yearday = date.today().year();
        if (monthday < 3) {
            yearday--;
        }
        Date Fyfirstday = date.newInstance(yearday, 4, 1);
        Date FyEndday = Fyfirstday.addMonths(12);
        // 状态为计划中或完毕未报告 并且 OPD计划实施日期大于等于Fy开始日 并且 小于 结束日 并且 每个战略科室对应的opd计划(opd计划所关联的战略科室被包含在所有战略科室中)
        List<OPDPlan__c> OPDPlanList = [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:anotAccList
                                        and OPDPlan_ImplementDate__c >= : FYfirstDay
                                        and OPDPlan_ImplementDate__c < : FyEndday
                                        and (Status__c = '计划中'  or Status__c = '完毕未报告')];
        //3.战略客户下全部的Opd计划
        Map<String, List<OPDPlan__c>> OpdMap = new Map<String, List<OPDPlan__c>>();
        // 1、创建一个存opd计划Id的list
        List<String> opdPlanIdList = new List<String>();
        // 2、遍历存战略科室Id的list
        for (String anotAcc : anotAccList) {
            // 3、遍历检索出来的opd计划
            for (OPDPlan__c opdId : OPDPlanList) {
                // 4、将 战略科室(key)检索出来的opd计划 (value)
                OpdMap.put(anotAcc, OPDPlanList);
                // 5、将 opd计划存入list(String)
                opdPlanIdList.add(opdId.Id);
            }
 
        }
        String producDetail;
        // 遍历目标客户
        for (Account_Number_of_target__c anot : AccList) {
            //遍历opd计划月Api,opd计划月Api(key) 产品名(value)
            for (String monthapikey : OPDPlanMonthMap.keySet()) {
                //在这里写对应的opd数是否为空
                Boolean anotFlage = true;
                boolean FlagBl = true;
                //获取客户opd月值,如果客户opd计划月值为空的话,跳出循环
                if (anot.get(monthapikey) == null) {
                    continue;
                }
                //opd计划月的值(将其转换成String类型)
                String monthValue = String.valueOf(anot.get(monthapikey));
                // 如果 opd计划月的值 不等于空 将 opd计划月的值赋值给(Integer类型的变量)
                Integer monthValueIn;
                if (String.isNotBlank(monthValue)) {
                    monthValueIn = Integer.valueOf(monthValue.substring(0, monthValue.length() - 1));
                }
                // 如果 opd计划月的值为空 或 opd计划月大于下个月(当前月的值+1)
                if (monthValueIn < 4) {
                    monthValueIn += 12;
                }
                Integer NextMonthIn  = date.today().month() - 1;
                if (NextMonthIn < 4) {
                    NextMonthIn += 12;
                }
                if (String.isBlank(monthValue) || monthValueIn > NextMonthIn) {
                    // 则跳出循环
                    continue;
                    // 如果以上条件不满足:
                } else {
                    // 获取opd计划数api,将其以‘,’为分隔符存入list中
                    String opdPlanNumber = PlanMonthAndAmountMap.get(monthapikey);
                    List<String> planNumberValue = opdPlanNumber.split(',');
                    // 遍历 opd计划数api
                    for (String planNumberApi : planNumberValue) {
                        FlagBl = true;
                        // 1、判断对应的opd数是否为空 如果
                        // 1、不为空
                        if (String.isNotBlank(String.valueOf(anot.get(planNumberApi)))) {
                            // 1、boolean变量为false
                            anotFlage = false;
                            //2、为空
                        } else {
                            // 1、获取 opd计划存在List中 (如果没有,则新创一个opd)
                            List<OPDPlan__c> OpPlanList = OpdMap.get(String.valueOf(anot.Account__c).substring(0, 15));
                            if (OpPlanList.size() < 0) {
                                OpPlanList = new List<OPDPlan__c>();
                            }
                            // 2、循环比对已存在的计划出借备品信息和理论上存在的计划出借备品信息
                            for (OPDPlan__c bp : OpPlanList) {
                                // 1、如果 有计划出借备品信息 则 将计划出借备品信息以‘;’为分隔符存入list(String)中
                                if (String.isNotBlank(bp.PlanProdDetail__c)) {
                                    List<String> bpList = bp.PlanProdDetail__c.split(';');
                                    // 1、遍历计划出借备品信息
                                    for (String OPDbp : bpList) {
                                        //1、得到每一个备品
                                        //2、得到每一个计划数名字(通过map获取全部的计划数名字,再将其遍历获取单个计划书名字,
                                        //     之后将其备品与计划数名字进行对比,如果相等(表示有对应的opd计划)则跳出循环)
                                        if (OPDbp.equals(planNumberApi)) {
                                            anotFlage = false;
                                            FlagBl = false;
                                        }
                                    }
                                }
                            }
                            if (FlagBl = false) {
                                continue;
                            }
                        }
                    }
                    if (anotFlage = false) {
                        continue;
                    }
                    // 将产品名: opd计划月的值 赋值给 产品明细变量上
                    //产品明细
                    producDetail = OPDPlanMonthMap.get(monthapikey) ;
                }
            }
            // 如果产品明细不为空 则任务的
            if (String.isNotBlank(producDetail)) {
                String anotName = anot.Account__r.name;
                String anotdepart = anot.Account__c;
                task__c newTask = new task__c();
                // 被分配者-战略科室的所有人
                newTask.assignee__c = anot.Account__r.ownerid;
                // 所有人-所有人
                newTask.ownerid = anot.Account__r.ownerid;
                //     产品明细-产品明细
                newTask.ProductDetails__c = producDetail;
                //     记录类型-OPD
                newTask.RecordTypeId =
                    Schema.SObjectType.task__c.getRecordTypeInfosByDeveloperName().get('OPD').getRecordTypeId();
                //     任务区分-‘被动任务’
                newTask.taskDifferent__c = '被动任务';
                //     任务名称-‘用户拜访:’ + 战略科室名
                newTask.Name = '用户拜访:' + anotName;
                //     客户-战略科室
                newTask.account__c = anotdepart;
                //newTask.OpportunityId__c = opdp.Id;
                //     任务状态2-‘01 分配’
                newTask.taskStatus__c = '01 分配';
                //     将任务添加到list(task__c)
                taskList.add(newTask);
            }
        }
        // 如果list中有任务 则
        if (taskList.size() > 0) {
            // 将该任务添加到数据库中
            Database.SaveResult[] SaveResult = Database.insert(taskList, false);
            // 计数,添加了几条
            AllCount = SaveResult.size();
            //循环,任务的条数
            for (Integer i = 0 ; i < SaveResult.size() ; i++) {
                // 如果没添加成功,将‘被动任务’:该任务 存到日志中,将第几条的报错信息存到错误日志中,计数总共没添加成功几条
                if (! SaveResult.get(i).isSuccess()) {
                    logstr += taskList.get(i).account__c + ',';
                    errorstr += SaveResult.get(i).getErrors();
                    failedCount++;
                }
            }
        }
    }
    // 创建日志(用来存添加失败的任务,以及每一条添加失败的信息)
    global void finish(DataBase.BatchableContext BC) {
        BatchIF_Log__c batchIfLog = new BatchIF_Log__c();
        batchIfLog.Type__c = 'CreateTask';
        if (logstr.length() > 60000) {
            logstr = logstr.substring(0, 60000);
        }
        batchIfLog.Log__c = logstr;
        if (errorstr.length() > 60000) {
            batchIfLog.ErrorLog__c = errorstr.substring(0, 60000);
        } else {
            batchIfLog.ErrorLog__c = errorstr.substring(0, errorstr.length());
        }
        insert batchIfLog;
        emailMessages.add('失败日志:' + batchIfLog.Id);
        sendemail();
    }
    // 发送提醒邮件
    global void sendemail() {
        // 1、如果战略科室为空 并且 医院为空 则
        if (isAutoexec) {
            PretechBatchEmailUtil db = new PretechBatchEmailUtil();
            // 定义两个数组(一个为空,一个存接收邮件者,一个存抄送人)及一个标题
            String[] Receiver = new String[] {UserInfo.getUserName()};
            List<String> CCto = new List<String>();
            String title = '创建失败任务';
            //如果邮件信息有值 并且 失败总数大于0 则
            if (System.Test.isRunningTest()) {
                db.successMail('', 1);
            }
            if (emailMessages.size() > 0 && failedCount > 0) {
                //  发送失败邮件的内容为:接收人,抄送人,标题,将全部的错误日志显示出来,总数,成功数,失败数
                db.failedMail(Receiver, CCto, title,
                              String.join(emailMessages, '/n'),
                              AllCount, AllCount - failedCount, failedCount, '', true);
                //  如果!Test.isRunningTest,则发送
                if (!Test.isRunningTest()) {
                    db.send();
                }
            }
        }
    }
}