public without sharing class RentalAgencyReceivedController {
    public List<EsdInfo> esdList { get; set; }
    public String stepName {get;set;}
    public String qrcode {get;set;}
    public boolean done_flg {get;set;}
    public String raId {get;set;}
    public Boolean readOnly { get;  set; }
    public Boolean stockupActive{get;set;}
    public String lostResult {get;set;} // 检索用
    public String cdsResult {get;set;} // 检索用
    private Rental_Apply__c parentObj;
    private Boolean isSameCity;

    public String skipId{get;set;}


    private static final Map<String,Schema.RecordTypeInfo>  DEVELOPERNAMEMAP  = Schema.SObjectType.Rental_Apply__c.getRecordTypeInfosByDeveloperName();
    public Boolean isAdvocateFollow{get;set;}
    public Boolean isImportReceiptForm{get;set;}

    public RentalAgencyReceivedController() {
        raId = ApexPages.currentPage().getParameters().get('id');
        stepName = '';
        lostResult = '';
        cdsResult = '';
        isImportReceiptForm = false;
        isAdvocateFollow = false;
        skipId = '';
    }
    private List<Rental_Apply_Equipment_Set_Detail__c> getDetails() {
        List<Rental_Apply_Equipment_Set_Detail__c> raesdList = [
                select Id
                     , Rental_Apply_Equipment_Set__c
                     , Asset__r.Product2Id
                     , Asset__r.CountForRepair__c
                     , Asset__r.Abandoned_RealThing__c
                     , Asset__r.You_Xiao_Ku_Cun__c
                     , Asset_return_time__c
                     , Fixture_Model_No__c
                     , SerialNumber_F__c
                     , Arrival_wh_Flag_F__c
                     , Arrival_wh_Abandoned_Flag_F__c
                     , Fixture_Set_Detail__r.Is_OneToOne__c
                     , Is_Body__c
                     , Rental_Apply_Equipment_Set__r.Fixture_Set__r.Name
                     , FSD_OneToOneAccessory_Cnt_F__c
                     , Asset__r.WH_location__c
                     , OneToOne_Flag__c
                     , Fixture_QRCode_F__c
                     , Rental_Apply_Equipment_Set__r.Name
                     , Name, Asset__c, Asset__r.Name, Asset__r.SerialNumber, Asset__r.Product_Serial_No__c
                     , Check_lost_Item__c
                     , Inspection_result_after_F__c
                     , Arrival_in_wh__c
                     , CDS_complete__c
                     , Arrival_wh_Result_Agency__c
                     , Check_lost_Item_Final__c
                     , Check_lost_Item_F__c
                     , Internal_Asset_number_c__c
                     , Return_DeliverySlip__c
                     , DeliverySlip__c
                     , Rental_Apply_Equipment_Set__r.Wei_Arrival_in_wh__c
                     , LastModifiedDate
                     , LastModifiedBy.Name
                     , Lost_item_giveup__c
                     , Internal_asset_location__c
                     , Arrival_wh_time__c
                     , Rental_Apply_Equipment_Set__r.First_RAESD__r.Asset__c
                     , Rental_Apply_Equipment_Set__r.First_RAESD__r.Arrival_wh_Result_Agency__c
                     , Rental_Apply_Equipment_Set__r.First_RAESD__r.Asset__r.You_Xiao_Ku_Cun__c
                     , CanAgencyChangeResult__c
                     , SeparateFromMain__c
                     , Arrival_wh_time_Agency_First__c
                  from Rental_Apply_Equipment_Set_Detail__c
                 where Rental_Apply__c =:raId and ((Shipment_request_time2__c <> null and Cancel_Select__c = False ))
                 order by Rental_Apply_Equipment_Set__r.Name, Rental_Apply_Equipment_Set__c, Is_Body__c DESC, Name
        ];
        return raesdList;
    }
    private Map<Id, Rental_Apply_Equipment_Set_Detail__c> getDetailsMap() {
        List<Rental_Apply_Equipment_Set_Detail__c> raesdList = getDetails();
        Map<Id, Rental_Apply_Equipment_Set_Detail__c> raesdMap = new Map<Id, Rental_Apply_Equipment_Set_Detail__c>();

        for(Rental_Apply_Equipment_Set_Detail__c raesd:raesdList) {
            raesdMap.put(raesd.Id, raesd);
        }
        return raesdMap;
    }

    
    // 画面初始化
    public PageReference init() {
        done_flg = false;

        if (raId != null) {
            List<Rental_Apply__c> raList = [
                SELECT Id
                     , Name
                     , Yi_loaner_arranged__c
                     , demo_purpose2__c
                     , Asset_loaner_start_day__c
                     , Hope_Lonaer_date_Num__c
                     , Campaign_EndDate_F__c
                     , requestNoJoinStr2__c
                     , Root_Rental_Apply__c
                     , ToAgency__c
                     , StockDown_ng_num__c
                     , DeliverySlip__c
                     , Old_Rental_Apply__c
                     , Split_Apply_Reason__c
                     , HP_received_sign_rich__c
                     , Status__c
                     , Old_Rental_Apply__r.Asset_loaner_start_date__c
                     , Old_Rental_Apply__r.HP_received_sign_rich__c
                     , ShelfUp_ng_num__c
                     , RecordType.Name
                     , RecordType.Id
                     , OwnerId
                  FROM Rental_Apply__c
                 WHERE Id=:raId
                 LIMIT 1
            ];
            if(raList.isEmpty()) {
                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '备品借出申请不存在！'));
                return null;
            }
            parentObj = raList[0];
            List<User> owners = [SELECT OCM_man_province_Rental__c FROM User WHERE Id=:parentObj.OwnerId LIMIT 1];
            if(owners.isEmpty()) {
                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '申请者不存在！'));
                return null;
            }
            else {
                isSameCity = owners[0].OCM_man_province_Rental__c == parentObj.ToAgency__c;
            }

            //wangweipeng      2021/09/03           SFDC-C4H4BM        start
            //查询是否是从单,并且从单是否没有上传签收单
            if(raList != null && raList.size() > 0 && isSameCity){
                String ra_RecordTypeId = DEVELOPERNAMEMAP.get('AgencyRequest').getRecordTypeId();//获取记录类型
                ra_RecordTypeId = ra_RecordTypeId.substring(0,15);

                for(Rental_Apply__c rac : raList){
                    //备品签收单是否为空
                    if(String.isBlank(rac.HP_received_sign_rich__c)){
                        isImportReceiptForm = true;//当前签收单是否上传签收单

                        //判断是否为办事处的单子，如果是，那么是从单
                        String recordTypeId = rac.RecordType.Id;
                        recordTypeId = recordTypeId.substring(0,15);
                        if(ra_RecordTypeId == recordTypeId){
                            //判断原数据单是否为空，为空和不为空的提示信息不一样
                            if(String.isBlank(rac.Root_Rental_Apply__c)){
                                isAdvocateFollow = true;
                            }
                        }
                        break;
                    }
                }
            }
            //wangweipeng      2021/09/03           SFDC-C4H4BM        end
            
            readOnly = parentObj.ShelfUp_ng_num__c == 0;
            esdList = getEsdInfos();
            this.stockupActive = checkCanChangeResult(esdList, esdList);
            if (esdList.isEmpty()) {
                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '备品借出明细不存在！'));
                return null;
            }
        }
        return null;
    }

    //wangweipeng     2021/09/09   SFDC-C4H4BM    start
    //重定向到
    public PageReference redirectPag(){
        PageReference ref = new Pagereference('/apex/WebToEquipmentSetShippmentReceived');
        ref.setRedirect(true);
        return ref;
    }
    //wangweipeng     2021/09/09   SFDC-C4H4BM    end
    
    /**
     * @param locations 存放地
     * @return 最新的盘点时间
     */
    private Datetime getLatestInventoryTime(Set<String> locations) {
        Datetime latestInventoryTime = System.now().addYears(-100);
        List<Inventory_Header__c> headers =  [
            SELECT Id, CreatedDate FROM Inventory_Header__c
            WHERE Internal_asset_location__c IN:locations
            // 盘点没有半途而废的
            ORDER BY CreatedDate DESC LIMIT 1
        ];
        if(!headers.isEmpty()) {
            latestInventoryTime = headers[0].CreatedDate;
        }
        return latestInventoryTime;
    }

    /**
     * @description 获取调拨信息
     * @param assetIdSet 全部的设备Id
     * @param earliestStockinTime 回库最早的时间
     * @return {设备Id:{调拨类型:数量}}
     */
    private Map<Id, Map<String, Integer>> getTransferCount(Set<Id> assetIdSet, Datetime earliestStockinTime) {
        Map<Id, Map<String, Integer>> resultMap = new Map<Id, Map<String, Integer>>();
        AggregateResult[]  aggs = [
            select Asset__c,TransferType__c , count(id) cnt
            from TransferApplyDetail__c
            where Cancel_Select__c = false
            AND CreatedDate >=: earliestStockinTime // 回库开始后的所有未取消的调拨都要考虑
            AND Asset__c IN: assetIdSet
            group by Asset__c,TransferType__c
        ];
        for(AggregateResult agg:aggs) {
            Id assetId = (Id) agg.get('Asset__c');
            String transferType = String.valueOf(agg.get('TransferType__c'));
            Integer cnt = Integer.valueOf(agg.get('cnt'));
            if(!resultMap.containsKey((assetId))) {
                resultMap.put(assetId, new Map<String, Integer>());
            }
            resultMap.get(assetId).put(transferType, cnt);
        }
        return resultMap;
    }
    private List<EsdInfo> getEsdInfos() {
        List<EsdInfo> esdList1 = new List<EsdInfo>();
        // 备品set明细
        List<Rental_Apply_Equipment_Set_Detail__c> eList = getDetails();
        for (Rental_Apply_Equipment_Set_Detail__c esd : eList) {
            EsdInfo ei = new EsdInfo(esd);
            // 同城的发货后可编辑
            if(isSameCity) {
                ei.editable = esd.DeliverySlip__c != null && !esd.Lost_item_giveup__c;
            }
            // 非同城回寄后可编辑
            else {
                ei.editable = (esd.Return_DeliverySlip__c != null || String.isNotBlank(esd.Check_lost_Item_F__c))
                                && !esd.Lost_item_giveup__c;
            }
            esdList1.add(ei);
        }
        return esdList1;
    }
    /**
     * @description 库存及调拨情况检查
     * @param esdBase 数据库里明细
     * @param esdPage 画面上的明细
     * @param transferCountMap {设备Id:{调拨类型:数量}}各设备的调拨类型及数量
     * @param otherLinkCountMap {设备Id:{调拨类型:数量}}各设备的背景link数量
     * @param linkChangeMap 附属品理论上要建的link
     * @param resultChangeMap {设备Id:{调拨类型:修改的数量}}用作返回值，存储各设备的变更类型及数量
     * */
    private void checkCanChangeLinkByTransfer(EsdInfo esdBase, EsdInfo esdPage,
                                                Map<Id, Map<String, Integer>> transferCountMap,
                                                Map<Id, Map<String, Integer>> otherLinkCountMap,
                                                Map<Id, Map<String, Integer>> linkChangeMap,
                                                Map<Id, Map<String, Integer>> resultChangeMap
                                                ) {

        String assetFieldApiAfter = '';
        String transferTypeAfter = '';
        String assetFieldApiBefore = '';
        String transferTypeBefore = '';
        // 建link要以画面为准
        switch on esdPage.rec.Arrival_wh_Result_Agency__c {
            when 'OK' {
                assetFieldApiAfter = 'You_Xiao_Ku_Cun__c';
                transferTypeAfter = '有效库存';
            }
            when '移至报废区' {
                assetFieldApiAfter = 'Abandoned_RealThing__c';
                transferTypeAfter = '待废弃';
            }
            when '待修理' {
                assetFieldApiAfter = 'CountForRepair__c';
                transferTypeAfter = '待修理';
            }
        }
        switch on esdBase.rec.Arrival_wh_Result_Agency__c {
            when 'OK' {
                assetFieldApiBefore = 'You_Xiao_Ku_Cun__c';
                transferTypeBefore = '有效库存';
            }
            when '移至报废区' {
                assetFieldApiBefore = 'Abandoned_RealThing__c';
                transferTypeBefore = '待废弃';
            }
            when '待修理' {
                assetFieldApiBefore = 'CountForRepair__c';
                transferTypeBefore = '待修理';
            }
        }
        // 没有选回库结果的或首次回库不用判
        if(String.isBlank(assetFieldApiAfter)) {
            return ;
        }
        if (esdBase.rec.OneToOne_Flag__c) {
            esdPage.needLink = true;
            String otoKey = esdBase.rec.Asset__c;
            if(!linkChangeMap.containsKey(otoKey)) {
                linkChangeMap.put(otoKey, new Map<String, Integer>{'有效库存'=>0, '待废弃' => 0, '待修理' => 0});
            }
            Integer cnt = linkChangeMap.get(otoKey).get(transferTypeAfter) + 1;
            linkChangeMap.get(otoKey).put(transferTypeAfter, cnt);
            // 已回库未回库明细都要检查是否可创建link
            if(esdBase.rec.Rental_Apply_Equipment_Set__r.First_RAESD__r.Arrival_wh_Result_Agency__c == 'OK'
                && esdBase.rec.Rental_Apply_Equipment_Set__r.First_RAESD__r.Asset__r.You_Xiao_Ku_Cun__c <= 0) {
                esdPage.needLink = esdBase.rec.Arrival_in_wh__c && !esdBase.rec.SeparateFromMain__c;
            }
            else if(transferCountMap.containsKey(esdBase.rec.Rental_Apply_Equipment_Set__r.First_RAESD__r.Asset__c)) {
                esdPage.needLink = esdBase.rec.Arrival_in_wh__c && !esdBase.rec.SeparateFromMain__c;
            }
            else if(transferCountMap.containsKey(esdBase.rec.Asset__c)
                && transferCountMap.get(esdBase.rec.Asset__c).containsKey(transferTypeBefore)
                ) {
                Integer otherLinkCount = 0;
                if (otherLinkCountMap.containsKey(esdBase.rec.Asset__c) && otherLinkCountMap.get(esdBase.rec.Asset__c).containsKey(transferTypeBefore)) {
                    otherLinkCount = otherLinkCountMap.get(esdBase.rec.Asset__c).get(transferTypeBefore);
                }
                Integer changeCount = 0;
                if (resultChangeMap.containsKey(esdBase.rec.Asset__c) && resultChangeMap.get(esdBase.rec.Asset__c).containsKey(transferTypeBefore)) {
                    changeCount = resultChangeMap.get(esdBase.rec.Asset__c).get(transferTypeBefore);
                }
                if(esdBase.rec.Arrival_wh_Result_Agency__c == esdPage.rec.Arrival_wh_Result_Agency__c) {
                    // 先上架5个废弃，然后调拨2个废弃，又修改回库把1个废弃改成其它，则能建link的有3个，
                    esdPage.needLink = cnt <= Integer.valueOf(esdBase.rec.Asset__r.get(assetFieldApiBefore))
                                            - transferCountMap.get(esdBase.rec.Asset__c).get(transferTypeBefore)
                                            - changeCount
                                            - otherLinkCount ;

                }
            }
        }
    }

    /**
     * @description 库存及调拨情况检查
     * @param esdBase 数据库里明细
     * @param esdPage 画面上的明细
     * @param transferCountMap {设备Id:{调拨类型:数量}}各设备的调拨类型及数量
     * @param otherLinkCountMap {设备Id:{调拨类型:数量}}各设备的背景link数量
     * @param resultChangeMap {设备Id:{调拨类型:修改的数量}}用作返回值，存储各设备的变更类型及数量
     * */
    private void checkCanChangeResultByTransfer(EsdInfo esdBase, EsdInfo esdPage,
                                                Map<Id, Map<String, Integer>> transferCountMap,
                                                Map<Id, Map<String, Integer>> otherLinkCountMap,
                                                Map<Id, Map<String, Integer>> resultChangeMap) {
        String assetFieldApi = '';
        String transferType = '';
        // 修改结果要以数据库里的结果为准
        switch on esdBase.rec.Arrival_wh_Result_Agency__c {
            when 'OK' {
                assetFieldApi = 'You_Xiao_Ku_Cun__c';
                transferType = '有效库存';
            }
            when '移至报废区' {
                assetFieldApi = 'Abandoned_RealThing__c';
                transferType = '待废弃';
            }
            when '待修理' {
                assetFieldApi = 'CountForRepair__c';
                transferType = '待修理';
            }
        }
        if(String.isBlank(assetFieldApi)) {
            return ;
        }
        if(!resultChangeMap.containsKey(esdBase.rec.Asset__c)) {
            resultChangeMap.put(esdBase.rec.Asset__c, new Map<String, Integer>());
        }
        Integer cnt = 0;
        if(resultChangeMap.get(esdBase.rec.Asset__c).containsKey(transferType)) {
            cnt = resultChangeMap.get(esdBase.rec.Asset__c).get(transferType);
        }
        if(esdPage.rec.Arrival_wh_Result_Agency__c != esdBase.rec.Arrival_wh_Result_Agency__c) {
            resultChangeMap.get(esdBase.rec.Asset__c).put(transferType, cnt + 1);
        }

        if(esdBase.rec.Rental_Apply_Equipment_Set__r.First_RAESD__r.Arrival_wh_Result_Agency__c == 'OK'
            && esdBase.rec.Rental_Apply_Equipment_Set__r.First_RAESD__r.Asset__r.You_Xiao_Ku_Cun__c <= 0
            && esdBase.rec.Arrival_in_wh__c && !esdBase.rec.SeparateFromMain__c) {
            esdBase.canChangeResult = false;
            esdPage.errorInfo = esdBase.rec.Fixture_Model_No__c + '：配套已被分配，不可修改回库结果';
        }
        else if(transferCountMap.containsKey(esdBase.rec.Rental_Apply_Equipment_Set__r.First_RAESD__r.Asset__c)
            && esdBase.rec.Arrival_in_wh__c && !esdBase.rec.SeparateFromMain__c) {
            esdBase.canChangeResult = false;
            esdPage.errorInfo = esdBase.rec.Fixture_Model_No__c + '：配套已被调拨，不可以修改回库结果';
        }
        else if(Integer.valueOf(esdBase.rec.Asset__r.get(assetFieldApi)) <= 0) {
            esdBase.canChangeResult = false;
            esdPage.errorInfo = esdBase.rec.Fixture_Model_No__c + '：保有设备里'+ transferType +'数不足，不可修改回库结果';
        }
        // 变化数量 与 调拨里的数量 + 背景link数量 比较
        else if(transferCountMap.containsKey(esdBase.rec.Asset__c) && transferCountMap.get(esdBase.rec.Asset__c).containsKey(transferType)) {
            Integer available = Integer.valueOf(esdBase.rec.Asset__r.get(assetFieldApi)) - Integer.valueOf(transferCountMap.get(esdBase.rec.Asset__c).get(transferType));
            if (otherLinkCountMap.containsKey(esdBase.rec.Asset__c) && otherLinkCountMap.get(esdBase.rec.Asset__c).containsKey(transferType)) {
                available -= otherLinkCountMap.get(esdBase.rec.Asset__c).get(transferType);
            }
            // 所有有效库存/待废弃数/待修理数都被调拨
            if(available <= 0) {
                esdBase.canChangeResult = false;
                esdPage.errorInfo = esdBase.rec.Fixture_Model_No__c + '：已被调拨，不可修改回库结果';
            }
            // 有效库存/待废弃数/待修理数部分调拨，需要保证修改的数量不能超过库存数减去调拨数
            // 例如有效库存有5个，调拨有3个，这个设备在回库画面上有5条借出明细，
            // 显示时5条都是可编辑的，但至多改动其中2条
            else if(resultChangeMap.get(esdBase.rec.Asset__c).get(transferType) > available) {
                esdPage.errorInfo = esdBase.rec.Fixture_Model_No__c + '：有调拨明细，只可以把' + available + '条'
                                  + '从【' + esdBase.rec.Arrival_wh_Result_Agency__c + '】'
                                  + '改成其它选项';
            }
        }
        // 需要保证修改的数量不能超过库存数
        // 例如有效库存有2个，这个设备在回库画面上有5条借出明细，
        // 显示时5条都是可编辑的，但至多改动其中2条
        else if(Integer.valueOf(esdBase.rec.Asset__r.get(assetFieldApi)) < resultChangeMap.get(esdBase.rec.Asset__c).get(transferType)) {
            esdPage.errorInfo = esdBase.rec.Fixture_Model_No__c + '：最多可以把'
                              + Integer.valueOf(esdBase.rec.Asset__r.get(assetFieldApi)) + '条'
                              + '从【' + esdBase.rec.Arrival_wh_Result_Agency__c + '】改成其它选项';
        }
    }
    /**
     * @description 对数据库里明细做检查，并将检查结果反映在画面上
     * @param esdListBase 数据库里的
     * @param esdListPage 画面上的
     * @return 回库按钮是否可点击。只要有可以修改的，就返回true
     * */
    private Boolean checkCanChangeResult(List<EsdInfo> esdListBase, List<EsdInfo> esdListPage) {
        Boolean canChange = false;
        Datetime now = System.now();
        Datetime earliestStockinTime = System.now();
        Set<String> locations = new Set<String> ();
        Set<Id> assetIdSet = new Set<Id>(); //
        Set<Id> assetIdSetChecked = new Set<Id>(); // 勾选配套里的
        Set<Id> updateRas = new Set<Id> ();

        Boolean allEmpty = true;
        for(Integer i = 0; i < esdListBase.size(); i++ ) {
            EsdInfo esdBase = esdListBase[i];
            EsdInfo esdPage = esdListPage[i];
            esdPage.errorInfo = '';
            if(esdBase.rec.Id != esdPage.rec.Id) {
                esdPage.errorInfo = esdBase.rec.Fixture_Model_No__c + '后台数据不存在，请刷新画面！';
            }
            if(esdBase.rec.LastModifiedDate != esdPage.rec.LastModifiedDate) {
                esdPage.errorInfo = esdBase.rec.Fixture_Model_No__c + '后台数据被 ' + esdBase.rec.LastModifiedBy.Name + ' 修改，请刷新画面！';
            }
            locations.add(esdBase.rec.Internal_asset_location__c);
            allEmpty = allEmpty && String.isBlank(esdBase.rec.Arrival_wh_Result_Agency__c);
            assetIdSet.add(esdBase.rec.Asset__c);
            if(esdPage.rec.Is_Body__c && esdPage.checked) {
                updateRas.add(esdPage.rec.Rental_Apply_Equipment_Set__c);
            }
            if(updateRas.contains(esdPage.rec.Rental_Apply_Equipment_Set__c)) {
                assetIdSetChecked.add(esdPage.rec.Asset__c);
            }
            if(esdBase.rec.Arrival_wh_time_Agency_First__c != null) {
                if(esdBase.rec.Arrival_wh_time_Agency_First__c < earliestStockinTime) {
                    earliestStockinTime = esdBase.rec.Arrival_wh_time_Agency_First__c;
                }
            }
        }
        if(allEmpty) {
            return true;
        }
        Datetime latestInventoryTime = getLatestInventoryTime(locations);
        Map<Id, Map<String, Integer>> transferCountMap = getTransferCount(assetIdSet, earliestStockinTime);
        Map<Id, Map<String, Integer>> resultChangeMap = new Map<Id, Map<String, Integer>>(); // 要修改的回库结果
        Map<Id, Map<String, Integer>> otherLinkCountMap = getOtherLinkCount(assetIdSetChecked);
        Map<Id, Map<String, Integer>> linkChangeMap = new Map<Id, Map<String, Integer>>(); // 要更新的link
        for(Integer i = 0; i < esdListBase.size(); i++ ) {
            EsdInfo esdBase = esdListBase[i];
            EsdInfo esdPage = esdListPage[i];
            // 是否回库超2天
            if(!esdBase.rec.CanAgencyChangeResult__c && esdBase.rec.Arrival_wh_time__c != null) {
                esdBase.canChangeResult = false;
                esdPage.errorInfo = '已超过回库后两个工作日，不可修改回库结果';
            }
            // 是否有过盘点
            if(String.isNotBlank(esdBase.rec.Arrival_wh_Result_Agency__c)
                && latestInventoryTime >= esdBase.rec.Arrival_wh_time__c) {
                esdBase.canChangeResult = false;
                esdPage.errorInfo = '已开始新的盘点，不可修改回库结果';
            }
            checkCanChangeResultByTransfer(esdBase, esdPage, transferCountMap, otherLinkCountMap, resultChangeMap);
            canChange = esdBase.canChangeResult || canChange;
        }
        // 回库结果修改会影响到设备里的废弃数，必须等全部的变化情况统计完成后，再判断要不要建link
        for(Integer i = 0; i < esdListBase.size(); i++ ) {
            EsdInfo esdBase = esdListBase[i];
            EsdInfo esdPage = esdListPage[i];
            // 已上过架的附属品都有被调拨的可能，都要重新判一次要不要建link
            if (updateRas.contains(esdBase.rec.Rental_Apply_Equipment_Set__c) && esdBase.rec.OneToOne_Flag__c) {
                checkCanChangeLinkByTransfer(esdBase, esdPage, transferCountMap, otherLinkCountMap, linkChangeMap, resultChangeMap);
            }
        }
        return canChange;
    }
    /**
     * @description 查出勾选配套里附属品的后台link情况（不包括当前配套已生成的link）
     * @param assetIdSetChecked 勾选配套里的设备Id
     * @return {附属品Id:{类型:数量}}
     * */
    private Map<Id, Map<String, Integer>> getOtherLinkCount(Set<Id> assetIdSetChecked) {
        List<Fixture_OneToOne_Link__c> links = [
            SELECT Id,Abandoned_RealThing__c,CountForRepair__c,Quantity__c,
                    Accessory_Asset__c
             FROM Fixture_OneToOne_Link__c
            WHERE Main_Asset__c NOT IN:assetIdSetChecked
            AND Accessory_Asset__c IN:assetIdSetChecked
            AND (Abandoned_RealThing__c > 0 OR CountForRepair__c > 0)
        ];
        Map<Id, Map<String, Integer>> resultMap = new Map<Id, Map<String, Integer>>();
        for(Fixture_OneToOne_Link__c link : links) {
            if(!resultMap.containsKey(link.Accessory_Asset__c)) {
                resultMap.put(link.Accessory_Asset__c, new Map<String, Integer>{'有效库存' => 0, '待废弃' => 0, '待修理' => 0 });
            }
            Integer fei = intValueOf(link.Abandoned_RealThing__c);
            Integer xiu = intValueOf(link.CountForRepair__c);
            Integer you = intValueOf(link.Quantity__c - fei - xiu);
            resultMap.get(link.Accessory_Asset__c).put('有效库存', fei + resultMap.get(link.Accessory_Asset__c).get('有效库存'));
            resultMap.get(link.Accessory_Asset__c).put('待废弃', fei + resultMap.get(link.Accessory_Asset__c).get('待废弃'));
            resultMap.get(link.Accessory_Asset__c).put('待修理', xiu + resultMap.get(link.Accessory_Asset__c).get('待修理'));
        }
        return resultMap;
    }
    // 检索按钮
    public void filter() {
        for(EsdInfo esd:esdList) {
            if(stringEquals(esd.lostFinished, lostResult) && stringEquals(esd.cdsFinished, cdsResult)) {
                esd.hidden = false;
            }
            else {
                esd.hidden = true;
            }
        }
    }
    /**
    @param s1 明细字段值
    @param s2 画面选择值
    @return 一样则返回true, null和'' 也为true
    @description
    */
    private Boolean stringEquals(String s1, String s2) {
        // 画面选择值为空时，不用作筛选条件，恒为true
        if(String.isBlank(s2)) {
            return true;
        }
        else{
            return s2.equals(s1);
        }
    }
    // 清除按钮
    public void clearFilter() {
        lostResult = '';
        cdsResult = '';
        for(EsdInfo esd:esdList) {
            esd.hidden = false;
        }
    }
    // 回库按钮
    public void stockup() {
        done_flg = false;
        Datetime now = System.now();
        Id userId = Userinfo.getUserId();
        Boolean hasChecked = false;
        Savepoint sp = Database.setSavepoint();
        try {
            List<OlympusCalendar__c> dateList = [SELECT Date__c, After_2_WorkDay__c FROM OlympusCalendar__c WHERE Date__c=:now.date() LIMIT 1];
            if(dateList.isEmpty() || dateList[0].After_2_WorkDay__c == null) {
                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '日历数据不存在！'));
                return;
            }
            Date afterTwoWorkday = dateList[0].After_2_WorkDay__c;
            Map<Id, Rental_Apply_Equipment_Set_Detail__c> updateRaesdMap = new Map<Id, Rental_Apply_Equipment_Set_Detail__c>();
            //Map<Id, Rental_Apply_Equipment_Set_Detail__c> raesdMap = getDetailsMap(); // 取最新的明细数据
            List<EsdInfo> esdListBase = getEsdInfos(); // 取最新的明细数据做检查
            checkCanChangeResult(esdListBase, esdList);

            Map<Id, Rental_Apply_Equipment_Set_Detail__c> raesIdMainMap = new Map<Id, Rental_Apply_Equipment_Set_Detail__c> (); // 一览Id->主体Id, 用于构建一览内的link
            Set<Id> assIdSet = new Set<Id>(); // 明细所连的asset，用于加锁
            Map<String, Fixture_OneToOne_Link__c> newLinkMap = new Map<String, Fixture_OneToOne_Link__c>(); // 主Id:附Id->新link

            for(Integer i = 0; i < esdList.size();i++) {
                EsdInfo esd = esdList[i];
                if((esd.checked || raesIdMainMap.containsKey(esd.rec.Rental_Apply_Equipment_Set__c)) && !esd.hidden) {
                    hasChecked = true;

                    Rental_Apply_Equipment_Set_Detail__c raesd = esdListBase[i].rec;
                    assIdSet.add(raesd.Asset__c);
                    // 回库确认
                    if(raesd.Arrival_wh_Result_Agency__c != esd.rec.Arrival_wh_Result_Agency__c) {
                        if(String.isBlank(raesd.Check_lost_Item_F__c) || !raesd.CDS_complete__c) {
                            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, raesd.Fixture_Model_No__c + '未完成欠品确认&CDS，不可回库！'));
                            return;
                        }
                        if(String.isBlank(esd.rec.Arrival_wh_Result_Agency__c)) {
                            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, raesd.Fixture_Model_No__c + '回库结果不可为空！'));
                            return;
                        }
                        if(String.isNotBlank(esdList[i].errorInfo)) {
                            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, esdList[i].errorInfo));
                            return;
                        }
                        raesd.Arrival_wh_Result_Agency__c = esd.rec.Arrival_wh_Result_Agency__c;
                        if(raesd.Arrival_wh_Result_Agency__c == 'OK') {
                            raesd.Inspection_result_after__c = 'OK';
                            raesd.Inspection_result_after_NG__c = null;
                            raesd.After_Inspection_time__c = now;
                            raesd.Inspection_staff_After__c = userId;
                        }
                        else if(raesd.Arrival_wh_Result_Agency__c == '移至报废区') {
                            raesd.Inspection_result_after__c = 'NG';
                            raesd.Inspection_result_after_NG__c = '废弃';
                            raesd.After_Inspection_time__c = now;
                            raesd.Inspection_staff_After__c = userId;
                        }
                        else if(raesd.Arrival_wh_Result_Agency__c == '待修理') {
                            raesd.Inspection_result_after__c = 'NG';
                            raesd.Inspection_result_after_NG__c = '维修';
                            raesd.After_Inspection_time__c = now;
                            raesd.Inspection_staff_After__c = userId;
                        }
                        if(!raesd.Arrival_in_wh__c) {
                            raesd.Arrival_in_wh__c = true;
                            raesd.Arrival_wh_time_Agency_First__c = now;
                            raesd.Arrival_wh_After_2_Workday__c = afterTwoWorkday;
                            raesd.Return_wh_chenk_staff__c = userid;
                        }
                        raesd.Arrival_wh_time__c = now;
                        updateRaesdMap.put(raesd.Id, raesd);
                    }
                    if(raesd.OneToOne_Flag__c && raesd.SeparateFromMain__c == esd.needLink) {
                        raesd.SeparateFromMain__c = !esd.needLink;
                        updateRaesdMap.put(raesd.Id, raesd);
                    }
                    // 需要建link的主体
                    if(raesd.Is_Body__c){
                        raesIdMainMap.put(esd.rec.Rental_Apply_Equipment_Set__c, raesd);
                    }
                    // 每次回库时都会根据当前回库情况，重新刷一遍
                    if(raesd.OneToOne_Flag__c) {
                        // 获取主体明细
                        Rental_Apply_Equipment_Set_Detail__c mainRaesd = null;
                        if(raesIdMainMap.containsKey(raesd.Rental_Apply_Equipment_Set__c)) {
                            mainRaesd = raesIdMainMap.get(raesd.Rental_Apply_Equipment_Set__c);
                        }
                        if(mainRaesd != null) {
                            // 主体和附属品都cds完成，但上架不一致，报错
                            if(mainRaesd.CDS_complete__c && raesd.CDS_complete__c
                                && mainRaesd.Arrival_in_wh__c != raesd.Arrival_in_wh__c) {
                                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, mainRaesd.Fixture_Model_No__c + '必须整套上架！'));
                                return;
                            }
                            String key = mainRaesd.Asset__c + ':' + raesd.Asset__c;
                            Fixture_OneToOne_Link__c link;
                            if(newLinkMap.containsKey(key)) {
                                link = newLinkMap.get(key);
                            }
                            else {
                                link = new Fixture_OneToOne_Link__c(Quantity__c=0, CountForRepair__c=0, Abandoned_RealThing__c=0);
                            }
                            // 主体废弃或修理，附属品只要上架就建link
                            if((mainRaesd.Arrival_wh_Result_Agency__c == '移至报废区' || mainRaesd.Arrival_wh_Result_Agency__c == '待修理')
                                && !raesd.SeparateFromMain__c) {
                                link.Quantity__c += 1;
                                // 附属不OK时，占用link的一对一附属品管理数量
                                switch on raesd.Arrival_wh_Result_Agency__c {
                                    when '待修理' {
                                        link.CountForRepair__c += 1;
                                    }
                                    when '移至报废区' {
                                        link.Abandoned_RealThing__c += 1;
                                    }
                                }
                            }
                            // 主体OK，附属品只有OK才建link
                            else if(mainRaesd.Arrival_wh_Result_Agency__c == 'OK' && raesd.Arrival_wh_Result_Agency__c == 'OK'
                                && !raesd.SeparateFromMain__c) {
                                link.Quantity__c += 1;
                            }
                            // 主体欠品但没放弃，附属品只有OK才建link
                            else if(mainRaesd.Check_lost_Item_F__c == '欠品' && !mainRaesd.Lost_item_giveup__c
                                && raesd.Arrival_wh_Result_Agency__c == 'OK' && !raesd.SeparateFromMain__c) {
                                link.Quantity__c += 1;
                            }
                            else {
                                raesd.SeparateFromMain__c = true;
                                updateRaesdMap.put(raesd.Id, raesd);
                            }
                            newLinkMap.put(key, link);
                        }
                    }
                }
            }
            if(!hasChecked) {
                ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '未选择操作的一览'));
                return;
            }
            Oly_TriggerHandler.bypass(AssetHandlerCheck.class.getName());
            if(!updateRaesdMap.isEmpty()) {
                List<Asset> assList = [SELECT Id FROM Asset WHERE Id IN:assIdSet FOR UPDATE];
                FixtureUtil.withoutUpdate(updateRaesdMap.values());
                //print('更新明细',updateRaesdMap);
                done_flg = true;
            }
            if(!newLinkMap.isEmpty()) {
                createLinks(newLinkMap);
                done_flg = true;
            }
            Oly_TriggerHandler.clearBypass(AssetHandlerCheck.class.getName());

            if(done_flg) {
                init();
                done_flg = true;
            }
            //print('更新后Asset',[SELECT Id
            //    , Name
            //    , You_Xiao_Ku_Cun__c
            //    , Abandoned_RealThing__c
            //    , CountForRepair__c
            //    , In_wh_Fu_Shu_Pin_You_Xiao_Ku_Cun_Sum__c
            //    , Ji_Zhong_Guan_Li_Ku_Cun__c
            //    , Rental_Count__c
            //     FROM Asset WHERE Id IN:assIdSet]);
            //print('更新后link',[
            //    SELECT Id
            //    , Quantity__c
            //    , In_wh_Fu_Shu_Pin_You_Xiao_Ku_Cun_F__c
            //    , Accessory_Asset__r.Name
            //    , Abandoned_RealThing__c
            //    , CountForRepair__c
            //    , Select_Accessory_Asset_Cnt__c
            //    FROM Fixture_OneToOne_Link__c
            //    WHERE Main_Asset__c IN:assIdSet
            //       AND Accessory_Asset__c IN:assIdSet]);
            //Database.rollback(sp);
        }
        catch (Exception ex) {
            system.debug('=====' + ex.getMessage());
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, ex.getMessage()));
            Database.rollback(sp);
            done_flg = false;
        }
    }
    /**
    @description 新建link或向已有的link加数量
    @param newLinkMap 主Id:附Id->待新建的link
    */
    private void createLinks(Map<String, Fixture_OneToOne_Link__c> newLinkMap) {
        Set<Id> mainIdSet = new Set<Id>();
        // 收集主体Id
        for(String otoKey:newLinkMap.keySet()) {
            String mainId = otoKey.split(':')[0];
            mainIdSet.add(mainId);
        }
        Map<Id, Asset> assMap = new Map<Id, Asset>([
            SELECT Id
                 , You_Xiao_Ku_Cun__c
                 , Abandoned_RealThing__c
                 , CountForRepair__c
                 , Last_Reserve_RAES_Detail__r.Rental_Apply__c
              FROM Asset
             WHERE Id IN:mainIdSet
        ]);
        Set<String> uselessKey = new Set<String>();
        // 检查主体保有设备是否可以建link
        for(String otoKey:newLinkMap.keySet()) {
            String mainId = otoKey.split(':')[0];
            if(!assMap.containsKey(mainId)) {
                throw new ControllerUtil.myException(mainId + '保有设备不存在！');
            }
            else {
                Asset ass = assMap.get(mainId);
                // 主体保有设备有库存时才建link
                if(ass.Last_Reserve_RAES_Detail__r.Rental_Apply__c != parentObj.Id
                    && intValueOf(ass.You_Xiao_Ku_Cun__c) + intValueOf(ass.Abandoned_RealThing__c) + intValueOf(ass.CountForRepair__c) == 0) {
                    uselessKey.add(otoKey);
                }
            }
        }
        // 主体没库存时，上架后不用建link
        for(String otoKey: uselessKey) {
            newLinkMap.remove(otoKey);
        }
        if(newLinkMap.isEmpty()) {
            return;
        }
        Map<String, Fixture_OneToOne_Link__c> linkMap = new Map<String, Fixture_OneToOne_Link__c>(); // 主Id:附Id->link对象
        Map<String, Fixture_OneToOne_Link__c> deleteLinkMap = new Map<String, Fixture_OneToOne_Link__c>(); // 主Id:附Id->link对象
        String linkSql = 'SELECT Quantity__c, Abandoned_RealThing__c, CountForRepair__c, Main_Asset__c, Accessory_Asset__c FROM Fixture_OneToOne_Link__c WHERE ';
        for(String otoKey:newLinkMap.keySet()) {
            String mainId = otoKey.split(':')[0];
            String acceId = otoKey.split(':')[1];
            linkSql += '(Main_Asset__c = \'' + mainId + '\' AND Accessory_Asset__c = \''+acceId+'\') OR';
        }
        linkSql = linkSql.removeEnd('OR');
        List<Fixture_OneToOne_Link__c> matchingLinks = Database.query(linkSql);
        for(Fixture_OneToOne_Link__c link: matchingLinks) {
            linkMap.put(link.Main_Asset__c + ':' + link.Accessory_Asset__c, link);
        }
        for(String otoKey: newLinkMap.keySet()) {
            Fixture_OneToOne_Link__c link = new Fixture_OneToOne_Link__c();
            // 修改现有link里的数量，如果数量完全一致跳过更新
            if(linkMap.containsKey(otoKey)) {
                link = linkMap.get(otoKey);
                if(link.Quantity__c != newLinkMap.get(otoKey).Quantity__c
                    || link.Abandoned_RealThing__c != newLinkMap.get(otoKey).Abandoned_RealThing__c
                    || link.CountForRepair__c != newLinkMap.get(otoKey).CountForRepair__c) {
                    link.Quantity__c = newLinkMap.get(otoKey).Quantity__c;
                    link.Abandoned_RealThing__c = newLinkMap.get(otoKey).Abandoned_RealThing__c;
                    link.CountForRepair__c = newLinkMap.get(otoKey).CountForRepair__c;
                }
                else {
                    linkMap.remove(otoKey);
                    continue;
                }
            }
            // 新建link
            else {
                link.Main_Asset__c = otoKey.split(':')[0];
                link.Accessory_Asset__c = otoKey.split(':')[1];
                link.Quantity__c = newLinkMap.get(otoKey).Quantity__c;
                link.Abandoned_RealThing__c = newLinkMap.get(otoKey).Abandoned_RealThing__c;
                link.CountForRepair__c = newLinkMap.get(otoKey).CountForRepair__c;
            }
            if(link.Quantity__c == 0) {
                if(link.Id != null) {
                    deleteLinkMap.put(otoKey, link);
                }
                linkMap.remove(otoKey);
            }
            else {
                linkMap.put(otoKey, link);
            }
        }
        if(!deleteLinkMap.isEmpty()) {
            FixtureUtil.withoutDelete(deleteLinkMap.values());
        }
        if(!linkMap.isEmpty()) {
            //print('更新link',linkMap);
            FixtureUtil.withoutUpsertObjects(linkMap.values());
        }
    }
    private Integer intValueOf(Decimal d) {
        if(d == null) {
            return 0;
        }
        return Integer.valueOf(d);
    }
    // 欠品确认&CDS按钮
    public void lostAndCDS() {
        done_flg = false;
        Map<Id, Rental_Apply_Equipment_Set_Detail__c> updateRaesdMap = new Map<Id, Rental_Apply_Equipment_Set_Detail__c>();
        Map<Id, Rental_Apply_Equipment_Set_Detail__c> raesdMap = getDetailsMap(); // 取最新的明细数据
        Set<Id> raesIdSet = new Set<Id>();
        Boolean hasChecked = false;
        Datetime now = System.now();
        for(EsdInfo esd:esdList) {
            if((esd.checked || raesIdSet.contains(esd.rec.Rental_Apply_Equipment_Set__c)) && !esd.hidden) {
                hasChecked = true;
                if(!raesdMap.containsKey(esd.rec.Id)) {
                    ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, esd.rec.Fixture_Model_No__c + '后台数据不存在，请刷新画面！'));
                    return;
                }
                raesIdSet.add(esd.rec.Rental_Apply_Equipment_Set__c);
                Rental_Apply_Equipment_Set_Detail__c raesd = raesdMap.get(esd.rec.Id);
                if(raesd.LastModifiedDate != esd.rec.LastModifiedDate) {
                    ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, esd.rec.Fixture_Model_No__c + '后台数据被 ' + raesd.LastModifiedBy.Name + ' 修改，请刷新画面！'));
                    return;
                }
                // 欠品最初是空或OK时，修改结果存到最初
                if(String.isBlank(raesd.Check_lost_Item__c) || raesd.Check_lost_Item__c == 'OK') {
                    if(esd.lostFinished != raesd.Check_lost_Item__c) {
                        raesd.Check_lost_Item__c = esd.lostFinished;
                        // 同城首次欠品时，记入回寄时间，使状态变成欠品中
                        if(isSameCity && raesd.Check_lost_Item__c == '欠品' && raesd.Asset_return_time__c == null) {
                            raesd.Asset_return_time__c = now;
                        }
                    }
                }
                // 欠品最初是欠品时，修改结果存到最终
                else if(esd.lostFinished != raesd.Check_lost_Item_F__c) {
                    if(esd.lostFinished == 'OK' && raesd.Return_DeliverySlip__c == null && !isSameCity) {
                        ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, esd.rec.Fixture_Model_No__c + '未回寄，欠品确认不可选OK'));
                        return;
                    }
                    else {
                        raesd.Check_lost_Item_Final__c = esd.lostFinished;
                    }
                }
                // 画面上的CDS与后台不一致时更新
                if(!raesd.CDS_complete__c && esd.cdsFinished == 'OK' ) {
                    raesd.CDS_complete__c = true;
                    // 人和时间在trigger里赋值
                }
                else if(raesd.CDS_complete__c && esd.cdsFinished != 'OK') {
                    raesd.CDS_complete__c = false;
                    raesd.CDS_complete_time__c = null;
                    raesd.CDS_staff__c = null;
                }
                if (String.isNotBlank(raesd.Check_lost_Item_Final__c)) {
                    if (raesd.Check_lost_Item_Final__c == '欠品' || raesd.Check_lost_Item_Final__c == '消耗' ) {
                        raesd.Return_DeliverySlip__c = null;
                        raesd.CDS_complete__c = false;
                        if (raesd.Check_lost_Item_Final__c == '欠品') raesd.NoItemReturn__c = false;
                    }
                }
                else {
                    raesd.Lost_item_check_staff_Final__c = null;
                    raesd.Lost_item_check_time_Final__c = null;
                    if (raesd.Check_lost_Item__c == '欠品' || raesd.Check_lost_Item__c == '消耗' ) {
                        raesd.Return_DeliverySlip__c = null;
                        raesd.CDS_complete__c = false;
                        if (raesd.Check_lost_Item__c == '欠品') raesd.NoItemReturn__c = false;
                    }
                    if (String.isBlank(raesd.Check_lost_Item__c)) {
                        raesd.Lost_item_check_staff__c = null;
                        raesd.Lost_item_check_time__c = null;
                    }
                }
                if (raesd.Lost_item_giveup__c && raesd.Check_lost_Item__c == null) {
                    raesd.Check_lost_Item__c = '欠品';
                    raesd.Return_DeliverySlip__c = null;
                }
                updateRaesdMap.put(raesd.Id, raesd);
            }
        }
        if(!hasChecked) {
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, '未选择操作的一览'));
            return;
        }
        Savepoint sp = Database.setSavepoint();
        try {
            if(!updateRaesdMap.isEmpty()) {
                createReturnDelivery(updateRaesdMap);
                FixtureUtil.withoutUpdate(updateRaesdMap.values());
                init();
                done_flg = true;
                //Database.rollback(sp);
            }
        }
        catch (Exception ex) {
            system.debug('=====' + ex.getMessage());
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, ex.getMessage()));
            Database.rollback(sp);
        }
    }
    /**
    @description 回寄单字段赋值或清空
    @param updateRaesdMap 待更新的明细
    */
    private void createReturnDelivery(Map<Id, Rental_Apply_Equipment_Set_Detail__c> updateRaesdMap) {
        Boolean needDummy = false;
        for(Id raesdId: updateRaesdMap.keySet()) {
            Rental_Apply_Equipment_Set_Detail__c raesd = updateRaesdMap.get(raesdId);
            String lost = '';
            if(String.isNotBlank(raesd.Check_lost_Item_Final__c)) {
                lost = raesd.Check_lost_Item_Final__c;
            }
            else {
                lost = raesd.Check_lost_Item__c;
            }
            if(lost == 'OK' && raesd.Return_DeliverySlip__c == null && (isSameCity || raesd.NoItemReturn__c)) {
                needDummy = true;
                break;
            }
        }
        FixtureDeliverySlip__c slip;
        Datetime now = System.now();
        if(needDummy) {
            String slipNo = parentObj.Name + '_Dummy';
            List<FixtureDeliverySlip__c> slips = [
                SELECT Id
                  FROM FixtureDeliverySlip__c
                 WHERE Name =:slipNo
                   AND DeliveryType__c = '回寄'
                 LIMIT 1
            ];
            if(!slips.isEmpty()) {
                slip = slips[0];
            }
            else {
                slip = new FixtureDeliverySlip__c(Name=slipNo
                    , DeliveryType__c = '回寄'
                    , Distributor_method__c = '其他'
                    , DeliveryCompany__c = '其他'
                    , Shippment_loaner_time__c = now
                    , Wh_Staff__c=Userinfo.getUserId());
                FixtureUtil.withoutInsert(new List<FixtureDeliverySlip__c> {slip});
            }
        }

        for(Id raesdId: updateRaesdMap.keySet()) {
            Rental_Apply_Equipment_Set_Detail__c raesd = updateRaesdMap.get(raesdId);
            String lost = '';
            if(String.isNotBlank(raesd.Check_lost_Item_Final__c)) {
                lost = raesd.Check_lost_Item_Final__c;
            }
            else {
                lost = raesd.Check_lost_Item__c;
            }
            if(lost == 'OK' && raesd.Return_DeliverySlip__c == null && (isSameCity || raesd.NoItemReturn__c)) {
                raesd.Return_DeliverySlip__c = slip.Id;
                raesd.Asset_return_time__c = now;
                updateRaesdMap.put(raesd.Id, raesd);
            }
        }
    }
    //// 调试用
    //private void print(String title, Map<String, Object> m) {
    //    ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Info, title));
    //    for(String a:m.keyset()) {
    //        ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Info, '' + m.get(a)));
    //    }
    //}
    //// 调试用
    //private void print(String title, Map<Id, Object> m) {
    //    ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Info, title));
    //    for(Id a:m.keyset()) {
    //        ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Info, '' + m.get(a)));
    //    }
    //}
    //// 调试用
    //private void print(String title, List<Object> l) {
    //    ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Info, title));
    //    for(Object o:l) {
    //        ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Info, '' + o));
    //    }
    //}

    public class EsdInfo {
        public Rental_Apply_Equipment_Set_Detail__c rec { get; set; }
        public Asset rec2 { get; set; }
        public String errorInfo { get; set; }
        public String accessorySetId { get; set; }
        public boolean editable { get; set; }
        public Boolean checked {get;set;}
        //public Boolean needsetone { get; set; }
        public String cdsFinished {get;set;}
        public String lostFinished {get;set;}
        public Boolean hidden {get;set;}
        public Boolean canChangeResult{get;set;} // 是否可修改回库结果
        public Boolean needLink{get;set;} //

        public EsdInfo(Rental_apply_equipment_Set_Detail__c rec) {
            this.rec = rec;
            this.editable = false;
            this.checked = false;
            this.lostFinished = rec.Check_lost_Item_F__c;
            this.hidden = false;
            this.cdsFinished = rec.CDS_complete__c ? 'OK' : '';
            this.canChangeResult = true;
            this.needLink = !rec.Is_Body__c;
        }
    }
}