liuyn
2024-03-11 a87f1c3df03078814ee97ad0c8ac200a232419e9
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
342
343
344
345
346
347
348
global class ConsumInventoryReportDtlArcRaesdBatch implements Database.Batchable<sObject>, Database.Stateful {
    private Inventory_Header__c ih_new = new Inventory_Header__c();
    private String docBodyRaesd = '';
    private Integer docBodyRaesdBlobSize = 0;
    private Id folderId = System.Label.InventoryFolder;//文档库id ymh add
    private Boolean falg = false;   //保存或更新标识 ymh add
 
    private Set<String> defaultAssetField;
    private Set<String> defaultRaesdField;
    private List<String> cListAssetField = new List<String>();
    private List<String> cListRaesdField = new List<String>();
    private Map<String, String> fieldAPIName = new Map<String, String>();
 
    global List<String> emailMessages;
    global Integer totalCount = 0; // 跨Batch 总件数
    global Integer totalCountDone = 0; // 跨Batch 成功件数
    global Integer executeCount = 0; // batch内的 总件数
    global Integer executeCountDone = 0; // batch内的 成功件数
    global Integer failedCount = 0; // batch内的 失败件数
    global Integer fileNo; // 生成多个文件时,文件名尾部追加序号
    private boolean overSizeFlg = false; // 当execute是否执行flag(false执行,true不执行)
 
    @TestVisible
    private static List<String> messagesForTest;
 
    /**
     * 批准后, Trigger 会来调
     */
    global ConsumInventoryReportDtlArcRaesdBatch(Inventory_Header__c ih_new ,Integer fileNo, Integer totalCount, Integer totalCountDone) {
        this.emailMessages = new List<String>();
        this.ih_new = ih_new;
        this.fileNo = fileNo;
        this.totalCount = totalCount;
        this.totalCountDone = totalCountDone;
    }
 
    global Database.QueryLocator start(Database.BatchableContext bc) {
        // bp3_Setting__c conf = bp3_Setting__c.getOrgDefaults();
        if (String.isBlank(folderId)) {
            this.emailMessages.add('未设置CSV保存文件夹,不能开始Batch');
            failedCount = 0;
            return Database.getQueryLocator([SELECT Id FROM Consum_Inventory_Detail__c LIMIT 0]);
        }
 
        Inventory_Batch_Mapping__mdt columns;
        List<String> keyList;
 
        defaultAssetField = new Set<String>();
        defaultRaesdField = new Set<String>();
 
        columns = [select From_Columns__c, Inventory_Columns__c from Inventory_Batch_Mapping__mdt where DeveloperName = 'ConsumAsset'];
        keyList = columns.Inventory_Columns__c.split(',');
        keyList.addAll(new List<String> {
                'Inventory_Zaiku_Count_Jia__c',
                'Inventory_Shipan_Count_Jia__c',
                //'Inventory_Weixiu_Count_Jia__c',
                'Inventory_Chujie_Count_Jia__c',
                //'Inventory_Daibaofei_Diushi_Count_Jia__c',
                'Inventory_Quantity_Jia__c',
                'Inventory_Profit_Quantity__c',
                'Inventory_Loss_Quantity__c',
                'Inventory_Deviation_Jia__c',
                'Inventory_Remarks__c',
                'Barcode__c',
                'Consumed_Count__c'
        });
        for (Integer i = 0; i < keyList.size(); i++) {
            if (!defaultAssetField.contains(keyList[i])) {
                cListAssetField.add(keyList[i]);
            }
            defaultAssetField.add(keyList[i]);
        }
 
        String cListRaesdFieldStr = 'Consum_Apply_Name__c,Account__c,RA_Status__c,Salesdept__c,WorkPlace__c,Person_In_Charge_New__c,Person_In_Charge__c,demo_purpose2__c,RAES_No__c,RAES_Status__c,RAESD_Name__c,RAESD_Status__c,Fixture_Model_No__c,SerialNumber__c,Internal_asset_location__c,Equipment_Type__c,Salesdepartment__c,WH_location__c,Consum_Start_Date__c,Show_demonstration__c,Operation_Type__c,Case_OR_animal_organ__c,Trial_User__c,Follower_User__r.Name,Spare__c,Request_approval_time__c,Select_Time__c,Request_shipping_day__c,Shipment_request_time2__c,Shippment_loaner_time__c,Loaner_received_time__c,Asset_return_time__c,Consum_Received_Day__c,Asset_Center_Confirm_Time__c,AssetManageConfirmYN__c,RAESD__c,Consum_Apply__c,Consum_Apply_Equipment_Set__c,Asset__c';
        cListRaesdField = cListRaesdFieldStr.split(',');
 
        //获取label
        String objectType ='Consum_Inventory_Detail__c';
        Map<String, Schema.SObjectType> schemaMap = Schema.getGlobalDescribe();
        Schema.SObjectType leadSchema = schemaMap.get(objectType);
        Map<String, Schema.SObjectField> fieldMap = leadSchema.getDescribe().fields.getMap();
 
        for(String fieldName : fieldMap.keySet()){
            fieldAPIName.put(fieldName, fieldMap.get(fieldName).getDescribe().getLabel());
        }
 
        Id ih_new_Id = ih_new.Id;
        List<Id> assetIds = new List<Id>();
 
        String idcQuerysql = 'select ' + String.join(new List<String>(defaultAssetField), ', ')
                + ' from Consum_Inventory_Detail__c'
                + ' where Sync_Asset_Record_Flag__c = true'
                + ' and Inventory_Header__c = :ih_new_Id';
 
        for (Consum_Inventory_Detail__c idc : Database.query(idcQuerysql)) {
            assetIds.add(idc.Asset__c);
        }
 
        String querysql = 'select ' + String.join(new List<String>(cListRaesdField), ', ') + ', Exported__c'
                + ' from Consum_Inventory_Detail__c where Asset__c IN :assetIds and Inventory_Header__c = :ih_new_Id and Asset_Status__c = \'出借中\''
                + ' and Exported__c = false';
 
        return Database.getQueryLocator(querysql);
    }
 
    global void execute(Database.BatchableContext BC, List<Consum_Inventory_Detail__c> raesdList) {
        // flag为true时,跳过execute处理
        if (true == overSizeFlg) {
            //System.abortJob(BC.getJobId());
            return;
        }
 
        executeCount += raesdList.size();
 
        Integer DOC_MAX_SIZE = Integer.valueOf(System.Label.DocumentFileSize_KB.replaceAll(',', '')) * 1000;  // 1024 ? 1000 ? 暂时用 1000 了
        Savepoint sp = Database.setSavepoint();
        try {
            List<Consum_Inventory_Detail__c> inventoryLst = new List<Consum_Inventory_Detail__c>();
            String executeBodyRaesd = '';
            // 借出明细
            for (Integer i = 0; i < raesdList.size(); i++) {
                Consum_Inventory_Detail__c dl = raesdList[i];
                String dummyRaesd = setDocBodyObject(dl, 'Caesd', false);
                Integer dummyRaesdSize = Blob.valueOf(dummyRaesd).size();
                // 当前字符串大小未超过 DOC_MAX_SIZE
                if (dummyRaesdSize <= DOC_MAX_SIZE - docBodyRaesdBlobSize) {
                    executeCountDone++;
                    executeBodyRaesd += dummyRaesd;
                    docBodyRaesdBlobSize += dummyRaesdSize;
                    // 处理完毕对象Exported字段置true
                    dl.Exported__c = true;
                    inventoryLst.add(dl);
                }
                // 当前字符串大小超过 DOC_MAX_SIZE
                else {
                    overSizeFlg = true;
                    if (0 == fileNo) {
                        fileNo++;
                    }
                    executeCount = executeCount - raesdList.size();
                    executeCount = executeCount + i;
                    break;
                }
            }
            docBodyRaesd += executeBodyRaesd;
            system.debug('###executeCount : ' + executeCount);
            system.debug('###executeCountDone : ' + executeCountDone);
            // 处理完毕对象update
            update inventoryLst;
        } catch (Exception e) {
            Database.rollback(sp);
            failedCount += raesdList.size();
            System.debug(LoggingLevel.ERROR, e.getMessage() + '\n' + e.getStackTraceString());
            this.emailMessages.add(e.getMessage() + '\n' + e.getStackTraceString());
        }
    }
 
    private String setDocBodyObject(sObject obj, String typeStr, boolean label) {
        List<String> toCol;
        if (typeStr == 'Caesd') {
            toCol = cListRaesdField;
        }
        Schema.SObjectType targetType = Consum_Inventory_Detail__c.sObjectType;
        Schema.DescribeSObjectResult sobjResult = targetType.getDescribe();
        Map<string, Schema.SObjectField> m = sobjResult.fields.getMap();
        String docBody = '';
        for (Integer i = 0; i < toCol.size(); i++) {
            List<String> cols = toCol[i].split('\\.');
            if (obj == null) {
                if (label) {
                    docBody += fieldAPIName.get(toCol[i].toLowerCase().replace('__r.name','__c')).escapeCsv();
                } else {
                    docBody += toCol[i].escapeCsv();
                }
            }
            else {
                Object val = CreateRelationListPagingCmpCtrl.getObjectValue(obj, cols);
                if (val != null) {
                    Schema.DescribeFieldResult descField = m.get(toCol[i].toLowerCase().replace('__r.name','__c')).getDescribe();
                    if(descField.getType() == DisplayType.DATETIME && String.isNotBlank('' + val)){
                        docBody += (''+((Datetime) val).addHours(8)).escapeCsv();
                    }
                    else{
                        docBody += ('' + val).escapeCsv();
                    }
                }
            }
            // 加 , 和 行末 的换行
            if (i < toCol.size() - 1) {
                docBody += ',';
            } else {
                docBody += '\r\n';
            }
        }
        return docBody;
    }
     //20231018  ymh 修改文档存储  start
    public ContentVersion getArchiveFilenameForInsert(String typeStr, Inventory_Header__c ih_new, Integer fileNo) {
        bp3_Setting__c conf = bp3_Setting__c.getOrgDefaults();
        
        String fileNoStr = '';
        if (fileNo != 0) {
            fileNoStr = '_' + String.valueOf(fileNo);
        }
        String filename = ih_new.Inventory_Start_Date__c.year() + ('' + ih_new.Inventory_Start_Date__c.month()).leftPad(2, '0')
                + '_' + ih_new.Internal_asset_location__c + '_耗材借出明细'  + fileNoStr +  '.csv';
        
        // Document ret = new Document();
        // ret.Name = filename;
        // ret.FolderId = folderId;
        // ret.Type = 'csv';
        // insert ret;
 
        // String docBody = setDocBodyObject(null, typeStr, false);
        // docBody += setDocBodyObject(null, typeStr, true);
        // ret.Body = Blob.valueOf(docBody);
 
        // return ret;
 
        String docBody = setDocBodyObject(null, typeStr, false);
        docBody += setDocBodyObject(null, typeStr, true);
 
        ContentVersion version = null;
        //20231103 ymh  修改优化sql查询  start
        List<ContentVersion> verlist = [SELECT Id, Title, VersionData,ContentDocumentId,IsMajorVersion FROM ContentVersion WHERE Title =:filename and FirstPublishLocationId =:folderId];
        // List<ContentVersion> verlist = [SELECT Id, Title, VersionData,ContentDocumentId,IsMajorVersion FROM ContentVersion WHERE Title =:filename];
        System.debug('verList是否存在----------->>>>>'+verlist);
        
        if( verlist.size() > 0 ){
            version = verlist[0];
            falg = true;
            // List<ContentDocumentLink> linkList = [SELECT ContentDocumentId FROM ContentDocumentLink WHERE ContentDocumentId =:verlist[0].ContentDocumentId];
            // if( linkList.size() > 0 ){
            //     version = verlist[0];
            //     falg = true;
            // }
        //20231103 ymh  修改优化sql查询  end
        }else{
            version = new ContentVersion();
            version.Title = filename;
            version.VersionData = Blob.valueOf(docBody);
            version.PathOnClient = filename+'.csv';
        }
        return version;
    }
 
    public String insertContentDocumentLink(String versionId){
        ContentVersion version = [select ContentDocumentId from ContentVersion where Id =: versionId];
 
        System.debug('存入link----------->>>>>'+version.ContentDocumentId);
        String result ='';
        try{
            ContentDocumentLink link = new ContentDocumentLink(); 
            link.ContentDocumentId = version.ContentDocumentId;
            link.LinkedEntityId = folderId;
            link.ShareType = 'I';
            link.Visibility = 'AllUsers';
            StaticParameter.ContentDocumentLink = false;
            insert link;
            result = '1';
        }catch(Exception e){
            result = '0';
            return result;
        }
        return result;
       
    }
    //20231018 ymh 修改文档存储  end
 
    global void finish(Database.BatchableContext BC) {
        if (docBodyRaesd == '') {
            this.emailMessages.add('耗材明细数据不存在');
        } else {
            if (this.emailMessages.size() == 0 && executeCount == executeCountDone) {
                //20231018 ymh 修改文档存储  start
                
                // Document raesdDoc = getArchiveFilenameForInsert('Caesd', ih_new, fileNo);
                // raesdDoc.Body = Blob.valueOf(raesdDoc.Body.toString() + docBodyRaesd);
                // Database.SaveResult saveResult = Database.update(raesdDoc, false)
                ContentVersion raesdVersion ;
                try{
                    raesdVersion = getArchiveFilenameForInsert('Caesd', ih_new, fileNo);
                    raesdVersion.VersionData = Blob.valueOf(raesdVersion.VersionData.toString() + docBodyRaesd);
                }catch(Exception e){
                    System.debug(LoggingLevel.ERROR, e.getMessage() + '\n' + e.getStackTraceString());
                    this.emailMessages.add(e.getMessage() + '\n' + e.getStackTraceString());
                }
                
                Database.SaveResult saveResult;
                String res;
                if(falg){
                    // csv文件存在  update
                    saveResult = Database.update(raesdVersion, false);
                }else{
                    //csv文件不存在  insert
                    saveResult = Database.insert(raesdVersion, false);
                    res = insertContentDocumentLink(raesdVersion.Id);
                }
                if (!saveResult.isSuccess() || res== '0') {
                    failedCount = executeCountDone;     // Docuemnt 都算成 fail
                    this.emailMessages = FixtureUtil.setSaveError(new List<Database.SaveResult>{saveResult}, ContentVersion.sObjectType, new List<ContentVersion>{raesdVersion}, this.emailMessages);
                }
                    //20231018 ymh 修改文档存储  end
            }
            totalCount += executeCount;
            totalCountDone += executeCountDone;
            // flag为true(字符串大小超过9.9M),且未发生错误时再次执行batch
            if (true == overSizeFlg && this.emailMessages.size() == 0 && executeCount == executeCountDone) {
                fileNo++;
                ConsumInventoryReportDtlArcRaesdBatch raesdBatch = new ConsumInventoryReportDtlArcRaesdBatch(ih_new, fileNo, totalCount, totalCountDone);
                Database.executeBatch(raesdBatch);
            } else {
                // TODO wwf email
                ConsumInventoryReportDtlArcRaesdBatch.messagesForTest = this.emailMessages;
                // 发 mail
                BatchEmailUtil be = new BatchEmailUtil();
                String[] toList = new String[]{};
                String title = '存档盘点CSV 耗材盘点明细(借出中) #' + fileNo + ' ';
                if (false == overSizeFlg) {
                    title += '最后 ';
                }
                String[] ccList = new String[]{};
 
                Inventory_Header__c iheader = [select Id, Inventory_Status__c, Name, Internal_asset_location__c, Inventory_Start_Date__c from Inventory_Header__c where Id = :ih_new.Id];
                String text = '耗材盘点报告书编号:' + iheader.Name + '  盘点地点:' + iheader.Internal_asset_location__c + '  盘点开始日:' + iheader.Inventory_Start_Date__c;
 
                if(this.emailMessages.size() == 0 && totalCount == totalCountDone) {
                    toList.add(UserInfo.getUserEmail());
                    be.successMail(toList, ccList, title, totalCountDone, text);
                } else {
                    String emailLabel = 'BatchNotify';
                    for (OrgWideEmailAddress tmpEmailObj : [SELECT Id, Address, DisplayName
                            FROM OrgWideEmailAddress
                            WHERE DisplayName like :emailLabel]) {
                        ccList.add(tmpEmailObj.Address);
                    }
                    for(String email : System.Label.Inventory_Result_Email.split(',')){
                        ccList.add(email);
                    }
                    be.failedMail(toList, ccList, title,
                            String.join(this.emailMessages, '\n'),
                            totalCount, totalCountDone, failedCount, text);
                }
                be.send();
            }
        }
    }
}