public with sharing class TransferAgencyReceivedController {
    public List<EsdInfo> esdList { get; set; }
    public String apply_no { get; private set; }
    public Boolean done_flg { get; set; }
    private String taId;
    public Boolean readOnly { get;  set; }
    public FixtureDeliverySlip__c slip { get; set; }
    public List<LabelValue> outputFieldList {get; set;}
    public Boolean forceSave { get; set; }
    public Boolean needforceSave { get; set; }
    public Boolean canReturn { get; set; }
    private final static String DELIMITER = '#';

    public TransferAgencyReceivedController() {
        taId = ApexPages.currentPage().getParameters().get('id');
        outputFieldList = setFieldSet('TransferApplyDetail__c', 'TransferAgencyReceived');
        forceSave = false;
        needforceSave = false;
        canReturn = false;
    }
    public PageReference init() {
        esdList = new List<EsdInfo>();
        done_flg = false;
        String jsonStr;

        if (taId != null) {
            readOnly = false;
            List<TransferApplyDetail__c> eList = getDetails();
            if (eList.size() > 0) {
                //20210111 ljh add start
                Map<String,Boolean> rsMap = new  Map<String,Boolean>();
                for (TransferApplyDetail__c tadd : eList) {
                    Boolean isonetoone = tadd.OneToOneAccessory__c || tadd.Main_OneToOne__c;
                    if (isonetoone) {
                        //有NG或者主机欠品
                        if(rsMap.containsKey(tadd.TransferApplySummary__c) &&  !rsMap.get(tadd.TransferApplySummary__c)) {
                            //满足条件更新值
                            if((String.isNotBlank(tadd.TransferApplySummary__r.First_TAD__r.ArrivalResult__c) && tadd.TransferApplySummary__r.First_TAD__r.ArrivalResult__c == '欠品' && tadd.TransferApplySummary__r.First_TAD__r.Main_OneToOne__c)
                                ||(String.isNotBlank(tadd.ArrivalResult__c) && tadd.ArrivalResult__c == 'NG' && (tadd.TransferApplySummary__r.First_TAD__r.Main_OneToOne__c || tadd.TransferApplySummary__r.First_TAD__r.OneToOneAccessory__c))){
                                rsMap.put(tadd.TransferApplySummary__c,true);
                            }
                        }else{
                            if(!rsMap.containsKey(tadd.TransferApplySummary__c)){
                                //新加入
                                Boolean tempVal;
                                if((String.isNotBlank(tadd.TransferApplySummary__r.First_TAD__r.ArrivalResult__c)&& tadd.TransferApplySummary__r.First_TAD__r.ArrivalResult__c == '欠品')
                                    ||(String.isNotBlank(tadd.ArrivalResult__c) && tadd.ArrivalResult__c == 'NG')){
                                    tempVal = true;
                                }else{
                                    tempVal = false;
                                }
                                rsMap.put(tadd.TransferApplySummary__c, tempVal);
                            }
                        }
                    }
                    else {
                        rsMap.put(tadd.TransferApplySummary__c,false);
                    }
                }
                //20210111 ljh add end
                Boolean need = true;
                Id rsId;
                for (TransferApplyDetail__c tad : eList) {
                    if (rsId != tad.TransferApplySummary__c) {
                        need = need == false;
                    }
                    if(tad.TransferApply__r.Shipment_Slip_tmp__c != null && jsonStr == null) {
                        jsonStr = tad.TransferApply__r.Shipment_Slip_tmp__c;
                    }
                    if(String.isBlank(apply_no)) {
                        apply_no = tad.TransferApply__r.Name;
                    }
                    if (tad.TransferApply__r.Yi_loaner_arranged__c == 0 || tad.TransferApply__r.ShelfUp_ng_num__c == 0) {
                        readOnly = true;
                    }
                    EsdInfo ei = new EsdInfo(tad);
                    ei.needColor = need;
                    ei.canReturn = rsMap.get(tad.TransferApplySummary__c);//20210111 ljh add
                    esdList.add(ei);
                    rsId = tad.TransferApplySummary__c;
                }
            }
            else {
                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '没有调拨明细！'));
                return null;
            }
        }
        if (jsonStr != null) {
            try {
                slip = (FixtureDeliverySlip__c)JSON.deserialize(jsonStr, FixtureDeliverySlip__c.class);
            } catch (Exception ex) {
                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, ex.getMessage()));
                if (slip == null) {
                    slip = new FixtureDeliverySlip__c();
                }
            }
        }
        else {
            if (slip == null) {
                slip = new FixtureDeliverySlip__c();
            }
        }
        if (slip.Wh_Staff__c == null) {
            slip.Wh_Staff__c = Userinfo.getUserId();
        }
        slip.IsForTransfer__c = true;

        return null;
    }
    private List<LabelValue> setFieldSet(String objApi, String fieldSetApi) {
        List<LabelValue> lvList = new List<LabelValue>();
        Map<String, Schema.FieldSet> fsMap = Schema.getGlobalDescribe().get(objApi).getDescribe().fieldSets.getMap();
        Schema.FieldSet fs = fsMap.get(fieldSetApi);
        List<FieldSetMember> fsmList = fs.getFields();

        for (FieldSetMember fsm : fsmList) {
            lvList.add(new LabelValue(fsm.getLabel(), fsm.getFieldPath()));
        }
        return lvList;
    }
    // 保存物流信息按钮
    public PageReference saveSlip() {
        done_flg = false;
        if(readOnly) return null;
        Savepoint sp = Database.setSavepoint();
        Boolean needroll = false;
        try {
            Set<Id> tsIdSet = new Set<Id>();
            Boolean haveError = false;
            List<TransferApplyDetail__c> tadList = new List<TransferApplyDetail__c>();
            List<EsdInfo> infoList = new List<EsdInfo>();

            Set<Id> ngSet = new Set<Id>();
            Set<Id> lostSet = new Set<Id>();
            for (EsdInfo main : esdList) {
                Boolean isonetoone = main.rec.OneToOneAccessory__c || main.rec.Main_OneToOne__c;
                if ((isonetoone || (main.rec.OneToOneAccessory__c == false && main.rec.Main_OneToOne__c == false)) && main.rec.ArrivalResult__c == 'NG') {
                    ngSet.add(main.rec.TransferApplySummary__c);
                }
                else if (isonetoone && main.rec.ArrivalResult__c == '欠品' && main.rec.Main_OneToOne__c) {
                    lostSet.add(main.rec.TransferApplySummary__c);
                }
                if (main.checked) {
                    tsIdSet.add(main.rec.TransferApplySummary__c);
                }
            }

            for (EsdInfo main : esdList) {
                Boolean isonetoone = main.rec.OneToOneAccessory__c || main.rec.Main_OneToOne__c;
                if (main.checked) {
                    if (ngSet.contains(main.rec.TransferApplySummary__c) == false && lostSet.contains(main.rec.TransferApplySummary__c) == false) {
                        ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, main.rec.SerialNumber_F__c + '只有主体欠品或者附属品NG的一览才可以回寄'));
                        haveError = true;
                        continue;
                    }
                    else if (isonetoone == false && main.rec.ArrivalResult__c == 'OK') {
                        ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, main.rec.SerialNumber_F__c + '只有主体欠品或者附属品NG的一览才可以回寄'));
                        haveError = true;
                        continue;
                    }
                    else {
                        tadList.add(main.rec);
                        infoList.add(main);
                    }
                }
                else if (isonetoone && tsIdSet.contains(main.rec.TransferApplySummary__c) && (ngSet.contains(main.rec.TransferApplySummary__c) || lostSet.contains(main.rec.TransferApplySummary__c))) {
                    ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, main.rec.SerialNumber_F__c + '【需整套回寄】'));
                    haveError = true;
                }
            }
            if (haveError == false) {
                if (tadList.size() == 0) {
                    ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '请选择要回寄的明细'));
                    return null;
                }
                if (slip.Id != null) {
                    slip = [
                        SELECT Combine_Pack__c, Name, Id, DeliveryCompany_SlipNo__c,DeliveryType__c,Distributor_method__c,DeliveryCompany__c,Wh_Staff__c, Wh_Staff__r.Name
                          FROM FixtureDeliverySlip__c
                         WHERE Id =:slip.Id
                           FOR UPDATE
                    ];
                }
                Map<Id, TransferApplyDetail__c> tadMap = new Map<Id, TransferApplyDetail__c>([SELECT Id
                                                             , Inspection_result_after_ng__c
                                                             , Lost_item_check_staff__c
                                                          FROM TransferApplyDetail__c
                                                         WHERE Id = :tadList
                                                           AND (Inspection_result_after_ng__c != null
                                                            OR Lost_item_check_staff__c != null)
                                                           AND Return_DeliverySlip__c != null]);

                tadList = new List<TransferApplyDetail__c>();
                if (tadMap.isEmpty()) {
                    slip.Shippment_loaner_time__c = Datetime.now();
                    needroll = String.isBlank(slip.Id);
                    FixtureUtil.withoutUpsertObjects(new List<FixtureDeliverySlip__c>{ slip });
                }
                for (EsdInfo main : infoList) {
                    if (tadMap.isEmpty()) {
                        main.rec.Inspection_result_after_ng__c = null;
                        main.rec.Inspection_result_after_NG_Final__c = null;
                        main.rec.After_Inspection_time__c = null;
                        main.rec.After_Inspection_time_Final__c = null;
                        main.rec.Inspection_result_after__c = null;
                        main.rec.Inspection_result_after_Final__c = null;
                        main.rec.Return_DeliverySlip__c = slip.Id;
                        main.rec.Asset_return_time__c = Datetime.now();
                        main.rec.Lost_item_check_staff__c = null;
                        main.rec.Lost_item_check_staff_Final__c = null;
                        main.rec.Lost_item_check_time__c = null;
                        main.rec.Check_lost_Item__c = null;
                        main.rec.Check_lost_Item_Final__c = null;
                        main.rec.CDS_complete__c = false;
                        main.rec.Lost_item_check_time_Final__c = null;
                        main.editable = false;
                        tadList.add(main.rec);
                    }
                    else if (tadMap.containsKey(main.rec.Id)) {
                        main.errorInfo = '明细已经做了收货确认,无法回寄,请刷新画面重试';
                        ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, main.rec.SerialNumber_F__c + '明细已经做了收货确认,无法回寄,请刷新画面重试'));
                    }
                }
                if (tadList.size() > 0) {
                    FixtureUtil.withoutUpdate(tadList);
                    ApexPages.addmessage(new ApexPages.message(ApexPages.severity.CONFIRM, '已回寄'));
                    return init();
                }
                else {
                    return init();
                }
            }
        }
        catch (Exception ex) {
            String msg = ex.getMessage();
            if (msg != null && msg.contains('DUPLICATE_VALUE') && msg.contains('DeliveryCompany_SlipNo__c')) {
                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '系统已存在相同的运输单。如果继续使用该运输单回寄，请输入运输单号检索，检索后再勾选配套回寄。'));
            } else {
                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, msg));
            }
            Database.rollback(sp);
            done_flg = false;
            if (needroll) {
                slip.Id = null;
            }
        }
        return null;
    }
    private List<TransferApplyDetail__c> getDetails() {
        List<TransferApplyDetail__c> eList = [
                select SerialNumber_F__c, OneToOneAccessory__c, Main_OneToOne__c, TransferApplySummary__c
                        , Internal_Asset_number_key__c, Fixture_Model_No_F__c, TAESD_Status__c
                        , TransferApply__c, Shippment_loaner_time__c
                        , TransferApply__r.Shipment_Slip_tmp__c
                        , TransferApply__r.Yi_loaner_arranged__c
                        , TransferApply__r.Name
                        , Fixture_Model_No__c
                        , SerialNumber__c
                        , Detail_Finish__c
                        , Inspection_result_after_F__c
                        , Loaner_asset_no__c
                        , ArrivalResult__c
                        , Arrival_wh_Abandoned_Flag_F__c
                        , Internal_asset_location_After__c
                        , Salesdepartment_After__c
                        , Return_DeliverySlip__c
                        , Asset_return_time__c
                        , Arrival_wh_Flag_F__c
                        , FSD_OneToOneAccessory_Cnt_F__c
                        , Cancel_Select__c
                        , TransferApply__r.ShelfUp_ng_num__c
                        , Asset__r.Product2.Name
                        , LastModifiedDate
                        , OneToOneAsset__c
                        , First_You_Xiao_Ku_Cun__c
                        , TransferApplySummary__r.First_TAD__r.Loaner_accsessary__c
                        , TransferApplySummary__r.First_TAD__r.ArrivalResult__c
                        , TransferApplySummary__r.First_TAD__r.Lost_item_giveup__c
                        , TransferApplySummary__r.First_TAD__r.Arrival_in_wh__c
                        , TransferApplySummary__r.First_TAD__r.Main_OneToOne__c
                        , TransferApplySummary__r.First_TAD__r.OneToOneAccessory__c
                        , Approved_F__c, Fixture_Name_F__c, TransferApplySummary__r.Fixture_Set__r.Name
                        , Fixture_QRCode_F__c, TransferApplySummary__r.Name, Pre_inspection_time__c, StockDown__c
                        , StockDown_time__c, Id, Name, Asset__c, Asset__r.Name, Asset__r.SerialNumber, Asset__r.Product_Serial_No__c,
                       Asset__r.Remark__c, Asset__r.ImageAsset__c, Asset__r.ImageSerial__c, Asset__r.ImageAssetUploadedTime__c, Asset__r.ImageSerialUploadedTime__c,
                       Loaner_CDS_Info__c, Inspection_result__c, Check_lost_Item__c, Pre_disinfection__c, Water_leacage_check__c, Inspection_result_after__c, Arrival_in_wh__c,
                       Asset__r.Pre_Reserve_TAES_Detail__c, Asset__r.Pre_Reserve_TAES_Detail__r.After_Inspection_time__c,
                       Inspection_result_after_ng__c, Inspection_result_ng__c, Lost_item_giveup__c, CDS_complete__c, Loaner_accsessary__c,Arrival_NG_Comment__c  //20210423 ljh 1832 add Arrival_NG_Comment__c
                  from TransferApplyDetail__c
                 where TransferApply__c = :taId
                   AND Cancel_Select__c = False
                 //order by TransferApplySummary__c, Is_First_TAD_F__c DESC, TransferApplySummary__r.Name, IndexFromUniqueKey__c
                 order by TransferApplySummary__r.Name, TransferApplySummary__c,Name
        ];
        return eList;
    }
    // // 下架按钮
    // public PageReference stockup() {

    //     done_flg = false;
    //     needforceSave = false;
    //     String userid = Userinfo.getUserId();
    //     List<TransferApplyDetail__c> eList = new List<TransferApplyDetail__c>();
    //     List<EsdInfo> otoCheckList_main = new List<EsdInfo>();
    //     List<EsdInfo> otoAccessoryList = new List<EsdInfo>();
    //     Set<Id> assetForLock = new Set<Id>();
    //     Set<String> ukeySet = new Set<String>();
    //     Boolean haveCheck = false;
    //     Boolean haveError = false;
    //     List<EsdInfo> newOneToOne = new List<EsdInfo>();
    //     for (EsdInfo esdInfo : esdList) {
    //         if (esdInfo.checked) {
    //             haveCheck = true;
    //             esdInfo.errorInfo = null;
    //             if (esdInfo.needsetone && String.isBlank(esdInfo.rec.OneToOneAsset__c) && esdInfo.rec.Arrival_in_wh__c) {
    //                 ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, esdInfo.rec.Asset__r.Product2.Name + ':上架需要设置一对一主体'));
    //                 haveError = true;
    //             }

    //             if (esdInfo.accessoryFlg) {
    //                 otoAccessoryList.add(esdInfo);
    //             } else {
    //                 if (!esdInfo.editable) continue;
    //                 TransferApplyDetail__c esd = esdInfo.rec;
    //                 eList.add(esd);
    //                 if (esd.Arrival_in_wh__c) {
    //                     if (esd.FSD_OneToOneAccessory_Cnt_F__c > 0 && esd.Main_OneToOne__c && (esd.ArrivalResult__c == 'OK' || (!esd.Arrival_wh_Abandoned_Flag_F__c && esd.Arrival_wh_Flag_F__c))) {
    //                         otoCheckList_main.add(esdInfo);
    //                     } else if ((esd.ArrivalResult__c == 'OK' || (!esd.Arrival_wh_Abandoned_Flag_F__c && esd.Arrival_wh_Flag_F__c)) && esd.FSD_OneToOneAccessory_Cnt_F__c > 0 && esd.Fixture_Set_Detail__r.Is_OneToOne__c) {
    //                         otoAccessoryList.add(esdInfo);
    //                     }
    //                     String ukey =  esd.Fixture_Model_No_F__c // 型号;存放地;本部
    //                             + ';' + esd.Internal_asset_location_After__c
    //                             + ';' + esd.Salesdepartment_After__c;
    //                     ukeySet.add(ukey);
    //                 }
    //             }
    //             if (esdInfo.editable) {
    //                 assetForLock.add(esdInfo.rec.Asset__c);
    //             }
    //         }
    //     }

    //     if (haveCheck == false) {
    //         ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '请勾选需要操作的明细'));
    //         return null;
    //     }
    //     else if (haveError) {
    //         return null;
    //     }

    //     Map<String, Map<Id, List<Id>>> assProductCountMapAll = new Map<String, Map<Id, List<Id>>>(); // 一览Id->产品Id->保有设备Id列表
    //     for (EsdInfo ei : otoAccessoryList) {
    //         Map<Id, List<Id>> assProductCountMap;
    //         if (assProductCountMapAll.containsKey(ei.accessorySetId)) {
    //             assProductCountMap = assProductCountMapAll.get(ei.accessorySetId);
    //         } else {
    //             assProductCountMap = new Map<Id, List<Id>>();
    //         }
    //         Id recId;
    //         Id product2Id;
    //         if (ei.rec2 != null) {
    //             recId = ei.rec2.Id;
    //             product2Id = ei.rec2.Product2Id;
    //         } else {
    //             recId = ei.rec.Asset__c;
    //             product2Id = ei.rec.Asset__r.Product2Id;
    //         }
    //         List<Id> count;
    //         if (assProductCountMap.containsKey(product2Id)) {
    //             count = assProductCountMap.get(product2Id);
    //         } else {
    //             count = new List<Id>();
    //         }
    //         count.add(recId);
    //         assProductCountMap.put(product2Id, count);
    //         assProductCountMapAll.put(ei.accessorySetId, assProductCountMap);
    //     }

    //     Boolean needSaveSet = false;
    //     Boolean needSaveDetail = false;
    //     Boolean needSaveAsset = false;

    //     List<Fixture_OneToOne_Link__c> otolinkList = new List<Fixture_OneToOne_Link__c>();
    //     boolean err = false;
    //     Map<String, Integer> otoMap = new Map<String, Integer>();
    //     for (EsdInfo main : otoCheckList_main) {
    //         List<TransferApplyDetail__c> tadList;
    //         //没有cancel的看最新一套明细的fsd数量
    //         //已经cancel的看最早一套明细的一对一分配数量
    //         //理论上出库前上架的数据不会有非cancel的情况，所以直接用Cancel_Select__c判断
    //         system.debug(main.rec);
    //         if (main.rec.Cancel_Select__c == false) {
    //             tadList = [select Asset__r.Product2.Name, Asset__c, Asset__r.Product2Id , OneToOneAccessory__c
    //                         from TransferApplyDetail__c
    //                        where TransferApplySummary__c = :main.rec.TransferApplySummary__c
    //                              and OneToOneAccessory__c = true
    //                              and Cancel_Select__c = false //找最新的一套明细
    //                              //and Canceled_Id__c = null //找最初的一套明细
    //                              and Asset__c <> null //过滤未分配的数据。
    //                              order by OneToOneAccessory__c desc];
    //         } else {
    //             tadList = [select Asset__r.Product2.Name, Asset__c, Asset__r.Product2Id , OneToOneAccessory__c
    //                         from TransferApplyDetail__c
    //                        where TransferApplySummary__c = :main.rec.TransferApplySummary__c
    //                              and OneToOneAccessory__c = true
    //                              //and Canceled_Id__c = null
    //                              and Asset__c <> null
    //                              order by OneToOneAccessory__c desc];
    //         }
    //         system.debug(tadList);
    //         Map<Id, List<Id>> assProductCountMap = new Map<Id, List<Id>>();
    //         if (assProductCountMapAll.containsKey(main.rec.TransferApplySummary__c)) {
    //             assProductCountMap = assProductCountMapAll.get(main.rec.TransferApplySummary__c);
    //         }

    //         for (TransferApplyDetail__c tad : tadList) {
    //             if (assProductCountMap.containsKey(tad.Asset__r.Product2Id) && assProductCountMap.get(tad.Asset__r.Product2Id).size() > 0) {

    //                 List<Id> count = assProductCountMap.get(tad.Asset__r.Product2Id);
    //                 String assetId = (String)count[0];
    //                 count.remove(0);
    //                 assProductCountMap.put(tad.Asset__r.Product2Id, count);
    //                 assProductCountMapAll.put(main.rec.TransferApplySummary__c, assProductCountMap);

    //                 String key = (String)main.rec.Asset__c + ':' + assetId;
    //                 Integer otoCnt;
    //                 if (otoMap.containsKey(key)) {
    //                     otoCnt = otoMap.get(key);
    //                 } else {
    //                     otoCnt = 0;
    //                 }
    //                 otoMap.put(key, otoCnt + 1);
    //             } else {
    //                 if (!forceSave && (main.rec.Cancel_Select__c == false || (main.rec.Cancel_Select__c == true && tad.OneToOneAccessory__c))) {
    //                     main.errorInfo = '未补全附属品:'+tad.Asset__r.Product2.Name;
    //                     ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, main.rec.SerialNumber_F__c + '未补全附属品:'+tad.Asset__r.Product2.Name));
    //                     err = true;
    //                     needforceSave = true;
    //                     break;
    //                 } else {
    //                     continue;
    //                 }
    //             }
    //         }
    //     }

    //     forceSave = false;
    //     if (err) return null;

    //     for (String oto : otoMap.keySet()) {
    //         List<String> keys = oto.split(':');
    //         Fixture_OneToOne_Link__c otolink = new Fixture_OneToOne_Link__c();
    //         otolink.Main_Asset__c = keys[0];
    //         otolink.Accessory_Asset__c = keys[1];
    //         otolink.Quantity__c = otoMap.get(oto);
    //         otolinkList.add(otolink);
    //     }

    //     // TODO 没变化不存
    //     // if (Step_status == '上架') {

    //         for (TransferApplyDetail__c esd : eList) {
    //             if (esd.Arrival_in_wh__c) {
    //                 esd.Arrival_wh_time__c = System.now();
    //                 esd.Return_wh_chenk_staff__c = userid;
    //             } else {
    //                 esd.Arrival_wh_time__c = null;
    //                 esd.Return_wh_chenk_staff__c = null;
    //             }
    //         }
    //         needSaveDetail = true;
    //     // }
    //     for (EsdInfo esdInfo : esdList) {
    //         if (esdInfo.accessoryFlg) continue;
    //         TransferApplyDetail__c esd = esdInfo.rec;
    //         if (esd.Arrival_in_wh__c && esd.FSD_OneToOneAccessory_Cnt_F__c > 0 && esd.Main_OneToOne__c && esd.Arrival_wh_Abandoned_Flag_F__c) {
    //             otoCheckList_main.add(esdInfo);
    //         }
    //     }
    //     String sqlStr = 'SELECT Id FROM Asset WHERE Id IN:assetForLock ';
    //     String sqlWhere = '';
    //     if(! ukeySet.isEmpty()) {
    //         for(String ukey: ukeySet) {
    //             // 型号;存放地;本部
    //             List<String> fields = ukey.split(';');
    //             // 型号
    //             if (String.isNotBlank(fields[0]) && fields[0] != 'null') {
    //                 sqlWhere += ' (Fixture_Model_No_F__c =\'' + String.escapeSingleQuotes(fields[0]) + '\'';
    //             } else {
    //                 sqlWhere += ' (Fixture_Model_No_F__c = null';
    //             }
    //             // 备品存放地
    //             if (String.isNotBlank(fields[1]) && fields[1] != 'null') {
    //                 sqlWhere += ' AND Internal_asset_location__c =\'' + String.escapeSingleQuotes(fields[1]) + '\'';
    //             } else {
    //                 sqlWhere += ' AND Internal_asset_location__c = null';
    //             }
    //             // 本部
    //             if (String.isNotBlank(fields[2]) && fields[2] != 'null') {
    //                 sqlWhere += ' AND Salesdepartment__c =\'' + String.escapeSingleQuotes(fields[2]) + '\')';
    //             } else {
    //                 sqlWhere += ' AND Salesdepartment__c = null)';
    //             }

    //             sqlWhere += ' OR';
    //         }
    //         sqlWhere = sqlWhere.removeEnd('OR');
    //         sqlWhere = '((' + sqlWhere + ')';
    //         sqlWhere += ' AND Delete_Flag__c = false '
    //                 + ' AND Asset_Owner__c = \'Olympus\''
    //                 + ' AND AssetManageConfirm__c = true'
    //                 + ' AND Quantity > 0'
    //                 + ' AND Freeze_sign_Abandoned_Flag__c = False'
    //                 + ' AND Manage_type__c = \'数量管理\')';
    //         sqlStr += ' OR ' + sqlWhere ;
    //     }
    //     sqlStr += ' FOR UPDATE';
    //     List<Asset> astLock = Database.query(sqlStr);
    //     Savepoint sp = Database.setSavepoint();
    //     try {
    //         // 强制删废弃主体的一对一link
    //         if (otoCheckList_main.size() > 0) {
    //             List<Id> mainIds = new List<Id>();
    //             for (EsdInfo oto : otoCheckList_main) {
    //                 if (String.isNotBlank(oto.rec.Asset__c)) {
    //                     // Asset__c 念のための確認
    //                     mainIds.add(oto.rec.Asset__c);
    //                 }
    //             }
    //             FixtureUtil.delOtOLinkData(mainIds);
    //         }

    //         if (otolinkList.size() > 0) {
    //             // TODO 只对现场追加的一对一附属品建link
    //             if (needSaveDetail) {
    //                 FixtureUtil.withoutUpsertObjects(otolinkList);
    //                 needSaveDetail = false;
    //             }
    //         }
    //         // 这里只更新明细，保有设备和link都放到trigger里更新
    //         if (needSaveDetail) FixtureUtil.withoutUpsertObjects(eList);

    //         List<EsdInfo> esdL = new List<EsdInfo>();
    //         for (EsdInfo esd : esdList) {
    //             if (!esd.accessoryFlg) {
    //                 esdL.add(esd);
    //             }
    //         }
    //         init();
    //         done_flg = true;
    //     } catch (Exception ex) {
    //         system.debug('=====' + ex.getMessage());
    //         ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, ex.getMessage()+'(回库)'));
    //         Database.rollback(sp);
    //         done_flg = false;
    //     }

    //     return null;
    // }

    public PageReference cdsSave() {
        Set<Id> rndIdSet = new Set<Id>();
        Boolean haveError = false;
        done_flg = false;
        for (EsdInfo main : esdList) {
            if (main.checked) {
                rndIdSet.add(main.rec.Id);
            }
            //20210426 ljh add 1832 start
            if(String.isBlank(main.rec.ArrivalResult__c) || main.rec.ArrivalResult__c != 'NG'){
                system.debug('111:Arrival_NG_Comment__c'+main.rec.Arrival_NG_Comment__c);
                main.rec.Arrival_NG_Comment__c = '';
            }
            //20210426 ljh add 1832 start
        }
        Map<Id, TransferApplyDetail__c> tadMap = new Map<Id, TransferApplyDetail__c>();
        for (TransferApplyDetail__c tad : getTad(rndIdSet)) {
            tadMap.put(tad.Id, tad);
            if (tad.Arrival_in_wh__c) {
                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, tad.SerialNumber_F__c + ':已经回库的明细不可以做到货确认&CDS操作'));
                haveError = true;
            }
            else if (tad.Lost_item_giveup__c) {
                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, tad.SerialNumber_F__c + ':已经欠品放弃的明细不可以做到货确认&CDS操作'));
                haveError = true;
            }
        }

        for (EsdInfo main : esdList) {
            if (main.checked) {
                if (main.rec.LastModifiedDate != tadMap.get(main.rec.Id).LastModifiedDate) {
                    ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, main.rec.SerialNumber_F__c + ':已经被修改,请刷新画面重试'));
                    haveError = true;
                }
                if (String.isBlank(main.rec.ArrivalResult__c)) {
                    ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, main.rec.SerialNumber_F__c + ':您点击的按钮与当前操作不符'));
                    haveError = true;
                }
                else if (main.rec.Arrival_in_wh__c) {
                    ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, main.rec.SerialNumber_F__c + ':您点击的按钮与当前操作不符'));
                    haveError = true;
                }
                //20210426 ljh add 1832 start
                system.debug('Arrival_NG_Comment__c'+main.rec.Arrival_NG_Comment__c);
                if (main.rec.ArrivalResult__c != null && main.rec.ArrivalResult__c == 'NG' && String.isBlank(main.rec.Arrival_NG_Comment__c)) {
                    ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, main.rec.SerialNumber_F__c + ':调拨到货确认结果NG，到货NG结果备注必须填写！'));
                    haveError = true;
                }
                //20210426 ljh add 1832 end
            }
        }
        if (haveError == false) {
            return saveRecord();
        }
        else {
            return null;
        }
    }

    public PageReference arrival_in_whSave() {
        Set<Id> rndIdSet = new Set<Id>();
        Set<Id> allrndIdSet = new Set<Id>();
        Boolean haveError = false;
        done_flg = false;
        for (EsdInfo main : esdList) {
            if (main.checked) {
                rndIdSet.add(main.rec.Id);
                allrndIdSet.add(main.rec.TransferApplySummary__c);
            }
        }
        Map<Id, TransferApplyDetail__c> tadMap = new Map<Id, TransferApplyDetail__c>();
        for (TransferApplyDetail__c tad : getTad(allrndIdSet)) {
            if (rndIdSet.contains(tad.Id)) {
                tadMap.put(tad.Id, tad);
                if (tad.ArrivalResult__c != 'OK') {
                    ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, tad.SerialNumber_F__c + ':到货确认不是OK不能回库'));
                    haveError = true;
                }
                else if (tad.CDS_complete__c == false) {
                    ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, tad.SerialNumber_F__c + ':没有做CDS保存不能回库'));
                    haveError = true;
                }
                else if (tad.Lost_item_giveup__c) {
                    ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, tad.SerialNumber_F__c + ':已经欠品放弃的明细不能回库'));
                    haveError = true;
                }
                else if (tad.Arrival_in_wh__c) {
                    ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, tad.SerialNumber_F__c + ':已经回库的明细不能再回库'));
                    haveError = true;
                }
            }
            else if (tad.ArrivalResult__c != '欠品' && tad.Cancel_Select__c == false
                && (tad.Main_OneToOne__c || tad.OneToOneAccessory__c)
                && !tad.Detail_Finish__c
                && tad.TransferApplySummary__r.First_TAD__r.Arrival_in_wh__c == false
            ) {
                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, tad.SerialNumber_F__c + ':回库时必须整套回库'));
                haveError = true;
            }
        }

        for (EsdInfo main : esdList) {
            if (main.checked) {
                if (main.rec.LastModifiedDate != tadMap.get(main.rec.Id).LastModifiedDate) {
                    ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, main.rec.SerialNumber_F__c + ':已经被修改,请刷新画面重试'));
                    haveError = true;
                }
                if (main.rec.ArrivalResult__c != 'OK') {
                    ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, main.rec.SerialNumber_F__c + ':您点击的按钮与当前操作不符'));
                    haveError = true;
                }
                else if (main.rec.CDS_complete__c == false) {
                    ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, main.rec.SerialNumber_F__c + ':您点击的按钮与当前操作不符'));
                    haveError = true;
                }
                else if (main.rec.Arrival_in_wh__c == false) {
                    ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, main.rec.SerialNumber_F__c + ':您点击的按钮与当前操作不符'));
                    haveError = true;
                }
            }
        }

        if (haveError == false) {
            return saveRecord();
        }
        else {
            return null;
        }
    }

    private List<TransferApplyDetail__c> getTad(Set<Id> rndIdSet) {
        return [select SerialNumber_F__c, OneToOneAccessory__c, Main_OneToOne__c, TransferApplySummary__c
                    , Internal_Asset_number_key__c, Fixture_Model_No_F__c, TAESD_Status__c
                    , TransferApply__c, Shippment_loaner_time__c
                    , TransferApply__r.Shipment_Slip_tmp__c
                    , TransferApply__r.Yi_loaner_arranged__c
                    , TransferApply__r.Name
                    , Fixture_Model_No__c
                    , SerialNumber__c
                    , Detail_Finish__c
                    , Inspection_result_after_F__c
                    , Loaner_asset_no__c
                    , ArrivalResult__c
                    , Arrival_wh_Abandoned_Flag_F__c
                    , Internal_asset_location_After__c
                    , Salesdepartment_After__c
                    , Return_DeliverySlip__c
                    , Asset_return_time__c
                    , Arrival_wh_Flag_F__c
                    , FSD_OneToOneAccessory_Cnt_F__c
                    , Cancel_Select__c
                    , TransferApply__r.ShelfUp_ng_num__c
                    , Asset__r.Product2.Name
                    , LastModifiedDate
                    , OneToOneAsset__c
                    , Approved_F__c, Fixture_Name_F__c, TransferApplySummary__r.Fixture_Set__r.Name
                    , Fixture_QRCode_F__c, TransferApplySummary__r.Name, Pre_inspection_time__c, StockDown__c
                    , TransferApplySummary__r.First_TAD__r.Loaner_accsessary__c
                    , First_You_Xiao_Ku_Cun__c
                    , TransferApplySummary__r.First_TAD__r.ArrivalResult__c
                    , TransferApplySummary__r.First_TAD__r.Lost_item_giveup__c
                    , TransferApplySummary__r.First_TAD__r.Arrival_in_wh__c
                    , TransferApplySummary__r.First_TAD__r.Main_OneToOne__c
                    , TransferApplySummary__r.First_TAD__r.OneToOneAccessory__c
                    , StockDown_time__c, Id, Name, Asset__c, Asset__r.Name, Asset__r.SerialNumber, Asset__r.Product_Serial_No__c,
                   Asset__r.Remark__c, Asset__r.ImageAsset__c, Asset__r.ImageSerial__c, Asset__r.ImageAssetUploadedTime__c, Asset__r.ImageSerialUploadedTime__c,
                   Loaner_CDS_Info__c, Inspection_result__c, Check_lost_Item__c, Pre_disinfection__c, Water_leacage_check__c, Inspection_result_after__c, Arrival_in_wh__c,
                   Asset__r.Pre_Reserve_TAES_Detail__c, Asset__r.Pre_Reserve_TAES_Detail__r.After_Inspection_time__c,
                   Inspection_result_after_ng__c, Inspection_result_ng__c, Lost_item_giveup__c, CDS_complete__c, Loaner_accsessary__c,Arrival_NG_Comment__c //20210426 ljh 1832 add Arrival_NG_Comment__c
              from TransferApplyDetail__c
             where Id = :rndIdSet OR TransferApplySummary__c = :rndIdSet FOR UPDATE];
    }


    // 保存按钮
    public PageReference saveRecord() {
        done_flg = false;
        needforceSave = false;
        String userid = Userinfo.getUserId();
        List<TransferApplyDetail__c> eList = new List<TransferApplyDetail__c>();
        List<EsdInfo> otoCheckList_main = new List<EsdInfo>();
        List<EsdInfo> otoAccessoryList = new List<EsdInfo>();
        Set<Id> assetForLock = new Set<Id>();
        Set<String> ukeySet = new Set<String>();
        Boolean haveError = false;
        Boolean haveCheck = false;

        List<EsdInfo> otoList = new List<EsdInfo>();
        Map<Id, List<EsdInfo>> checkMap = new Map<Id, List<EsdInfo>>();
        Set<Id> ngSet = new Set<Id>();
        Set<Id> lostSet = new Set<Id>();
        for (EsdInfo main : esdList) {
            if ((main.rec.OneToOneAccessory__c || main.rec.Main_OneToOne__c)
                && (main.rec.TransferApplySummary__r.First_TAD__r.Arrival_in_wh__c == false
                    && main.rec.TransferApplySummary__r.First_TAD__r.Loaner_accsessary__c == false
                    && main.rec.TransferApplySummary__r.First_TAD__r.Lost_item_giveup__c == false)
            ) {
                if (main.rec.ArrivalResult__c == 'NG') {
                    ngSet.add(main.rec.TransferApplySummary__c);
                }
                else if (main.rec.ArrivalResult__c == '欠品' && main.rec.Main_OneToOne__c) {
                    lostSet.add(main.rec.TransferApplySummary__c);
                }
            }
        }

        Id tsid;

        EsdInfo info;
        for (EsdInfo esdInfo : esdList) {
            tsid = esdInfo.rec.TransferApplySummary__c;
            if (esdInfo.checked) {
                if (esdInfo.rec.Main_OneToOne__c) {
                    info = esdInfo;
                }
                else if (esdInfo.rec.Main_OneToOne__c == false && esdInfo.rec.OneToOneAccessory__c == false) {
                    info = null;
                }

                haveCheck = true;
                esdInfo.errorInfo = null;
                if (esdInfo.needsetone && String.isBlank(esdInfo.rec.OneToOneAsset__c) && esdInfo.rec.Arrival_in_wh__c) {
                    ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, esdInfo.rec.SerialNumber_F__c + ':上架需要设置一对一主体'));
                    haveError = true;
                }
                if (esdInfo.rec.OneToOneAccessory__c
                    && esdInfo.rec.TransferApplySummary__r.First_TAD__r.Arrival_in_wh__c
                    && esdInfo.rec.First_You_Xiao_Ku_Cun__c == 0) {
                    esdInfo.rec.SkipLink__c = true;
                    continue;
                }
                else if (esdInfo.accessoryFlg) {
                    otoAccessoryList.add(esdInfo);
                } else {
                    if (!esdInfo.editable) continue;
                    TransferApplyDetail__c esd = esdInfo.rec;
                    eList.add(esd);
                    // ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '1'));
                    if (esd.Arrival_in_wh__c) {
                        if (info == null && esd.ArrivalResult__c == 'NG') {
                            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '到货NG的附属品不能上架,请做回寄操作'));
                            haveError = true;
                        }
                        if (ngSet.contains(esdInfo.rec.TransferApplySummary__c)) {
                            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, esd.SerialNumber_F__c + ':有到货确认NG的一览不可以上架'));
                            haveError = true;
                        }
                        if (esd.Main_OneToOne__c && (esd.ArrivalResult__c == 'OK' || (!esd.Arrival_wh_Abandoned_Flag_F__c && esd.Arrival_wh_Flag_F__c))) {
                            otoCheckList_main.add(esdInfo);
                            // ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '3'));
                        } else if ((esd.ArrivalResult__c == 'OK' || (!esd.Arrival_wh_Abandoned_Flag_F__c && esd.Arrival_wh_Flag_F__c)) && esd.OneToOneAccessory__c) {
                            otoAccessoryList.add(esdInfo);
                            if (info == null && !forceSave && (esdInfo.rec.TransferApplySummary__r.First_TAD__r.Arrival_in_wh__c && esdInfo.rec.First_You_Xiao_Ku_Cun__c > 0) == false) {
                                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, esd.SerialNumber_F__c + ':未选择主体一对一主体'));
                                // needforceSave = true;
                                haveError = true;
                            }
                        }
                        String ukey =  esd.Fixture_Model_No_F__c // 型号;存放地;本部
                                + ';' + esd.Internal_asset_location_After__c
                                + ';' + esd.Salesdepartment_After__c;
                        ukeySet.add(ukey);
                    }
                }
                if (esdInfo.editable) {
                    assetForLock.add(esdInfo.rec.Asset__c);
                }
                if (String.isNotBlank(esdInfo.rec.OneToOneAsset__c) && esdInfo.needsetone && esdInfo.rec.Arrival_in_wh__c) {
                    if (checkMap.containsKey(esdInfo.rec.OneToOneAsset__c) == false) {
                        checkMap.put(esdInfo.rec.OneToOneAsset__c, new List<EsdInfo>());
                    }
                    checkMap.get(esdInfo.rec.OneToOneAsset__c).add(esdInfo);
                    otoList.add(esdInfo);
                }
            }
            else if (info != null && info.rec.Arrival_in_wh__c && info.rec.TransferApplySummary__c == esdInfo.rec.TransferApplySummary__c && esdInfo.rec.ArrivalResult__c != '欠品') {
                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, esdInfo.rec.SerialNumber_F__c + ':一对一非欠品的附属品必须统一上架'));
                haveError = true;
            }
        }

        if (haveCheck == false) {
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '请勾选需要操作的明细'));
            return null;
        }
        else if (haveError) {
            return null;
        }

        if (checkMap.isEmpty() == false) {
            // 20220211 ljh SFDC-CBH5GH update start
            /*for (Asset ass : [SELECT Id FROM ASSET WHERE Asset_Owner__c = 'Olympus'
                                          AND Asset_loaner_category__c != '耗材'
                                          AND RecordTypeId = '01210000000kOPR'
                                          AND Delete_Flag__c = False
                                          AND AssetManageConfirm__c = true
                                          // AND Account.Management_Code__c =:System.Label.Account_Asset
                                          AND Loaner_accsessary__c = false
                                          AND Freeze_sign_Abandoned_Flag__c = false
                                          AND Last_Reserve_RAES_Detail__c = null
                                          AND You_Xiao_Ku_Cun__c > 0
                                          AND Id = :checkMap.keySet()]) {
                checkMap.remove(ass.Id);
            }*/
            // 调拨至 的办事处
            String locationAfter = esdList[0].rec.Internal_asset_location_After__c;
            Map<Id, Asset> checkAssetMap = new Map<Id, Asset>();
            List<Asset> checkAssetList = [SELECT Id,Internal_asset_location__c FROM ASSET WHERE Asset_Owner__c = 'Olympus'
                                          AND Asset_loaner_category__c != '耗材'
                                          AND RecordTypeId = '01210000000kOPR'
                                          AND Delete_Flag__c = False
                                          AND AssetManageConfirm__c = true
                                          // AND Account.Management_Code__c =:System.Label.Account_Asset
                                          AND Loaner_accsessary__c = false
                                          AND Freeze_sign_Abandoned_Flag__c = false
                                          AND Last_Reserve_RAES_Detail__c = null
                                          AND You_Xiao_Ku_Cun__c > 0
                                          AND Internal_asset_location__c = :locationAfter
                                          AND Id = :checkMap.keySet()];
            for (Asset ass : checkAssetList) {
                checkMap.remove(ass.Id);
            }
            if (checkMap.isEmpty() == false) {
                checkAssetMap.putAll([SELECT Id,Internal_asset_location__c,SerialNumber,Fixture_Model_No_F__c FROM ASSET WHERE  Id = :checkMap.keySet()]);
                for (Id assId : checkMap.keySet()) {
                    for (EsdInfo esdInfo : checkMap.get(assId)) {
                        // esdInfo.errorInfo = '保有设备:'+esdInfo.rec.SerialNumber_F__c + '请选择合适的主体';
                        // ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '保有设备:'+esdInfo.rec.SerialNumber_F__c + '请选择合适的主体'));
                        // haveError = true;
                        Asset checkAsset = checkAssetMap.get(assId);
                        if(checkAsset != null && checkAsset.Internal_asset_location__c != locationAfter){
                            // esdInfo.errorInfo = '保有设备:'+esdInfo.rec.SerialNumber_F__c + '和主体备品存放地不一致，请选择合适的主体';
                            // ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '保有设备:'+esdInfo.rec.SerialNumber_F__c + '和主体备品存放地不一致，请选择合适的主体'));
                            esdInfo.errorInfo = '附属品 '+esdInfo.rec.Fixture_Model_No__c+'('+esdInfo.rec.SerialNumber_F__c + ')与主体 '+checkAsset.Fixture_Model_No_F__c+'('+checkAsset.SerialNumber+')备品存放地不一致，不能入库';
                            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '附属品 '+esdInfo.rec.Fixture_Model_No__c+'('+esdInfo.rec.SerialNumber_F__c + ')与主体 '+checkAsset.Fixture_Model_No_F__c+'('+checkAsset.SerialNumber+')备品存放地不一致，不能入库'));
                            haveError = true;
                        }else{
                            esdInfo.errorInfo = '保有设备:'+esdInfo.rec.SerialNumber_F__c + '请选择合适的主体';
                            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '保有设备:'+esdInfo.rec.SerialNumber_F__c + '请选择合适的主体'));
                            haveError = true;
                        }
                        // 20220211 ljh SFDC-CBH5GH update end
                    }
                }
            }
            // 20220211 ljh SFDC-CBH5GH update end
        }

        if (haveError) {
            return null;
        }

        Map<String, Map<Id, List<Id>>> assProductCountMapAll = new Map<String, Map<Id, List<Id>>>(); // 一览Id->产品Id->保有设备Id列表
        for (EsdInfo ei : otoAccessoryList) {
            Map<Id, List<Id>> assProductCountMap;
            if (assProductCountMapAll.containsKey(ei.accessorySetId)) {
                assProductCountMap = assProductCountMapAll.get(ei.accessorySetId);
            } else {
                assProductCountMap = new Map<Id, List<Id>>();
            }
            Id recId;
            Id product2Id;
            if (ei.rec2 != null) {
                recId = ei.rec2.Id;
                product2Id = ei.rec2.Product2Id;
            } else {
                recId = ei.rec.Asset__c;
                product2Id = ei.rec.Asset__r.Product2Id;
            }
            List<Id> count;
            if (assProductCountMap.containsKey(product2Id)) {
                count = assProductCountMap.get(product2Id);
            } else {
                count = new List<Id>();
            }
            count.add(recId);
            assProductCountMap.put(product2Id, count);
            assProductCountMapAll.put(ei.accessorySetId, assProductCountMap);
        }

        Boolean needSaveSet = false;
        Boolean needSaveDetail = false;
        Boolean needSaveAsset = false;

        List<Fixture_OneToOne_Link__c> otolinkList = new List<Fixture_OneToOne_Link__c>();
        boolean err = false;
        Map<String, Integer> otoMap = new Map<String, Integer>();

        List<String> soqlList = new List<String>();
        if (otoCheckList_main.size() > 0) {
            for (EsdInfo main : otoCheckList_main) {
                if (main.rec.Cancel_Select__c == false) {
                    String soql = '(TransferApplySummary__c = \'' + main.rec.TransferApplySummary__c + '\' and Cancel_Select__c = false )';
                    soqlList.add(soql);
                }
                else {
                    String soql = '(TransferApplySummary__c = \'' + main.rec.TransferApplySummary__c + '\')';
                    soqlList.add(soql);
                }
            }

            String soql = 'select Asset__r.Product2.Name, Asset__c, Asset__r.Product2Id , OneToOneAccessory__c, TransferApplySummary__c,OneToOneAsset__c '
                        + ' from TransferApplyDetail__c '
                        + ' WHERE OneToOneAccessory__c = true and Asset__c <> null '
                        + ' AND (' + String.join(soqlList, ' OR ') + ') order by TransferApplySummary__c, OneToOneAccessory__c desc';

            Map<Id, List<TransferApplyDetail__c>> tadMap = new Map<Id, List<TransferApplyDetail__c>>();
            System.debug(soql);
            for (TransferApplyDetail__c tad : Database.query(soql)) {
                if (tadMap.containsKey(tad.TransferApplySummary__c) == false) {
                    tadMap.put(tad.TransferApplySummary__c, new List<TransferApplyDetail__c>());
                }
                tadMap.get(tad.TransferApplySummary__c).add(tad);
            }
            for (EsdInfo main : otoCheckList_main) {
                List<TransferApplyDetail__c> tadList = new List<TransferApplyDetail__c>();
                if (tadMap.containsKey(main.rec.TransferApplySummary__c)) {
                    tadList = tadMap.get(main.rec.TransferApplySummary__c);
                }
                //没有cancel的看最新一套明细的fsd数量
                //已经cancel的看最早一套明细的一对一分配数量
                //理论上出库前上架的数据不会有非cancel的情况，所以直接用Cancel_Select__c判断
                // system.debug(main.rec);
                // if (main.rec.Cancel_Select__c == false) {
                //     tadList = [select Asset__r.Product2.Name, Asset__c, Asset__r.Product2Id , OneToOneAccessory__c
                //                 from TransferApplyDetail__c
                //                where TransferApplySummary__c = :main.rec.TransferApplySummary__c
                //                      and OneToOneAccessory__c = true
                //                      and Cancel_Select__c = false //找最新的一套明细
                //                      //and Canceled_Id__c = null //找最初的一套明细
                //                      and Asset__c <> null //过滤未分配的数据。
                //                      order by OneToOneAccessory__c desc];
                // } else {
                //     tadList = [select Asset__r.Product2.Name, Asset__c, Asset__r.Product2Id , OneToOneAccessory__c
                //                 from TransferApplyDetail__c
                //                where TransferApplySummary__c = :main.rec.TransferApplySummary__c
                //                      and OneToOneAccessory__c = true
                //                      //and Canceled_Id__c = null
                //                      and Asset__c <> null
                //                      order by OneToOneAccessory__c desc];
                // }
                system.debug(tadList);
                Map<Id, List<Id>> assProductCountMap = new Map<Id, List<Id>>();
                if (assProductCountMapAll.containsKey(main.rec.TransferApplySummary__c)) {
                    assProductCountMap = assProductCountMapAll.get(main.rec.TransferApplySummary__c);
                }

                for (TransferApplyDetail__c tad : tadList) {
                    if (assProductCountMap.containsKey(tad.Asset__r.Product2Id) && assProductCountMap.get(tad.Asset__r.Product2Id).size() > 0) {

                        List<Id> count = assProductCountMap.get(tad.Asset__r.Product2Id);
                        String assetId = (String)count[0];
                        count.remove(0);
                        assProductCountMap.put(tad.Asset__r.Product2Id, count);
                        assProductCountMapAll.put(main.rec.TransferApplySummary__c, assProductCountMap);

                        String key = (String)main.rec.Asset__c + ':' + assetId;
                        Integer otoCnt;
                        if (otoMap.containsKey(key)) {
                            otoCnt = otoMap.get(key);
                        } else {
                            otoCnt = 0;
                        }
                        otoMap.put(key, otoCnt + 1);
                    } else {
                        // if (!forceSave && (main.rec.Cancel_Select__c == false || (main.rec.Cancel_Select__c == true && tad.OneToOneAccessory__c))) {
                        //     main.errorInfo = '未补全附属品(部分上架请勾选复选框):'+tad.Asset__r.Product2.Name;
                        //     ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, main.rec.SerialNumber_F__c + '未补全附属品:'+tad.Asset__r.Product2.Name));
                        //     err = true;
                        //     needforceSave = true;
                        //     break;
                        // } else {
                        //     continue;
                        // }
                    }
                }
            }
        }
        Set<Id> tdIdSet = new Set<Id>();
        forceSave = false;
        if (err) return null;
        // TODO 没变化不存
        // if (Step_status == '上架') {

            for (TransferApplyDetail__c esd : eList) {
                if (esd.Arrival_in_wh__c) {
                    esd.Arrival_wh_time__c = System.now();
                    esd.Return_wh_chenk_staff__c = userid;
                } else {
                    esd.Arrival_wh_time__c = null;
                    esd.Return_wh_chenk_staff__c = null;
                }
                tdIdSet.add(esd.Id);
            }
            needSaveDetail = true;
        // }
        for (EsdInfo esdInfo : esdList) {
            if (esdInfo.accessoryFlg) continue;
            TransferApplyDetail__c esd = esdInfo.rec;
            if (esd.Arrival_in_wh__c && esd.FSD_OneToOneAccessory_Cnt_F__c > 0 && esd.Main_OneToOne__c && esd.Arrival_wh_Abandoned_Flag_F__c) {
                otoCheckList_main.add(esdInfo);
            }
        }
        String sqlStr = 'SELECT Id FROM Asset WHERE Id IN:assetForLock ';
        String sqlWhere = '';
        if(! ukeySet.isEmpty()) {
            for(String ukey: ukeySet) {
                // 型号;存放地;本部
                List<String> fields = ukey.split(';');
                // 型号
                if (String.isNotBlank(fields[0]) && fields[0] != 'null') {
                    sqlWhere += ' (Fixture_Model_No_F__c =\'' + String.escapeSingleQuotes(fields[0]) + '\'';
                } else {
                    sqlWhere += ' (Fixture_Model_No_F__c = null';
                }
                // 备品存放地
                if (String.isNotBlank(fields[1]) && fields[1] != 'null') {
                    sqlWhere += ' AND Internal_asset_location__c =\'' + String.escapeSingleQuotes(fields[1]) + '\'';
                } else {
                    sqlWhere += ' AND Internal_asset_location__c = null';
                }
                // 本部
                if (String.isNotBlank(fields[2]) && fields[2] != 'null') {
                    sqlWhere += ' AND Salesdepartment__c =\'' + String.escapeSingleQuotes(fields[2]) + '\')';
                } else {
                    sqlWhere += ' AND Salesdepartment__c = null)';
                }

                sqlWhere += ' OR';
            }
            sqlWhere = sqlWhere.removeEnd('OR');
            sqlWhere = '((' + sqlWhere + ')';
            sqlWhere += ' AND Delete_Flag__c = false '
                    + ' AND Asset_Owner__c = \'Olympus\''
                    + ' AND AssetManageConfirm__c = true'
                    + ' AND Quantity > 0'
                    + ' AND Freeze_sign_Abandoned_Flag__c = False'
                    + ' AND Manage_type__c = \'数量管理\')';
            sqlStr += ' OR ' + sqlWhere ;
        }
        sqlStr += ' FOR UPDATE';
        List<Asset> astLock = Database.query(sqlStr);
        Savepoint sp = Database.setSavepoint();
        try {
            // 强制删废弃主体的一对一link
            if (otoCheckList_main.size() > 0) {
                List<Id> mainIds = new List<Id>();
                for (EsdInfo oto : otoCheckList_main) {
                    if (String.isNotBlank(oto.rec.Asset__c)) {
                        // Asset__c 念のための確認
                        mainIds.add(oto.rec.Asset__c);
                    }
                }
                FixtureUtil.delOtOLinkData(mainIds);
            }

            // 这里只更新明细，保有设备和link都放到trigger里更新
            if (eList.size() > 0) {
                FixtureUtil.withoutUpsertObjects(eList);
            }

            if (otoList.size() > 0) {
                soqlList = new List<String>();
                Map<String, Fixture_OneToOne_Link__c> otoMap1 = new Map<String, Fixture_OneToOne_Link__c>(); // 主Id附Id->link
                Map<String, Integer> otoMap2 = new Map<String, Integer>(); // 主Id、主型号、附型号->数量
                Map<Id, TransferApplyDetail__c> tdMap = new Map<Id, TransferApplyDetail__c>([
                    SELECT Id
                    , OneToOneAsset__c
                    , OneToOneAsset__r.Fixture_Model_No_F__c
                    , OneToOneAsset__r.SerialNumber
                    , Asset__c
                    , Asset_After__c
                    , Asset_After__r.Fixture_Model_No_F__c
                    , Asset_After__r.SerialNumber
                    , Asset__r.Fixture_Model_No_F__c
                    , Asset__r.SerialNumber
                    FROM TransferApplyDetail__c WHERE Id = :tdIdSet]);
                Map<String, Integer> standardLinkCount = getLinkCountFromStandard(tdMap);
                Map<Id, String> assetIdToModel = getAssetIdToModel(tdMap);
                Map<Id, String> assetIdToSerial = getAssetIdToSerial(tdMap);
                System.debug(assetIdToModel);
                for (EsdInfo esdInfo : otoList) {
                    Id afterId = esdInfo.rec.Asset__c;
                    if(tdMap.containsKey(esdInfo.rec.Id) && tdMap.get(esdInfo.rec.Id).Asset_After__c != null) {
                        afterId = tdMap.get(esdInfo.rec.Id).Asset_After__c;
                    }
                    // soqlList.add('(Main_Asset__c = \'' + esdInfo.rec.OneToOneAsset__c + '\' AND Accessory_Asset__c = \''+ afterId + '\')');
                    // 主体下已有的全部link要参与检查
                    soqlList.add('(Main_Asset__c = \'' + esdInfo.rec.OneToOneAsset__c  + '\')');
                }
                String linkSql = 'SELECT Quantity__c, Main_Asset__c, Main_Asset__r.Fixture_Model_No_F__c, Main_Asset__r.SerialNumber, Accessory_Asset__c, Accessory_Asset__r.Fixture_Model_No_F__c FROM Fixture_OneToOne_Link__c WHERE ' + String.join(soqlList, ' OR ');

                for (Fixture_OneToOne_Link__c oto : Database.query(linkSql)) {
                    otoMap1.put(String.valueOf(oto.Main_Asset__c) + String.valueOf(oto.Accessory_Asset__c), oto);
                    // 机身号不同的同型号主体，link要分开计数
                    String serialLinkName = String.join(new List<String> {
                        oto.Main_Asset__r.Fixture_Model_No_F__c,
                        oto.Main_Asset__r.SerialNumber,
                        oto.Accessory_Asset__r.Fixture_Model_No_F__c
                    }, DELIMITER);
                    Integer cnt = 0;
                    if(otoMap2.containsKey(serialLinkName)) {
                        cnt = otoMap2.get(serialLinkName);
                    }
                    otoMap2.put(serialLinkName, cnt + Integer.valueOf(oto.Quantity__c));
                }
                System.debug(otoMap2);

                Map<String, Fixture_OneToOne_Link__c> otoUpsertMap = new Map<String, Fixture_OneToOne_Link__c>();
                for (EsdInfo esdInfo : otoList) {
                    Id afterId = esdInfo.rec.Asset__c;
                    if(tdMap.containsKey(esdInfo.rec.Id) && tdMap.get(esdInfo.rec.Id).Asset_After__c != null) {
                        afterId = tdMap.get(esdInfo.rec.Id).Asset_After__c;
                    }
                    // 主Id附Id作为key，新建link或修改link数量
                    String key = String.valueOf(esdInfo.rec.OneToOneAsset__c) + afterId;
                    if (otoUpsertMap.containsKey(key) == false) {
                        Fixture_OneToOne_Link__c oto = new Fixture_OneToOne_Link__c();
                        if (otoMap1.containsKey(key)) {
                            oto = otoMap1.get(key);
                        }
                        else {
                            oto.Main_Asset__c = esdInfo.rec.OneToOneAsset__c;
                            oto.Accessory_Asset__c = tdMap.get(esdInfo.rec.Id).Asset_After__c;
                            oto.Quantity__c = 0;
                        }
                        otoUpsertMap.put(key, oto);
                    }
                    otoUpsertMap.get(key).Quantity__c += 1;
                    System.debug(otoUpsertMap);

                    // 主型号、附型号作为key，和标准配套做比较
                    String linkName = String.join(new List<String> {
                        assetIdToModel.get(esdInfo.rec.OneToOneAsset__c),
                        assetIdToModel.get(afterId)
                    }, DELIMITER);
                    // 主型号，主机身号，附型号作为key，用于和标准配套明细数量比较
                    // 不同主体下的link要分别计数，新入的附属品link要和既存的link按型号合并后计数
                    String serialLinkName = String.join(new List<String> {
                        assetIdToModel.get(esdInfo.rec.OneToOneAsset__c),
                        assetIdToSerial.get(esdInfo.rec.OneToOneAsset__c),
                        assetIdToModel.get(afterId)
                    }, DELIMITER);
                    // 主型号，主机身号，附型号，附机身号，用于画面提醒
                    String serialLinkNameFull = String.join(new List<String> {
                        assetIdToModel.get(esdInfo.rec.OneToOneAsset__c),
                        assetIdToSerial.get(esdInfo.rec.OneToOneAsset__c),
                        assetIdToModel.get(afterId),
                        esdInfo.rec.SerialNumber_F__c
                    }, DELIMITER);
                    System.debug(linkName);
                    System.debug(serialLinkName);
                    System.debug(serialLinkNameFull);

                    Integer cnt = 0;
                    if(otoMap2.containsKey(serialLinkName)) {
                        cnt = otoMap2.get(serialLinkName);
                    }
                    otoMap2.put(serialLinkName, cnt + 1);
                    System.debug(otoMap2);
                    System.debug(standardLinkCount);

                    if(!standardLinkCount.containsKey(linkName)) {
                        throw new ControllerUtil.myException(String.format('附属品 {2}({3})：不属于主体 {0}({1})配套中附属品，不能入库', serialLinkNameFull.split(DELIMITER)));
                    }
                    else if(standardLinkCount.get(linkName) < otoMap2.get(serialLinkName)) {
                        throw new ControllerUtil.myException(String.format('附属品 {2}({3})：超过主体 {0}({1})配套中该型号附属品数量，多余数量不能入库', serialLinkNameFull.split(DELIMITER)));
                    }
                }
                if (otoUpsertMap.isEmpty() == false) {
                    FixtureUtil.withoutUpsertObjects(otoUpsertMap.values());
                }
            }

            List<EsdInfo> esdL = new List<EsdInfo>();
            for (EsdInfo esd : esdList) {
                if (!esd.accessoryFlg) {
                    esdL.add(esd);
                }
            }
            init();
            done_flg = true;
        } catch (Exception ex) {
            system.debug('=====' + ex.getMessage());
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, ex.getMessage()));
            Database.rollback(sp);
            done_flg = false;
        }

        return null;
    }
    /**
     * @return 设备id->型号
     *
     * */
    private Map<Id, String> getAssetIdToModel(Map<Id, TransferApplyDetail__c> tdMap) {
        Map<Id, String> assetIdToModel = new Map<Id, String> ();
        for(TransferApplyDetail__c tad:tdMap.values()) {
            assetIdToModel.put(tad.OneToOneAsset__c, tad.OneToOneAsset__r.Fixture_Model_No_F__c);
            assetIdToModel.put(tad.Asset_After__c, tad.Asset_After__r.Fixture_Model_No_F__c);
            assetIdToModel.put(tad.Asset__c, tad.Asset__r.Fixture_Model_No_F__c);
        }
        return assetIdToModel;
    }
    /**
     * @return 设备id->机身号
     *
     * */
    private Map<Id, String> getAssetIdToSerial(Map<Id, TransferApplyDetail__c> tdMap) {
        Map<Id, String> assetIdToSerial = new Map<Id, String> ();
        for(TransferApplyDetail__c tad:tdMap.values()) {
            assetIdToSerial.put(tad.OneToOneAsset__c, tad.OneToOneAsset__r.SerialNumber);
            assetIdToSerial.put(tad.Asset_After__c, tad.Asset_After__r.SerialNumber);
            assetIdToSerial.put(tad.Asset__c, tad.Asset__r.SerialNumber);
        }
        return assetIdToSerial;
    }
    /**
     * @description 按所选主体的型号找到配套明细及数量
     * @return 主型号;附型号->数量
    */
    private Map<String, Integer> getLinkCountFromStandard(Map<Id, TransferApplyDetail__c> tdMap) {
        Map<String, Integer> mainModels = new Map<String, Integer>();
        Map<String, Integer> linkCounts = new Map<String, Integer>();
        for(TransferApplyDetail__c tad:tdMap.values()) {
            mainModels.put(tad.OneToOneAsset__r.Fixture_Model_No_F__c, 0);
        }
        List<Fixture_Set_Detail__c> fsdList = [SELECT Id
            , Quantity__c
            , Fixture_Model_No_F__c
            , Fixture_Set__r.Fixture_Set_Body_Model_No__c
            , Is_Body__c
            , Is_OneToOne__c
            FROM Fixture_Set_Detail__c
            WHERE Fixture_Set__r.Fixture_Set_Body_Model_No__c IN:mainModels.keySet()
            ORDER BY Fixture_Set__c, SortInt_F__c
        ];
        for(Fixture_Set_Detail__c fsd:fsdList){
            // 主体型号不可有多个配套
            if(mainModels.get(fsd.Fixture_Model_No_F__c) == 1) {
                throw new ControllerUtil.myException(fsd.Fixture_Model_No_F__c + '主体对应多个配套，无法继续');
            }
            if(fsd.Is_Body__c) {
                mainModels.put(fsd.Fixture_Model_No_F__c, 1);
            }
            else if (fsd.Is_OneToOne__c) {
                Integer c = 0;
                String linkName = fsd.Fixture_Set__r.Fixture_Set_Body_Model_No__c + DELIMITER + fsd.Fixture_Model_No_F__c;
                if (linkCounts.containsKey(linkName)) {
                    c = linkCounts.get(linkName);
                }
                linkCounts.put(linkName, c + Integer.valueOf(fsd.Quantity__c));
            }
        }
        return linkCounts;

    }



    public PageReference searchSlip() {
        done_flg = false;
        Map<String,boolean> esdIdMap = new Map<String,boolean>();
        // for (EsdInfo esd : esdList) {
        //     if (!esd.hasSended)
        //     esdIdMap.put(esd.rec.Id, esd.isChecked);
        // }

        String qryString = 'select Id, Name, DeliveryCompany_SlipNo__c,DeliveryType__c,Distributor_method__c,DeliveryCompany__c,Wh_Staff__c '
                + 'from FixtureDeliverySlip__c '
                + 'where Name =\''+ slip.Name +'\' and DeliveryType__c = \'回寄\'';
        if (String.isNotBlank(slip.Distributor_method__c)) {
            qryString += ' and Distributor_method__c = \''+ slip.Distributor_method__c +'\'';
        }
        if (String.isNotBlank(slip.DeliveryCompany__c)) {
            qryString += ' and DeliveryCompany__c = \''+ slip.DeliveryCompany__c +'\'';
        }
        List<FixtureDeliverySlip__c> slipList = Database.query(qryString);

        if (slipList.size() > 0) {
            if (slipList.size() > 1) {
                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '当前条件检索到复数条运输单，请追加检索条件!'));
                return null;
            }
            slip = slipList[0];
        }
        else {
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.WARNING, '没有检索出符合条件的运输单'));
        }
        return null;
    }

    public class EsdInfo {
        public TransferApplyDetail__c rec { get; set; }
        public Boolean canReturn { get; set; }//true  有能回寄的数据
        // 回库はSet単位で、明細一つ一つのquickCheck要らない
        public Boolean checked {get;set;}
        public boolean editable { get; set; }
        public String fsName {get;set;}
        public String tasId {get;set;}
        // public String errorInfo { get; set; }

        public Asset rec2 { get; set; }
        public String errorInfo { get; set; }
        public boolean accessoryFlg { get; set; }
        public String accessorySetId { get; set; }
        public Boolean discardFlg { get; set; }
        public Boolean needsetone { get; set; }
        public Boolean needColor { get; set; }
        // public boolean editable { get; set; }
        // public String fsName {get;set;}

        // public EsdInfo() {
        //     this.discardFlg = false;
        //     this.editable = false;
        // }

        public EsdInfo(TransferApplyDetail__c rec) {
            this.needColor = false;
            this.rec = rec;
            this.needsetone = rec.Arrival_in_wh__c == false && (
                                    //20210507 ljh update 1834 start
                                    //(rec.Main_OneToOne__c == false && rec.OneToOneAccessory__c == false)
                                    (rec.Main_OneToOne__c == false && rec.OneToOneAccessory__c == false && rec.Loaner_accsessary__c)
                                    //20210507 ljh update 1834 end
                                        || (rec.OneToOneAccessory__c && rec.TransferApplySummary__r.First_TAD__r.Arrival_in_wh__c && rec.First_You_Xiao_Ku_Cun__c == 0)
                                ) ;
            this.accessoryFlg = false;
            this.discardFlg = false;
            this.checked = false;
            this.editable = rec.Shippment_loaner_time__c != null && rec.Detail_Finish__c == false && rec.Asset_return_time__c == null;
            this.fsName = rec.TransferApplySummary__r.Name + '：' + rec.TransferApplySummary__r.Fixture_Set__r.Name;
            this.accessorySetId = rec.TransferApplySummary__c;
            /*this.canReturn = rec.TransferApplySummary__r.First_TAD__r.Loaner_accsessary__c == true
                         || (rec.TransferApplySummary__r.First_TAD__r.ArrivalResult__c != '欠品'
                                && rec.TransferApplySummary__r.First_TAD__r.ArrivalResult__c != 'NG'
                            );*/
            this.canReturn = false;//20210118 ljh update
        }


        // public EsdInfo(TransferApplyDetail__c rec) {
        //     this.rec = rec;
        //     this.checked = false;

        //     this.fsName = rec.TransferApplySummary__r.Name+'：'+rec.TransferApplySummary__r.Fixture_Set__r.Name;
        //     this.tasId = rec.TransferApplySummary__r.Id;
        // }
    }
    public class LabelValue {
        public String label {get; set;}
        public String value {get; set;}

        public LabelValue() {
            label = '';
            value = '';
        }

        public LabelValue(String l, String v) {
            label = l;
            value = v;
        }
    }
}