高章伟
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
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
global class ConsumInventoryStartAssetSnapshotBatch implements Database.Batchable<sObject>, Database.Stateful {
 
    private String cunFangDi { get; set; }     //存放地, 肯定有值 不为null
    private Datetime lastInventoryTime {get;set;} // 上次盘点时间
    private Inventory_Header__c ih_new = new Inventory_Header__c(); // 借出备品盘点表头
    private Inventory_Header__c ih_consum = new Inventory_Header__c(); // 耗材备品盘点表头
    private Map<String, List<String>> statusMap = new Map<String, List<String>>();
    private Map<String, String> assetFieldMap = new Map<String, String>();
    private Map<String, String> raesdFieldMap = new Map<String, String>();
    //private Map<String, String> repairFieldMap = new Map<String, String>();
    private Set<String> availableMain = new Set<String>();
    private Set<String> availableMainOnStock = new Set<String>();
    private Set<String> defaultAssetField;
    private Set<String> defaultRaesdField;
    //private Set<String> defaultRepairField;
 
    global List<String> emailMessages;
    global Integer totalCount = 0; // 总件数 (Asset)
    global Integer executedCount = 0;
    global Integer failedCount = 0;
    global Id recordTypeId;
 
    @TestVisible
    private static List<String> messagesForTest;
 
    global ConsumInventoryStartAssetSnapshotBatch(String cunFangDi, Inventory_Header__c ih_new){
        Integer i = 0;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        i ++;
        this.cunFangDi = cunFangDi;
        this.ih_new = [SELECT Id, Name, InventorySubmit_PIC__c,InventoryCheck_PIC__c FROM Inventory_Header__c WHERE Id=:ih_new.Id LIMIT 1];
        this.emailMessages = new List<String>();
        this.recordTypeId = Inventory_Header__c.sObjectType.getDescribe().getRecordTypeInfosByDeveloperName().get('Consum_Header').getRecordTypeId();
    }
 
    global Database.QueryLocator start(Database.BatchableContext bc) {
        List<Inventory_Header__c> lastInventory = [SELECT CreatedDate
                                               FROM Inventory_Header__c
                                              WHERE Fixture_Header__c!=null
                                                AND Fixture_Header__c!=:ih_new.Id
                                              ORDER BY CreatedDate DESC
                                              LIMIT 1
                                              ];
        if(lastInventory.isEmpty()){
            lastInventoryTime = Datetime.newInstanceGMT(1970, 1, 1, 0, 0, 0);
        }
        else{
            lastInventoryTime = lastInventory[0].CreatedDate;
        }
        List<Inventory_Header__c> ihConsumList = [SELECT Id
                                                 , Name
                                                 , Inventory_Status__c
                                                 , Internal_asset_location__c
                                                 , InventorySubmit_PIC__c
                                                 , InventoryCheck_PIC__c
                                              FROM Inventory_Header__c
                                             WHERE Fixture_Header__c = :ih_new.Id];
        if (ihConsumList.size() == 0){
            Inventory_Header__c ih = new Inventory_Header__c();
            ih.Internal_asset_location__c = cunFangDi;
            ih.Inventory_Status__c = '处理中';
            ih.InventoryPIC__c = UserInfo.getUserId();
            ih.Inventory_Start_Date__c = Date.today();
            ih.InventorySubmit_PIC__c = ih_new.InventorySubmit_PIC__c;
            ih.InventoryCheck_PIC__c = ih_new.InventoryCheck_PIC__c;
            ih.Fixture_Header__c = ih_new.id;
            ih.UniqueKey__c = cunFangDi+':'+Date.today().toStartOfMonth();
            ih.RecordTypeId = this.recordTypeId;
            insert ih;
            this.ih_consum = ih;
        }
        else if (ihConsumList[0].Inventory_Status__c != '处理中') {
            if (ihConsumList[0].Inventory_Status__c == null) {
                Inventory_Header__c ih = new Inventory_Header__c();
                ih.Internal_asset_location__c = ihConsumList[0].Internal_asset_location__c;
                ih.Inventory_Status__c = '处理中';
                ih.InventoryPIC__c = UserInfo.getUserId();
                ih.Inventory_Start_Date__c = Date.today();
                ih.InventorySubmit_PIC__c = ihConsumList[0].InventorySubmit_PIC__c;
                ih.InventoryCheck_PIC__c = ihConsumList[0].InventoryCheck_PIC__c;
                ih.Fixture_Header__c = ih_new.id;
                ih.UniqueKey__c = ihConsumList[0].Internal_asset_location__c+':'+Date.today().toStartOfMonth();
                ih.RecordTypeId = this.recordTypeId;
 
                delete ihConsumList[0];
                insert ih;
                this.ih_consum = ih;
            } else {
                this.emailMessages.add(ihConsumList[0].Name +'的状态是' + ihConsumList[0].Inventory_Status__c + ' ,不能盘点。');
                return Database.getQueryLocator([SELECT Id FROM Asset LIMIT 0]);
            }
        }
 
        List<Asset> errorList = [SELECT Id
                                      , Inventory_Frozen_Quantity__c
                                   FROM Asset
                                  WHERE (Inventory_Frozen_Quantity__c>0
                                     OR Appended_Inventory_Frozen_Quantity__c>0
                                     OR Inventory_Profit_Quantity__c>0
                                     OR Appended_Inventory_Profit_Quantity__c>0)
                                     AND Asset_loaner_category__c = '耗材'
                                    AND Internal_asset_location__c = :cunFangDi];
        if (errorList.size()>0) {
            Inventory_Header__c ihc = [SELECT Name FROM Inventory_Header__c WHERE id=:this.ih_consum.Id];
            this.emailMessages.add(ihc.Name + ' 耗材资产中存在未清空的冻结数, 不能盘点。');
            return Database.getQueryLocator([SELECT Id FROM Asset LIMIT 0]);
        }
 
        defaultAssetField = new Set<String> {'Id','Abandoned_RealThing__c','Abandoned_Inventory__c','Barcode__c','Consumed_Count__c','Fixture_Model_No_F__c','Internal_asset_location__c','WH_location__c','Ji_Zhong_Guan_Li_Ku_Cun__c','You_Xiao_Ku_Cun__c','Out_of_wh__c','Manage_type__c','Fixture_Status__c','Quantity','Frozen_Quantity__c'};
        defaultRaesdField = new Set<String> {'Id','Asset__c','RAESD_Status__c'};
 
        statusMap.put('出借中', new List<String> {'已出库','申请者已收货','申请者收货NG','待消耗','已回寄'});
        statusMap.put('在库', new List<String> {'䓍案中','申请中','暂定分配','已分配','已出库指示','移至过期区','待废弃','已回库'});
 
        Inventory_Batch_Mapping__mdt columns = [select From_Columns__c, Inventory_Columns__c from Inventory_Batch_Mapping__mdt where DeveloperName = 'ConsumAsset'];
        List<String> keyList = columns.From_Columns__c.split(',');
        List<String> valueList = columns.Inventory_Columns__c.split(',');
        for (Integer i = 0; i < keyList.size(); i++) {
            assetFieldMap.put(keyList[i], valueList[i]);
            defaultAssetField.add(keyList[i]);
        }
 
        columns = [select From_Columns__c, Inventory_Columns__c from Inventory_Batch_Mapping__mdt where DeveloperName = 'CAESD'];
        keyList = columns.From_Columns__c.split(',');
        valueList = columns.Inventory_Columns__c.split(',');
        for (Integer i = 0; i < keyList.size(); i++) {
            raesdFieldMap.put(keyList[i], valueList[i]);
            defaultRaesdField.add(keyList[i]);
        }
 
        String querysql = 'select ' + String.join(new List<String>(defaultAssetField), ', ')
                + ' from Asset '
                + 'where Internal_asset_location__c = :cunFangDi'
                + '  and Fixture_Status__c != \'废弃\''
                + '  and Delete_Flag__c = False'
                + '  and (Quantity > 0 or Consumed_Count__c > 0)'
                + '  and Asset_Owner__c = \'Olympus\''
                + '  and ' + FixtureUtil.getAssetSoqlBase()
                + '  and Asset_loaner_category__c = \'耗材\''
                // 增加排序确保主体先处理
                + '  order by Manage_type__c desc, Main_OneToOne__c desc, Last_Reserve_RAES_Detail__r.Is_Body__c desc';
        return Database.getQueryLocator(querysql);
    }
 
    global void execute(Database.BatchableContext BC, list<Asset> assetList) {
        // select ih_new, is batch executing, else return
        List<Inventory_Header__c> ihConsumList = [select Id, Name, Inventory_Status__c
                from Inventory_Header__c where Fixture_Header__c = :ih_new.Id];
        if (ihConsumList.size() == 0 || ihConsumList[0].Inventory_Status__c != '处理中') {
            // emailMessages ihConsumList[0].Name 的状态是 ihConsumList[0].Inventory_Status__c 不能盘点
            this.emailMessages.add(ihConsumList[0].Name +'的状态是' + ihConsumList[0].Inventory_Status__c + ' ,不能盘点。');
            return;
        }
    Savepoint sp = Database.setSavepoint();
    try {
        //总件数count
        totalCount += assetList.size();
 
        // UniqueKey__c:Record
        Map<String, Consum_Inventory_Detail__c> upsertMap = new Map<String, Consum_Inventory_Detail__c>();
        Map<Id, Asset> assetMap = new Map<Id, Asset>();
        for (Asset ast : assetList) {
            assetMap.put(ast.Id, ast);
            // '在库' from Asset
            Consum_Inventory_Detail__c ihDetail = new Consum_Inventory_Detail__c();
            ihDetail.Asset__c = ast.Id;
 
            ihDetail.Amount__c = ast.Quantity;
            ihDetail.WH_location__c = ast.WH_location__c;
 
            ihDetail.Asset_Status__c = '在库';
            ihDetail.Sync_Asset_Record_Flag__c = true;
            ihDetail.UniqueKey__c = ih_consum.Id+':'+ast.Fixture_Model_No_F__c+':'+ihDetail.Asset_Status__c+':'+ast.Id;
            ihDetail.Inventory_Header__c = ih_consum.Id;
            ihDetail.Fixture_Model_No__c = ast.Fixture_Model_No_F__c;
            ihDetail.Internal_asset_location__c = ast.Internal_asset_location__c;
            ihDetail.toAbandon_amount__c = ast.Abandoned_RealThing__c;
            ihDetail.Abandoned_Inventory_Start__c = ast.Abandoned_Inventory__c;
            if(ast.Abandoned_Inventory__c!=null && ast.Abandoned_Inventory__c > 0) {
                ihDetail.Amount__c -= ast.Abandoned_Inventory__c;
            }
            // '已消耗' from Asset
            if (ast.Consumed_Count__c > 0) {
                Consum_Inventory_Detail__c ihDetail_abd = new Consum_Inventory_Detail__c();
                ihDetail_abd.Asset__c = ast.Id;
                ihDetail_abd.Asset_Status__c = '已消耗';
                ihDetail_abd.UniqueKey__c = ih_consum.Id+':'+ast.Fixture_Model_No_F__c+':'+ihDetail_abd.Asset_Status__c+':'+ast.Id;
                ihDetail_abd.Inventory_Header__c = ih_consum.Id;
                ihDetail_abd.Fixture_Model_No__c = ast.Fixture_Model_No_F__c;
                ihDetail_abd.WH_location__c = ast.WH_location__c;
                ihDetail_abd.Internal_asset_location__c = ast.Internal_asset_location__c;
                ihDetail_abd.Amount__c = ast.Consumed_Count__c;
                ihDetail_abd.Consumed_Count_Start__c = ast.Consumed_Count__c;
                setMapObject(ihDetail_abd, ast, 'Asset');
                upsertMap.put(ihDetail_abd.UniqueKey__c, ihDetail_abd);
            }
            // '冻结' from Asset
            if (ast.Frozen_Quantity__c > 0) {
                Consum_Inventory_Detail__c ihDetail_frz = new Consum_Inventory_Detail__c();
                ihDetail_frz.Asset__c = ast.Id;
                //if (ast.Main_OneToOne__c) {
                //    ihDetail_frz.OneToOne_Body__c = true;
                //}
                //if (ast.Fixture_OneToOne_Link__c != null) {
                //    ihDetail_frz.Main_Asset__c = ast.Fixture_OneToOne_Link__r.Main_Asset__c;
                //}
                ihDetail_frz.Asset_Status__c = '冻结';
                ihDetail_frz.UniqueKey__c = ih_new.Id+':'+ast.Fixture_Model_No_F__c+':'+ihDetail_frz.Asset_Status__c+':'+ast.Id;
                ihDetail_frz.Inventory_Header__c = ih_consum.Id;
                ihDetail_frz.Fixture_Model_No__c = ast.Fixture_Model_No_F__c;
                ihDetail_frz.WH_location__c = ast.WH_location__c;
                ihDetail_frz.Internal_asset_location__c = ast.Internal_asset_location__c;
                ihDetail_frz.Amount__c = ast.Frozen_Quantity__c;
                setMapObject(ihDetail_frz, ast, 'Asset');
                upsertMap.put(ihDetail_frz.UniqueKey__c, ihDetail_frz);
                ihDetail.Amount__c = ihDetail.Amount__c - ihDetail_frz.Amount__c;
            }
            //待废弃数
            if (ast.Fixture_Status__c == '待废弃') {
                ihDetail.toAbandon_amount__c = ihDetail.Amount__c;
            }
            setMapObject(ihDetail, ast, 'Asset');
            //if (ast.Fixture_OneToOne_Link__c != null) {
            //    ihDetail.WH_location__c = ast.Fixture_OneToOne_Link__r.Main_Asset__r.WH_location__c;
            //}
            upsertMap.put(ihDetail.UniqueKey__c, ihDetail);
        }
 
        //耗材一览明细
        List<Consum_Apply_Equipment_Set_Detail__c> copy_caList = [select Consum_Apply__c
                from Consum_Apply_Equipment_Set_Detail__c
                where Asset__c IN :assetList
                    and Consum_Apply__r.RA_Status__c ='完了'
                    and RAESD_Status__c ='已消耗'
                    and Lost_item_check_time_Final__c>:lastInventoryTime
                    ];
 
        Set<Id> copy_caId = new Set<Id>();
        for (Consum_Apply_Equipment_Set_Detail__c copy_ca : copy_caList) {
            copy_caId.add(copy_ca.Consum_Apply__c);
        }
 
        String querysql = 'select ' + String.join(new List<String>(defaultRaesdField), ', ')
                + ' from Consum_Apply_Equipment_Set_Detail__c '
                + ' where Asset__c IN :assetList '
                + ' and (Consum_Apply__r.RA_Status__c <> \'完了\' or Consum_Apply__c in :copy_caId)';
 
        List<Consum_Apply_Equipment_Set_Detail__c> detailList = Database.query(querysql);
 
        for (Consum_Apply_Equipment_Set_Detail__c dl : detailList) {
            Asset ast = assetMap.get(dl.Asset__c);
            //String main_Asset_Id = null;
            //if (ast.Fixture_OneToOne_Link__c != null) {
            //    main_Asset_Id = ast.Fixture_OneToOne_Link__r.Main_Asset__c;
            //} else if (ast.Last_Reserve_RAES_Detail__r.Is_Body__c && statusMap.get('在库').contains(ast.Last_Reserve_RAES_Detail__r.RAESD_Status__c)) {
            //    main_Asset_Id = ast.Id;
            //}
 
            // 已消耗的耗材明细 (仿照备品的丢失改写)
            if ('已消耗' == dl.RAESD_Status__c && dl.Lost_item_check_time_Final__c!=null && dl.Lost_item_check_time_Final__c>lastInventoryTime) {
                Consum_Inventory_Detail__c ihDetail_lend = new Consum_Inventory_Detail__c();
                ihDetail_lend.Asset__c = ast.Id;
                ihDetail_lend.RAESD__c = dl.Id;
                ihDetail_lend.RAESD_Id__c = dl.Id;
                ihDetail_lend.Asset_Status__c = '已消耗明细';
                ihDetail_lend.UniqueKey__c = ih_consum.Id+':'+ast.Fixture_Model_No_F__c+':'+ihDetail_lend.Asset_Status__c+':'+ast.Id+':'+dl.Id;
                ihDetail_lend.Inventory_Header__c = ih_consum.Id;
                ihDetail_lend.Fixture_Model_No__c = ast.Fixture_Model_No_F__c;
                ihDetail_lend.WH_location__c = ast.WH_location__c;
                ihDetail_lend.Internal_asset_location__c = ast.Internal_asset_location__c;
                ihDetail_lend.Amount__c = 1;
                setMapObject(ihDetail_lend, ast, 'Asset');
                setMapObject(ihDetail_lend, dl, 'Raesd');
                upsertMap.put(ihDetail_lend.UniqueKey__c, ihDetail_lend);
            }
            // 出借中 from 明细
            else if (statusMap.get('出借中').contains(dl.RAESD_Status__c)) {
                Consum_Inventory_Detail__c ihDetail_lend = new Consum_Inventory_Detail__c();
                ihDetail_lend.Asset__c = ast.Id;
                ihDetail_lend.RAESD__c = dl.Id;
                ihDetail_lend.RAESD_Id__c = dl.Id;
                ihDetail_lend.Asset_Status__c = '出借中';
                ihDetail_lend.UniqueKey__c = ih_consum.Id+':'+ast.Fixture_Model_No_F__c+':'+ihDetail_lend.Asset_Status__c+':'+ast.Id+':'+dl.Id;
                ihDetail_lend.Inventory_Header__c = ih_consum.Id;
                ihDetail_lend.Fixture_Model_No__c = ast.Fixture_Model_No_F__c;
                ihDetail_lend.WH_location__c = ast.WH_location__c;
                ihDetail_lend.Internal_asset_location__c = ast.Internal_asset_location__c;
                ihDetail_lend.Amount__c = 1;
                setMapObject(ihDetail_lend, ast, 'Asset');
                setMapObject(ihDetail_lend, dl, 'Raesd');
                upsertMap.put(ihDetail_lend.UniqueKey__c, ihDetail_lend);
 
                String uniKey = ih_consum.Id+':'+ast.Fixture_Model_No_F__c+':'+'在库'+':'+ast.Id;
                Consum_Inventory_Detail__c ihDetail = upsertMap.get(uniKey);
                if (ihDetail != null) {
                    ihDetail.Amount__c -= 1;
                    upsertMap.put(ihDetail.UniqueKey__c, ihDetail);
                }
            }
            // 待移至报废区+设置虚拟货架号 from 明细
            else if (statusMap.get('在库').contains(dl.RAESD_Status__c)) {
                //if(dl.OneToOne_Flag__c == false) {
                    String uniKey = ih_consum.Id+':'+ast.Fixture_Model_No_F__c+':'+'在库'+':'+ast.Id;
                    String vhwLocation = '待回库区';
                    //if(dl.RAESD_Status__c == '已下架' || dl.RAESD_Status__c == '出库前已检测' ){
                    //    vhwLocation = '备货区';
                    //}
                    //设置待报废数量
                    Consum_Inventory_Detail__c ihDetail = upsertMap.get(uniKey);
                    if (dl.RAESD_Status__c == '待废弃' ) {
                        if (ihDetail.toAbandon_amount__c == null) {
                            ihDetail.toAbandon_amount__c = 1;
                        } else {
                            ihDetail.toAbandon_amount__c += 1;
                        }
                    }
 
                    ihDetail.VWH_location__c = vhwLocation;
                    upsertMap.put(ihDetail.UniqueKey__c, ihDetail);
                //}
                // 一对一
                //else {
                //    main_Asset_Id = dl.Rental_Apply_Equipment_Set__r.First_RAESD__r.Asset__c;
                //    String uniKey = ih_new.Id+':'+ast.Fixture_Model_No_F__c+':'+'在库'+':'+main_Asset_Id+':'+ast.Id;
                //    String vhwLocation = '待回库区';
                //    if(dl.RAESD_Status__c == '已下架' || dl.RAESD_Status__c == '出库前已检测' ){
                //        vhwLocation = '备货区';
                //    }
                //    Inventory_Detail__c ihDetail = upsertMap.get(uniKey);
                //    if (ihDetail == null) {
                //        ihDetail = new Inventory_Detail__c();
                //        ihDetail.Asset__c = ast.Id;
                //        ihDetail.OneToOne_Accsessary__c = true;
                //        ihDetail.Main_Asset__c = main_Asset_Id;
                //        ihDetail.Asset_Status__c = '在库';
                //        ihDetail.UniqueKey__c = ih_new.Id+':'+ast.Fixture_Model_No_F__c+':'+ihDetail.Asset_Status__c+':'+ihDetail.Main_Asset__c+':'+ast.Id;
                //        ihDetail.Inventory_Header__c = ih_new.Id;
                //        ihDetail.Fixture_Model_No__c = ast.Fixture_Model_No_F__c;
                //        ihDetail.VWH_Location__c = vhwLocation;
                //        ihDetail.Internal_asset_location__c = ast.Internal_asset_location__c;
                //        ihDetail.Amount__c = 1;
                //        setMapObject(ihDetail, ast, 'Asset');
                //        ihDetail.WH_location__c = dl.Rental_Apply_Equipment_Set__r.First_RAESD__r.Asset__r.WH_location__c;
                //        upsertMap.put(ihDetail.UniqueKey__c, ihDetail);
                //    } else {
                //        ihDetail.Amount__c += 1;
                //        //ihDetail.VWH_location__c = vhwLocation;
                //        upsertMap.put(ihDetail.UniqueKey__c, ihDetail);
                //    }
                //    uniKey = ih_new.Id+':'+ast.Fixture_Model_No_F__c+':'+'在库'+':'+null+':'+ast.Id;
                //    if (upsertMap.containsKey(uniKey)) {
                //        Inventory_Detail__c ihDetail_org = upsertMap.get(uniKey);
                //        ihDetail_org.Amount__c -= 1;
                //        upsertMap.put(ihDetail_org.UniqueKey__c, ihDetail_org);
                //    }
                //}
            }
        }
        // link 一对一
        //List<Fixture_OneToOne_Link__c> otoAccessoryList =
        //    [select Accessory_Asset__r.Fixture_Model_No_F__c,
        //            Accessory_Asset__r.Internal_asset_location__c,
        //            Accessory_Asset__r.WH_location__c,
        //            Main_Asset__r.WH_location__c,
        //            Accessory_Asset__c,
        //            Main_Asset__c,
        //            Quantity__c
        //        from Fixture_OneToOne_Link__c
        //        where Accessory_Asset__r.Internal_asset_location__c=:cunFangDi
        //         and Accessory_Asset__c IN :assetList];
        //for (Fixture_OneToOne_Link__c odl : otoAccessoryList) {
        //    Asset ast = assetMap.get(odl.Accessory_Asset__c);
        //    String main_Asset_Id = odl.Main_Asset__c;
        //    String uniKey = ih_new.Id+':'+ast.Fixture_Model_No_F__c+':'+'在库'+':'+main_Asset_Id+':'+ast.Id;
        //    Inventory_Detail__c ihDetail = upsertMap.get(uniKey);
        //    if (ihDetail == null) {
        //        ihDetail = new Inventory_Detail__c();
        //        ihDetail.Asset__c = ast.Id;
        //        ihDetail.Asset_Status__c = '在库';
        //        ihDetail.Inventory_Header__c = ih_new.Id;
        //        ihDetail.UniqueKey__c = uniKey;
        //        ihDetail.OneToOne_Accsessary__c = true;
        //        ihDetail.Main_Asset__c = main_Asset_Id;
        //        ihDetail.Fixture_Model_No__c = odl.Accessory_Asset__r.Fixture_Model_No_F__c;
        //        ihDetail.Internal_asset_location__c = odl.Accessory_Asset__r.Internal_asset_location__c;
        //        ihDetail.Amount__c = odl.Quantity__c;
        //        setMapObject(ihDetail, ast, 'Asset');
        //        ihDetail.WH_location__c = odl.Main_Asset__r.WH_location__c;
        //        ihDetail.Fixture_OneToOne_Link__c = odl.Id;
        //        upsertMap.put(ihDetail.UniqueKey__c, ihDetail);
        //    } else {
        //        ihDetail.Amount__c += odl.Quantity__c;
        //        upsertMap.put(ihDetail.UniqueKey__c, ihDetail);
        //    }
        //    uniKey = ih_new.Id+':'+ast.Fixture_Model_No_F__c+':'+'在库'+':'+null+':'+ast.Id;
        //    if (upsertMap.containsKey(uniKey)) {
        //        Inventory_Detail__c ihDetail_org = upsertMap.get(uniKey);
        //        ihDetail_org.Amount__c -= odl.Quantity__c;
        //        upsertMap.put(ihDetail_org.UniqueKey__c, ihDetail_org);
        //    }
        //}
 
        //check amount
        Set<Id> asstIdSet = new Set<Id>();
        List<Consum_Inventory_Detail__c> upsertDetailList = new List<Consum_Inventory_Detail__c>();
        for (String uniKey: upsertMap.keySet()) {
            Consum_Inventory_Detail__c upsertDetail = upsertMap.get(uniKey);
            if (upsertDetail.Amount__c >= 0) {
                upsertDetailList.add(upsertDetail);
                // 收集所有在库的一对一主体Asset
                //if (upsertDetail.OneToOne_Body__c && upsertDetail.Amount__c > 0 && upsertDetail.Asset_Status__c == '在库') {
                //    availableMain.add(upsertDetail.Main_Asset__c);
                //    if (String.isBlank(upsertDetail.VWH_location__c)) availableMainOnStock.add(upsertDetail.Main_Asset__c);
                //}
            }
            if (upsertDetail.Amount__c < 0) {
                asstIdSet.add(upsertDetail.Asset__c);
                //error
                this.emailMessages.add('保有设备:'+upsertDetail.Fixture_Model_No__c + '(' + upsertDetail.Asset__c + ')的' + Consum_Inventory_Detail__c.Fields.Amount__c.getDescribe().getLabel() + ' < 0');
                //failedCount ++;
            }
        }
 
        // 处理找不到主体的一对一附属品
        //for (Consum_Inventory_Detail__c idc : upsertDetailList) {
        //    if (idc.OneToOne_Accsessary__c) {
        //        // 一对一附属品,并且对应的主体不是在库状态。
        //        if (!availableMain.contains(idc.Main_Asset__c) ||
        //                // 一对一附属品在借出明细里,主机单独上架了
        //                (availableMainOnStock.contains(idc.Main_Asset__c) && String.isBlank(idc.Fixture_OneToOne_Link__c))) {
 
        //            String uKey = idc.UniqueKey__c;
        //            List<String> parts = uKey.split(':');
        //            parts[3] = 'null';
        //            uKey = String.join(parts, (':'));
        //            // 把集中库存的的数量加回去
        //            Consum_Inventory_Detail__c ihDetail_org = upsertMap.get(uKey);
        //            if (ihDetail_org != null) {
        //                ihDetail_org.Amount__c += idc.Amount__c;
        //                upsertMap.put(ihDetail_org.UniqueKey__c, ihDetail_org);
        //                upsertMap.put(idc.UniqueKey__c, null);
        //            } else {
        //                //个体一对一附属品的话,清除一对一状态。
        //                if (idc.Manage_type__c == FixtureUtil.managetypeMap.get(FixtureUtil.Managetype.Ge_Ti_Guan_Li)) {
        //                    upsertMap.put(idc.UniqueKey__c, null);
        //                    idc.UniqueKey__c = uKey;
        //                    idc.OneToOne_Accsessary__c = false;
        //                    upsertMap.put(idc.UniqueKey__c, idc);
        //                } else {
        //                    this.emailMessages.add('不整合一对一数据:UniqueKey(' + idc.UniqueKey__c + ')');
        //                }
        //            }
        //        }
        //    }
        //}
 
        // 重新做成upsertlist
        upsertDetailList = new List<Consum_Inventory_Detail__c>();
        for (String uniKey: upsertMap.keySet()) {
            Consum_Inventory_Detail__c upsertDetail = upsertMap.get(uniKey);
            if (upsertDetail != null && upsertDetail.Amount__c >= 0) {
                upsertDetailList.add(upsertDetail);
            }
        }
 
        List<Database.UpsertResult> upResult = Database.upsert(upsertDetailList, Consum_Inventory_Detail__c.Fields.UniqueKey__c, false);
        this.emailMessages = FixtureUtil.setUpstError(upResult, Consum_Inventory_Detail__c.sObjectType, upsertDetailList, this.emailMessages);
        for (Integer i = 0; i < upResult.size(); i++) {
            Database.UpsertResult sr = upResult[i];
            if (!sr.isSuccess()) {
                Consum_Inventory_Detail__c iobj = upsertDetailList[i];
                asstIdSet.add(iobj.Asset__c);
            }
        }
        //upsert upsertDetailList UniqueKey__c;
 
        failedCount += asstIdSet.size();
    } catch(Exception e) {
        Database.rollback(sp);
        System.debug(LoggingLevel.ERROR, + e.getMessage() + '\n' + e.getStackTraceString());
        this.emailMessages.add(ihConsumList[0].Name  + ' 耗材盘点开始处理 Exception:' + e.getMessage() + '\n' + e.getStackTraceString());
    }
        executedCount += assetList.size();
    }
 
    global void finish(Database.BatchableContext BC) {
        String text = '';
        try {
            if (this.emailMessages.size() == 0 && totalCount == executedCount) {
                List<Inventory_Header__c> iheaderList = [select Id
                                                              , Inventory_Status__c
                                                              , Name
                                                              , Internal_asset_location__c
                                                              , Inventory_Start_Date__c
                                                              , Fixture_Header__c
                                                            from Inventory_Header__c
                                                            where Id = :ih_consum.Id
                                                            or Id = :ih_new.Id];
                for(Inventory_Header__c iheader : iheaderList){
                    iheader.Inventory_Status__c = '盘点中';
                    if(String.isNotBlank(iheader.Fixture_Header__c)){
                        text += '耗材盘点报告书编号:' + iheader.Name + '  耗材盘点地点:' + iheader.Internal_asset_location__c + '  耗材盘点开始日:' + iheader.Inventory_Start_Date__c;
                    }
                }
                update iheaderList;
                text += '\n耗材盘点batch已结束,可以开始盘点。';
            } else {
                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_consum.Id];
                text = '耗材盘点报告书编号:' + iheader.Name + '  耗材盘点地点:' + iheader.Internal_asset_location__c + '  耗材盘点开始日:' + iheader.Inventory_Start_Date__c;
                text += '\n开始盘点 处理失败。';
            }
        } catch (Exception e) {
            system.debug(e);
            this.emailMessages.add(e.getMessage());
        }
        ConsumInventoryStartAssetSnapshotBatch.messagesForTest = this.emailMessages;
        // 发 mail
        BatchEmailUtil be = new BatchEmailUtil();
        String[] toList = new String[]{UserInfo.getUserEmail()};
        String title = '开始耗材盘点';
        String[] ccList = new String[]{};
        for(String email : System.Label.Inventory_Result_Email.split(',')){
            ccList.add(email);
        }
        if(this.emailMessages.size() == 0 && totalCount == executedCount) {
            be.successMail(toList,ccList, title, totalCount, text);
        }else{
            String emailLabel = 'BatchNotify';
            for (OrgWideEmailAddress tmpEmailObj : [SELECT Id, Address, DisplayName
                    FROM OrgWideEmailAddress
                    WHERE DisplayName like :emailLabel]) {
                ccList.add(tmpEmailObj.Address);
            }
            if (totalCount != executedCount) {
                this.emailMessages.add('有一部分Batch没有运行, 请确认系统管理员。');
            }
            be.failedMail(toList, ccList, title,
                    String.join(this.emailMessages, '\n'),
                    totalCount, executedCount, failedCount);
        }
        be.send();
    }
    private void setMapObject(Consum_Inventory_Detail__c idetail, sObject obj, String typeStr) {
        List<String> fromCol;
        List<String> toCol;
        if (typeStr == 'Asset') {
            fromCol = new List<String>(assetFieldMap.keySet());
            toCol = assetFieldMap.values();
        //} else if (typeStr == 'Repair') {
        //    fromCol = new List<String>(repairFieldMap.keySet());
        //    toCol = repairFieldMap.values();
        } else {
            fromCol = new List<String>(raesdFieldMap.keySet());
            toCol = raesdFieldMap.values();
        }
 
        for (Integer i = 0; i < fromCol.size(); i++) {
            List<String> cols = fromCol[i].split('\\.');
            idetail.put(toCol[i], CreateRelationListPagingCmpCtrl.getObjectValue(obj, cols));
        }
    }
}