global with sharing class TransferApplySelectDetailController extends CreateRelationListPagingCtrlBase {
    public override Integer getSearchNumMax() {
        //各ページに制御あれば、最大件数を指定する
        // searchNumMax = Integer.valueOf(Label.Product_Select_Limit);
        // searchNumMax = 20;
        pagesize = '1000'; // 一页实际显示的行数受SHOW_SIZE控制
        return searchNumMax;
    }
    //20210814 ljh 管理编码 start
    public transient static Map<String,String> locationMap;
    static {
        locationMap = new Map<String, String> {
            '北京 备品中心' => 'BJ',
            '上海 备品中心' => 'SH',
            '广州 备品中心' => 'GZ'
        };
    }
    //20210814 ljh 管理编码 end
    /* 選択されたデータ取得用Soql　Fromから*/
    public override String getSelectedDataSql() {
        // オブジェクトAPI名
        selectedDataSql = ' From TransferApplyDetail__c';
        selectedDataSql += ' where TransferApply__c = \'' + String.escapeSingleQuotes(parentId) + '\'';
        selectedDataSql += ' and Cancel_Select__c = false';
        selectedDataSql += ' order by TransferApplySummary__c, Main_OneToOne__c desc, Asset__c, IndexFromUniqueKey__c';
        for(String field:FIELD_NAME_MAP.keySet()) {
            myComponentController.columnRightRW.put(field, 'r');
        }
        myComponentController.columnRightRW.put('OneToOneAccessory__c', 'r');
        myComponentController.columnRightRW.put('VF_TransferCount__c', 'w');
        myComponentController.columnRightRW.put('VF_TransferCount_Abandoned__c', 'w');
        myComponentController.columnRightRW.put('VF_TransferCount_Repair__c', 'w');
        myComponentController.columnRightRW.put('VF_TransferCount_Lost__c', 'w');
        myComponentController.columnRightRW.put('SalesProvince_After__c', 'w');
        myComponentController.columnRightRW.put('Salesdepartment_After__c', 'w');
        myComponentController.columnRightRW.put('EquipmentSet_Managment_Code_After__c', 'w');
        myComponentController.columnRightRW.put('Equipment_Type_After__c', 'w');
        myComponentController.columnRightRW.put('WH_location__c', 'w');
        // 20210814 ljh 管理编码        
        myComponentController.columnRightRW.put('CodeKey__c', 'r');
        myComponentController.columnRightRW.put('CreatedDate', 'r');
        // 20210814 ljh 管理编码
        return selectedDataSql;
    }

    public override String getOriginObjName() {
        // オブジェクトAPI名
        originObjName = 'Asset';
        return originObjName;
    }
    public override String getOriginObjColumns() {
        // 項目セット
        List<String> cols = FIELD_NAME_MAP.values();
        originObjColumns = String.join(cols, ', ') ;
        return originObjColumns;
    }

    public override String getObjName() {
        // オブジェクトAPI名
        objName = 'TransferApplyDetail__c';
        return objName;
    }
    public override String getColumnLeftFieldSetName() {
        // 左の項目セット
        columnLeftFieldSetName = '';
        return columnLeftFieldSetName;
    }
    public override String getColumnRightFieldSetName() {
        // 右の項目セット
        columnRightFieldSetName = '';
        switch on (parentObj.RecordType.DeveloperName) {
            when 'AgencyToCenter' {
                columnRightFieldSetName = 'TransferApplySelectDetailAgency';
            }
            when 'InsideCenter' {
                columnRightFieldSetName = 'TransferApplySelectDetailInside';
            }
            when 'CenterToOther' {
                columnRightFieldSetName = 'TransferApplySelectDetailOther';
            }
            when else {
                columnRightFieldSetName = 'TransferApplySelectDetailCenter';
            }
        }

        return columnRightFieldSetName;
    }
    public override Boolean getShowRecordCountMSG() {
        return false;
    }
    public override List<String> getColumnFieldList() {
        // strColumus 里加 field
        // FixtureUtil#raesdGroupByAssetId()の項目も必要
        List<String> cols = new List<String>{'TransferApplySummary__c'
                                , 'Approved_F__c'
                                , 'StockDown__c'
                                , 'OneToOneAccessory__c'
                                , 'TransferType__c'
                                , 'Cancel_Select__c'
                                , 'DeliverySlip__c'
                                , 'Fixture_OneToOne_Link__c'
                                , 'Request_time__c'
                                , 'Add_Request_demo_time__c'
                                , 'Fixture_OneToOne_Link__r.In_wh_Fu_Shu_Pin_You_Xiao_Ku_Cun_F__c'
                                , 'Fixture_OneToOne_Link__r.Abandoned_RealThing__c'
                                , 'Fixture_OneToOne_Link__r.CountForRepair__c'
                                , 'FSD_SortInt__c'
                                , 'IndexFromUniqueKey__c'
                                , 'Salesdepartment_After__c'
                                , 'VF_TransferCount_Repair__c' //20210814 ljh add  SFDC-C5K393
                                , 'VF_TransferCount_Lost__c' //20210814 ljh add SFDC-C5K393
                                , 'VF_TransferCount_Abandoned__c' //20210814 ljh add SFDC-C5K393
                                , 'VF_TransferCount__c' //20210814 ljh add SFDC-C5K393
                                , 'Equipment_Type_After__c' //20210818 ljh add SFDC-C5K393
                                , 'SalesProvince_After__c' //20210818 ljh add SFDC-C5K393
                                , 'EquipmentSet_Managment_Code_After__c' //20210818 ljh add SFDC-C5K393
                                , 'WH_location__c' //20210818 ljh add SFDC-C5K393
                                , 'CodeKey__c' // 20210814 ljh 管理编码
                                , 'CreatedDate' // 20210814 ljh 管理编码
                            };
        for(String field:FIELD_NAME_MAP.keySet()) {
            cols.add('Asset__r.' + FIELD_NAME_MAP.get(field));
            cols.add(field);
        }
        return cols;
    }

    public override String getFKColumnField() {
        // getObjName 连 getOriginObjName 的 FK
        return '';
    }

    public override String getRecordTypeId() {
        //ページレイアウトを収得するのレコードタイプ
        recordTypeId = '';
        return recordTypeId;
    }

    // ページコントローラに検索処理は、WhereSoql作成のみ、パラメータとして、コンポーネントに渡される
    public override String getSqlWhereStr() {
        sqlWhereStr = '';

        if (getIsNeedRunSearch()) {
            sqlWhereStr = this.makeSoql(keyword, assetnumber);
        }
        //20201215 ljh add start
        if(raAssetId != null && raAssetId.size() > 0){
            List<String> raAssetIdList = new List<String>(raAssetId);
            //System.debug('raAssetIdList:'+raAssetIdList);
            String sqlTail = '(\'';
            for(Integer i = 0 ; i< raAssetIdList.size();i++){
                if(i<raAssetIdList.size()-1){
                    sqlTail += raAssetIdList[i]+'\',\'';
                }else{
                    sqlTail += raAssetIdList[i]+'\')';
                }
            }
            sqlWhereStr += ' and Id IN '+sqlTail;
        }

        //20201215 ljh add end
        return sqlWhereStr;

    }

    public override String getOrderbyStr() {
        String ordStr = 'order by Fixture_Model_No_F__c';
        return ordStr;
    }

    public override Boolean getIsNeedRunSearch() {
        return this.searchAsset;
    }

    /*****************検索用******************/


    /*****************ソート時再検索条件（画面からの入力条件を無視するため）******************/
    public String keyword { get; set; }
    public String assetnumber {get; set;}
    public TransferApply__c parentObj { get; private set; }
    private List<TransferApplySummaryBean> tasBeanList{get;set;} // 全部的，包括申请单下已有的、导入的和检索出的
    private List<TransferApplySummaryBean> filteredTasBeanList {get;set;} // tasBeanList的子集，需要在画面上显示的，

    public Boolean isCenter {get;set;}
    public Boolean readonly {get;set;}
    public Integer detailCountLimit{get;private set;}
    private Boolean searchAsset {get;set;}
    public String fieldName {get;set;}
    public String fieldValue {get;set;}
    public String operator {get;set;}
    public static Integer SHOW_SIZE = 20 ; // 一页实际显示多少个行

    public String raId { get; private set; }//20201215 ljh /// start
    public String newid { get; private set; }//20201215 ljh add start
    public Boolean isComeFromRa { get; private set; } //20201215 ljh add start
    public Set<String> raAssetId; //20201215 ljh add start
    public Map<Id, Map<String, Integer>> raAssetCountMap; // 从借出申请创建，记录设备数量，设备Id->调拨分类->数量
    public TransferApplySelectDetailController() {
        parentId = ApexPages.currentPage().getParameters().get('id');
        tasBeanList = new List<TransferApplySummaryBean>();
        filteredTasBeanList  = new List<TransferApplySummaryBean>();
        raAssetCountMap = new Map<Id, Map<String, Integer>>();
        detailCountLimit = 10000;
        searchAsset = false;
        isComeFromRa = false;
        isCenter = true;
        readonly = false;
        if (String.isBlank(this.parentId)) {
            raId = ApexPages.currentPage().getParameters().get('raid');
            if(!String.isBlank(this.raId)){
                this.parentId = ApexPages.currentPage().getParameters().get('newid');
                //isCenter 这个是判断是否是备品中心操作，虽然此时一定是办事处但是isCenter是false不一定从备品出借过来的
                isComeFromRa = true;
            }
        }
        parentObj = getParentObj(false);
    }
    /**
    @description 获取最新的申请数据，并做检查，要放到try里
    @param needCheck 是否做检查
    @return 最新的申请
    */
    private TransferApply__c getParentObj(Boolean needCheck) {
        TransferApply__c ta = null;
        if (!String.isBlank(this.parentId)) {
            List<TransferApply__c> taList = [
                SELECT Id
                     , Add_Approval_Status__c
                     , Status__c
                     , RecordType.DeveloperName
                     , From_Location__c
                     , Rental_Apply__c //20200105 ljh add
                     , LastModifiedDate
                     , LastModifiedBy.Name
                     , Request_approval_time__c
                     , Yi_loaner_arranged__c
                     , DeliverySlip__c
                     , TA_Status__c
                     , Destination_location__c // 20210826 ljh 管理编码
                  FROM TransferApply__c
                 WHERE Id=:parentId
            ];
            if(taList.isEmpty()) {
                throw new ControllerUtil.myException('参数错误：请指定Id。');
            }
            else{
                ta = taList[0];
                if(needCheck) {
                    if(parentObj != null && parentObj.LastModifiedDate != ta.LastModifiedDate) {
                        throw new ControllerUtil.myException('后台数据被 ' + ta.LastModifiedBy.Name + ' 修改，请刷新画面！');
                    }
                    if(ta.RecordType.DeveloperName == 'InsideCenter' && ta.Status__c != '草案中') {
                        throw new ControllerUtil.myException('同备品中心调拨类型，提交审批后不可修改！');
                    }
                    else if(ta.DeliverySlip__c != null) {
                        throw new ControllerUtil.myException('申请单已出库，不可修改明细！');
                    }
                }
                isCenter = ta.RecordType.DeveloperName != 'AgencyToCenter';
                if (String.isNotBlank(ta.Rental_Apply__c)) {
                    raId = ta.Rental_Apply__c;
                    //从备品出借过来的
                    isComeFromRa = true;
                }
                if(ta.Yi_loaner_arranged__c > 0 || ta.Status__c == '申请中' || ta.Add_Approval_Status__c == '申请中') {
                    readonly = true;
                }
                else if(ta.RecordType.DeveloperName == 'InsideCenter' && ta.TA_Status__c == '已更新') {
                    readonly = true;
                }
                else {
                    readonly = false;
                }
            }
        } else {
            throw new ControllerUtil.myException('参数错误：请指定Id。');
        }
        return ta;
    }
    private void loadAssetMap(Id assId, String transferType) {
        if(raAssetCountMap == null) {
            raAssetCountMap = new Map<Id, Map<String, Integer>>();
        }
        Map<String, Integer> cntMap = null;
        if(raAssetCountMap.containsKey(assId)) {
            cntMap = raAssetCountMap.get(assId);
        }
        else {
            cntMap = new Map<String, Integer>{'待修理'=>0,'待废弃'=>0,'有效库存'=>0,'丢失找回'=>0};
        }
        cntMap.put(transferType, cntMap.get(transferType) + 1);
        raAssetCountMap.put(assId, cntMap);
    }
    public void init() {
        //20201215 ljh add start
        if(isComeFromRa){
            //查找符合要求的保有设备
            raAssetId = new Set<String>();
            List<Rental_Apply_Equipment_Set_Detail__c> raesdList = [SELECT Id,Name,Lost_item_giveup__c,Arrival_in_wh__c,Arrival_wh_Result_Agency__c
            ,Rental_Apply_Equipment_Set__r.First_RAESD__r.Arrival_in_wh__c
            ,Rental_Apply_Equipment_Set__r.First_RAESD__r.Arrival_wh_Result_Agency__c
            ,Rental_Apply_Equipment_Set__r.First_RAESD__r.Lost_item_giveup__c
            ,Rental_Apply_Equipment_Set__r.First_RAESD__r.Asset__c
            ,Is_Body__c,Asset__c,Rental_Apply__c,Lost_Item_return__c,OneToOne_Flag__c
            ,Check_lost_Item__c,Check_lost_Item_Final__c,Rental_Apply_Equipment_Set__r.First_You_Xiao_Ku_Cun__c
            ,Rental_Apply_Equipment_Set__r.First_RAESD__r.Arrival_wh_time__c,Arrival_wh_time__c
            FROM Rental_Apply_Equipment_Set_Detail__c WHERE Rental_Apply__c = :raId AND Cancel_Select__c = false];
            for(Rental_Apply_Equipment_Set_Detail__c raesd:raesdList){
                if(raesd.Asset__c != null){
                    //画面默认且仅显示符合调拨要求的数据（①欠品断念后找回的主体 ②（主体上架ok）欠品断念后找回的附属品 ③主体待修理的整个配套 ④（主体上架ok）待修理的附属品）⑤主体断念后单独的附属品
                    if(raesd.Is_Body__c){
                        //①欠品断念后主体
                        if(raesd.Lost_item_giveup__c ){
                            raAssetId.add(raesd.Asset__c);
                        }
                        //②主体待修理/移至报废区
                        if(raesd.Arrival_wh_Result_Agency__c != null && (raesd.Arrival_wh_Result_Agency__c == '待修理' || raesd.Arrival_wh_Result_Agency__c == '移至报废区' )){
                            raAssetId.add(raesd.Asset__c);
                        }
                    }else{
                        //①主体欠品断念后的整个配套(不是欠品的附属品)
                        //有主体得是一对一附属品
                        if(raesd.Rental_Apply_Equipment_Set__r.First_RAESD__r.Lost_item_giveup__c  &&
                        raesd.OneToOne_Flag__c  &&
                        raesd.Arrival_wh_Result_Agency__c != null) {
                            raAssetId.add(raesd.Asset__c);
                            if(raesd.Arrival_wh_Result_Agency__c == '待修理') {
                                loadAssetMap(raesd.Asset__c, '待修理');
                            }
                            else if(raesd.Arrival_wh_Result_Agency__c == '移至报废区') {
                                loadAssetMap(raesd.Asset__c, '待废弃');
                            }
                            else {
                                loadAssetMap(raesd.Asset__c, '有效库存');
                            }
                        }
                        //②（主体上架ok）待修理的附属品
                        if(raesd.Rental_Apply_Equipment_Set__r.First_RAESD__r.Arrival_wh_Result_Agency__c !=null &&
                        raesd.Rental_Apply_Equipment_Set__r.First_RAESD__r.Arrival_wh_Result_Agency__c == 'OK'  &&
                        raesd.OneToOne_Flag__c  &&
                        raesd.Arrival_wh_Result_Agency__c != null && (raesd.Arrival_wh_Result_Agency__c == '待修理' || raesd.Arrival_wh_Result_Agency__c == '移至报废区')){
                            raAssetId.add(raesd.Asset__c);
                            if(raesd.Arrival_wh_Result_Agency__c == '待修理') {
                                loadAssetMap(raesd.Asset__c, '待修理');
                            }
                            else if(raesd.Arrival_wh_Result_Agency__c == '移至报废区') {
                                loadAssetMap(raesd.Asset__c, '待废弃');
                            }
                        }
                        //⑤ （主体上架ok）断念后的附属品
                        if(raesd.Rental_Apply_Equipment_Set__r.First_RAESD__r.Arrival_wh_Result_Agency__c !=null &&
                        raesd.Rental_Apply_Equipment_Set__r.First_RAESD__r.Arrival_wh_Result_Agency__c == 'OK'  &&
                        raesd.OneToOne_Flag__c  &&
                        raesd.Lost_item_giveup__c ){
                            raAssetId.add(raesd.Asset__c);
                            loadAssetMap(raesd.Asset__c, '丢失找回');
                        }
                        //20210120  add start
                        if(raesd.Rental_Apply_Equipment_Set__r.First_You_Xiao_Ku_Cun__c <= 0
                        && raesd.OneToOne_Flag__c  && String.isNotBlank(raesd.Check_lost_Item__c) && String.isNotBlank(raesd.Check_lost_Item_Final__c) && raesd.Check_lost_Item__c == '欠品' && raesd.Check_lost_Item_Final__c == 'OK'
                        && raesd.Arrival_in_wh__c && raesd.Arrival_wh_time__c != raesd.Rental_Apply_Equipment_Set__r.First_RAESD__r.Arrival_wh_time__c){
                            raAssetId.add(raesd.Asset__c);
                            if(raesd.Arrival_wh_Result_Agency__c == '待修理') {
                                loadAssetMap(raesd.Asset__c, '待修理');
                            }
                            else if(raesd.Arrival_wh_Result_Agency__c == '移至报废区') {
                                loadAssetMap(raesd.Asset__c, '待废弃');
                            }
                            else {
                                loadAssetMap(raesd.Asset__c, '有效库存');
                            }
                        }
                        //20210120  add end
                    }
                }
            }
            //System.debug('000111raAssetId:'+raAssetId);
            if(raAssetId.size() > 0){
                isNeedSearchFirst=true;
                this.searchAsset=true;
                getSqlWhereStr();
            }else{
                ApexPages.addMessage(new ApexPages.Message(ApexPages.severity.ERROR, '该申请没有符合条件的一览明细!'));
            }
        }else{
            isNeedSearchFirst = false;
        }
        //20201215 ljh add end
    }

    // 所在地区(本部)
    public List<SelectOption> salesdepartmentOpts {
        get {
            if (salesdepartmentOpts == null) {
                salesdepartmentOpts = getPickList('TransferApplyDetail__c', 'Salesdepartment__c');
            }
            return salesdepartmentOpts;
        }
        set;
    }
    // 所在地区(省)
    public List<SelectOption> salesProvinceOpts {
        get {
            if (salesProvinceOpts == null) {
                salesProvinceOpts = getPickList('TransferApplyDetail__c', 'SalesProvince__c');
            }
            return salesProvinceOpts;
        }
        set;
    }
    // 备品分类
    public List<SelectOption> equipmentTypeOpts {
        get {
            if (equipmentTypeOpts == null) {
                equipmentTypeOpts = getPickList('TransferApplyDetail__c', 'Equipment_Type__c');
            }
            return equipmentTypeOpts;
        }
        set;
    }
    public List<SelectOption> fieldNameOpts {
        get{
            List<SelectOption> selectOptions = new List<SelectOption> { new SelectOption('', '') };
            selectOptions.add(new SelectOption('Internal_asset_location__c' , '备品存放地'));
            selectOptions.add(new SelectOption('Salesdepartment__c' , '所在地区(本部)'));
            selectOptions.add(new SelectOption('Fixture_Model_No__c' , '型号'));
            selectOptions.add(new SelectOption('Internal_Asset_number_key__c' , '固定资产编号(Key)'));
            selectOptions.add(new SelectOption('Manage_type__c' , '管理种类'));
            selectOptions.add(new SelectOption('SerialNumber__c' , '机身编号'));
            selectOptions.add(new SelectOption('Main_OneToOne__c' , '是否一对一主体'));

            return selectOptions;
        }
    }
    public List<SelectOption> operatorOpts {
        get{
            List<SelectOption> selectOptions = new List<SelectOption> { new SelectOption('', '') };
            selectOptions.add(new SelectOption('==','等于'));
            selectOptions.add(new SelectOption('!=','不等于'));
            selectOptions.add(new SelectOption('<','<'));
            selectOptions.add(new SelectOption('>','>'));
            selectOptions.add(new SelectOption('<=','<='));
            selectOptions.add(new SelectOption('>=','>='));
            selectOptions.add(new SelectOption('contains','包含'));
            selectOptions.add(new SelectOption('notcontains','不包含'));
            selectOptions.add(new SelectOption('startswith','起始字符'));
            return selectOptions;
        }
    }
    public void clear() {
        fieldName = '';
        operator = '';
        fieldValue = '';
        myComponentController.page = 1;
        refreshViewList(tasBeanList);
    }
    public void filter() {
        if (String.isNotBlank(fieldName) && String.isNotBlank(operator)) {
            filteredTasBeanList.clear();
            for (TransferApplySummaryBean info : tasBeanList) {
                TransferApplyDetail__c tad = (TransferApplyDetail__c) info.wpinfoList[0].sObj;
                String fieldValueInRecord = tad.get(fieldName) == null ? '' :String.valueOf(tad.get(fieldName));
                if(fieldValue == null) {
                    fieldValue = '';
                }
                Boolean meet = false;
                if (operator == '==' && fieldValueInRecord == String.valueOf(fieldValue)) {
                    meet = true;
                }
                else if (operator == '!=' && fieldValueInRecord != String.valueOf(fieldValue)) {
                    meet = true;
                }
                else if (operator == '<' && fieldValueInRecord < String.valueOf(fieldValue)) {
                    meet = true;
                }
                else if (operator == '<=' && fieldValueInRecord <= String.valueOf(fieldValue)) {
                    meet = true;
                }
                else if (operator == '>' && fieldValueInRecord > String.valueOf(fieldValue)) {
                    meet = true;
                }
                else if (operator == '>=' && fieldValueInRecord >= String.valueOf(fieldValue)) {
                    meet = true;
                }
                else if (operator == 'contains' && fieldValueInRecord.contains(String.valueOf(fieldValue))) {
                    meet = true;
                }
                else if (operator == 'notcontains' && !fieldValueInRecord.contains(String.valueOf(fieldValue))) {
                    meet = true;
                }
                else if (operator == 'startswith' && fieldValueInRecord.startsWith(String.valueOf(fieldValue))) {
                    meet = true;
                }
                if (meet) {
                    filteredTasBeanList.add(info);
                }
            }
            Integer filterLimit = SHOW_SIZE;
            if (filteredTasBeanList.size() > filterLimit) {
                while (filteredTasBeanList.size() > filterLimit) {
                    filteredTasBeanList.remove(filterLimit);
                }
                ApexPages.addMessage(new ApexPages.Message(ApexPages.severity.WARNING, '满足条件的超过' + filterLimit + '条，此处只显示前' + filterLimit + '，请更换筛选条件'));
            }
        }
        else {
            ApexPages.addMessage(new ApexPages.Message(ApexPages.severity.ERROR, '请填写筛选条件'));
        }
        myComponentController.page = 1;
        refreshViewList(filteredTasBeanList);
    }
    // 检索按钮
    public PageReference searchOpp() {
        return searchOpp(true);
    }

    private PageReference searchOpp(Boolean searchAsset) {

        this.searchAsset = searchAsset;
        // 選択済みの製品を取得
        myComponentController.getSelectedDataInfo();

        getSqlWhereStr();

        // コンポーネントにSoqlを発行して、ページングする
        myComponentController.searchAndPaging();
        return null;
    }
    // 取消明细按钮
    public void cancelDetail() {
        Map<Id, TransferApplyDetail__c> delTadMap = new Map<Id, TransferApplyDetail__c>();
        Map<Id, TransferApplySummary__c> updateTasMap = new Map<Id, TransferApplySummary__c>();
        Map<Id, TransferApplyDetail__c> updateTadMap = new Map<Id, TransferApplyDetail__c>();
        Set<Id> assIdSet = new Set<Id>();
        Savepoint sp = Database.setSavepoint();
        try {
            parentObj = getParentObj(true);
            for(TransferApplySummaryBean tasBean : tasBeanList) {
                if(tasBean.wpinfoList[0].check) {
                    for(WrapperInfo wi: tasBean.wpinfoList) {
                        TransferApplyDetail__c tad = (TransferApplyDetail__c) wi.sobj;
                        if(parentObj.Status__c == '已批准' || parentObj.Yi_loaner_arranged__c == 0) { // 出库前可以做取消
                            if(tad.Approved_F__c) {
                                tad.Cancel_Select__c = true;
                                tad.Cancel_Reason__c = '主动取消';
                                assIdSet.add(tad.Asset__c);
                                updateTadMap.put(tad.Id, tad);
                            }
                            else if (tad.Id == null) {
                                throw new ControllerUtil.myException('未保存过的明细不可取消');
                            }
                            else { // 追加未审批的明细要删除
                                delTadMap.put(tad.Id, tad);
                            }
                        }
                        else {
                            throw new ControllerUtil.myException('不可以取消明细');
                        }
                    }
                }
            }
            for(Id tadId:delTadMap.keySet()) {
                if(updateTadMap.containsKey(tadId)) {
                    updateTadMap.remove(tadId);
                }
            }
            if(!delTadMap.isEmpty()) {
                delete delTadMap.values();
            }
            if(!updateTadMap.isEmpty()) {
                update updateTadMap.values();
            }
            // 追加批准状态处理
            updateAddApproval();
            // 取消成功时，把勾都去掉
            for(TransferApplySummaryBean tasBean : tasBeanList) {
                tasBean.wpinfoList[0].check = false;
            }
            searchOpp(false);
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Info, '取消成功'));
            parentObj = getParentObj(false);
            //print('更新后Asset',[SELECT Name,You_Xiao_Ku_Cun__c,TransferFrozenQuantity__c FROM Asset WHERE Id =: assIdSet]);
            //print('更新后link',[SELECT Name,In_wh_Fu_Shu_Pin_You_Xiao_Ku_Cun_F__c,TransferFrozenQuantity__c FROM Fixture_OneToOne_Link__c WHERE Main_Asset__c =: assIdSet]);
            //Database.rollback(sp);
        }
        catch (Exception ex) {
            System.debug(ex.getStackTraceString());
            ApexPages.addMessages(ex);
            Database.rollback(sp);
        }
    }
    // 调试用
    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 void importCSVFile() {
        String csvData = ApexPages.currentPage().getParameters().get('csvData');
        List<List<String>> tempCsvBody = CSVReader.readIETFRFC4180CSVFile(Blob.valueof(csvData));  // 全部CSV数据
        List<String> importLabelList = tempCsvBody[0];  // CSV读入的标题行
        Set<Id> assetIdSet = new Set<Id>();
        List<TransferApplyDetail__c> tadList = new List<TransferApplyDetail__c>();
        Integer importLine = 0;
        List<String> warningList = new List<String>();

        removeUncheckedTasBean();
        Set<Id> hideAssetIdSet = new Set<Id>(); // 个体管理的保有设备如果已经在明细中，则检索时不再显示
        removeUncheckedTasBean();
        for(TransferApplySummaryBean tasBean:tasBeanList) {
            for(WrapperInfo wf:tasBean.wpinfoList) {
                TransferApplyDetail__c tad = (TransferApplyDetail__c) wf.sObj;
                if(tad.Manage_type__c == '个体管理') {
                    hideAssetIdSet.add(tad.Asset__c);
                }
                else if(!tad.OnetoOneAccessory__c) { // 数量管理非一对一附属品，如果导入中已存在则不再在检索结果中显示
                    hideAssetIdSet.add(tad.Asset__c);
                }
            }
        }

        Map<String, String> labelToApiMap = createLabelApiMap();
        Map<String, SObjectField> queryAssetFieldMap = TransferApplyDetail__c.getSObjectType().getDescribe().fields.getMap();
        for (Integer i = 1; i < tempCsvBody.size(); i++) {
            TransferApplyDetail__c tempTad = new TransferApplyDetail__c();
            for (Integer j = 0; j < importLabelList.size(); j++) {
                String api = labelToApiMap.get(importLabelList[j]);
                if (queryAssetFieldMap.containsKey(api) == false) {
                    throw new ControllerUtil.myException('字段:【' + importLabelList[j] + '】在' + TransferApplyDetail__c.getSObjectType().getDescribe().getLabel() + '里不存在, 请确认。');
                }
                DescribeFieldResult queryAssetFieldResult = queryAssetFieldMap.get(api).getDescribe();
                if (String.isNotBlank(tempCsvBody[i][j])){
                    String value = String.valueOf(tempCsvBody[i][j]).trim();
                    if (queryAssetFieldResult.getType() == Schema.DisplayType.Date) {
                        tempTad.put(api, Date.valueOf(value));
                    } else if (queryAssetFieldResult.getType() == Schema.DisplayType.Boolean) {
                        tempTad.put(api, Boolean.valueOf(value));
                    } else if (queryAssetFieldResult.getType() == Schema.DisplayType.Double) {
                        tempTad.put(api, Decimal.valueOf(value));
                    } else {
                        tempTad.put(api, value);
                    }
                }
            }

            Id assetId = tempTad.Asset__c;
            if(String.isBlank(assetId)){
                throw new ControllerUtil.myException('【' + queryAssetFieldMap.get('Asset__c').getDescribe().getLabel() + '】不可为空' + tempTad);
            }
            else if(!hideAssetIdSet.contains(assetId)) {
                // 已导过的或申请下已存在的设备不重复显示
                assetIdSet.add(assetId);
                tadList.add(tempTad);
            }
        }
        if(assetIdSet.isEmpty()) {
            return;
        }

        String assSql = 'SELECT '
                      + String.join(FIELD_NAME_MAP.values(), ', ')
                      + ' FROM Asset ';
        assSql += this.makeSoql('','');
        assSql += ' and Id IN :assetIdSet';
        Map<Id, Asset> assetMap = new Map<Id, Asset>((List<Asset>)Database.query(assSql));
        Map<Id, TransferApplySummaryBean> mainTasBeanMap = new Map<Id, TransferApplySummaryBean> (); //主体保有设备Id->一览bean
        for(Integer i = 0; i < tadList.size(); i++) {
            TransferApplyDetail__c tad = tadList[i];
            Asset ass = null;
            if(assetMap.containsKey(tad.Asset__c)){
                ass = assetMap.get(tad.Asset__c);
            }
            else {
                warningList.add(tad.Asset__c+'不存在');
                continue;
            }
            for(String field:FIELD_NAME_MAP.keySet()) {
                tad.put(field, ass.get(FIELD_NAME_MAP.get(field)));
            }

            if(tad.VF_TransferCount_Abandoned__c > 0) {
                tad.TransferType__c = '待废弃';
            }
            else if(tad.VF_TransferCount_Repair__c > 0) {
                tad.TransferType__c = '待修理';
            }
            else if(tad.VF_TransferCount_Lost__c > 0) {
                tad.TransferType__c = '丢失找回';
            }
            else {
                tad.TransferType__c = '有效库存';
            }
            TransferApplySummaryBean tasBean = new TransferApplySummaryBean();
            if(ass.Main_OneToOne__c) {
                tad.Main_OneToOne__c = true;
                mainTasBeanMap.put(ass.Id, tasBean);
            }
            WrapperInfo wf = new WrapperInfo(tad, myComponentController);
            wf.check = true;
            tasBean.wpinfoList.add(wf);
            tasBeanList.add(tasBean);
            importLine++;
        }
        for(Integer i = 0; i < Math.min(5, warningList.size()); i++){
            ApexPages.addMessage(new ApexPages.Message(ApexPages.severity.WARNING, warningList[i]));
        }
        if (warningList.size() > 0) {
            ApexPages.addMessage(new ApexPages.Message(ApexPages.severity.WARNING, warningList.size() + '条记录不存在或不可调拨'));
        }
        if(importLine == 0) {
            ApexPages.addMessage(new ApexPages.Message(ApexPages.severity.WARNING, '未导入任何数据，请检查CSV文件'));
        }
        else {
            String importSuccessfulMsg = '导入CSV文件完成，成功导入' + importLine + '条数据。';
            ApexPages.addMessage(new ApexPages.Message(ApexPages.severity.INFO, importSuccessfulMsg));
            if(parentObj.RecordType.DeveloperName != 'InsideCenter') {
                addOnetoOneAccessories(mainTasBeanMap);
            }
            myComponentController.page = 1;
            refreshViewList(tasBeanList);
        }
    }

    private Map<String, String> createLabelApiMap(){
        Map<String,String> apiMap = new Map<String,String>();
        Map<String,Schema.SObjectField> mfields = TransferApplyDetail__c.sObjectType.getDescribe().fields.getMap();
        for(String strField:mfields.keySet()) {
            SObjectField fl = mfields.get(strField);
            apiMap.put(fl.getDescribe().getlabel(), strField);
        }
        return apiMap;
    }
    public PageReference savePage() {
        if(save()){
            searchOpp(isComeFromRa);
            ApexPages.addMessage(new ApexPages.Message(ApexPages.severity.INFO, '保存完了'));
        }
        return null;
    }
    public Boolean save() {

        Boolean done = false;
        List<TransferApplyDetail__c> upsertTadList = new List<TransferApplyDetail__c>();
        List<TransferApplyDetail__c> upsertTadMList = new List<TransferApplyDetail__c>();
        List<TransferApplyDetail__c> deleteTadList = new List<TransferApplyDetail__c>();
        List<TransferApplySummary__c> newTasList= new List<TransferApplySummary__c>();
        Savepoint sp = Database.setSavepoint();
        try {
            parentObj = getParentObj(true);
            // 找出现有型号->一览
            List<TransferApplySummary__c> tasList = [
                    SELECT First_TAD__r.Fixture_Model_No_F__c
                        , First_TAD__r.SerialNumber_F__c
                        , First_TAD__r.Main_OneToOne__c
                        , IndexFromUniqueKey__c
                        , TransferDetail_Cnt__c
                    FROM TransferApplySummary__c
                    WHERE TransferApply__c =:parentId AND Cancel_Select__c = false
            ];
            Map<String, TransferApplySummary__c> tasMap = new Map<String, TransferApplySummary__c>();
            Map<String, Integer> tasIndexMap = new Map<String, Integer>();
            List<TransferApplySummaryBean> beansForCheck = new List<TransferApplySummaryBean>();
            for(TransferApplySummary__c tas: tasList) {
                // 型号相同的数量附属品都放到一个一览里
                String tasKey = tas.First_TAD__r.Fixture_Model_No_F__c;
                // 型号相同的主体要分别构造一览（用序列号区分）
                if(tas.First_TAD__r.Main_OneToOne__c) {
                    tasKey += ':' + tas.First_TAD__r.SerialNumber_F__c;
                }
                tasMap.put(tasKey, tas);
            }
            Boolean FirstOnlyMain = false; //20210511 ljh 1832 add

            for(TransferApplySummaryBean tasBean:tasBeanList) {
                if(tasBean.wpinfoList[0].check) {
                    beansForCheck.add(tasBean);
                    TransferApplyDetail__c tad = (TransferApplyDetail__c) tasBean.wpinfoList[0].sObj;
                    String tasKey = tad.Fixture_Model_No__c;
                    if(tad.Main_OneToOne__c) {
                        tasKey += ':' + tad.SerialNumber__c;
                    }
                    TransferApplySummary__c tas = null;
                    if(!tasMap.containsKey(tasKey)) {
                        tas = new TransferApplySummary__c();
                        tas.TransferApply__c = parentId;
                        tas.Fixture_Set__c = tasBean.tas.Fixture_Set__c;
                        tasMap.put(tasKey, tas);
                    }
                    else {
                        tas = tasMap.get(tasKey);
                    }
                    if(tasIndexMap.containsKey(tad.Fixture_Model_No__c)) {
                        //20210511 ljh update 1832 start
                        //tas.IndexFromUniqueKey__c = tasIndexMap.get(tad.Fixture_Model_No__c);
                        if(tad.Main_OneToOne__c
                            ||
                            (tad.Main_OneToOne__c == false
                            && tad.Loaner_accsessary__c == false
                            && tad.OneToOneAccessory__c == false
                            && !FirstOnlyMain)
                        ) {
                            if(tad.Main_OneToOne__c == false && tad.Loaner_accsessary__c == false && tad.OneToOneAccessory__c == false){
                                FirstOnlyMain = true;
                            }
                            tas.IndexFromUniqueKey__c = tasIndexMap.get(tad.Fixture_Model_No__c)+1;
                        }
                        //20210511 ljh update 1832 end
                    }
                    else {
                        tas.IndexFromUniqueKey__c = 1;
                        //20210511 ljh add 1832 start
                        if(tad.Main_OneToOne__c == false && tad.Loaner_accsessary__c == false && tad.OneToOneAccessory__c == false){
                            FirstOnlyMain = true;
                        }
                        //20210511 ljh add 1832 end
                    }
                    //20210511 ljh update 1832 start
                    //if(tad.Main_OneToOne__c) {
                    //     tasIndexMap.put(tad.Fixture_Model_No__c, intValueOf(tas.IndexFromUniqueKey__c + 1));
                    // }
                    tasIndexMap.put(tad.Fixture_Model_No__c, intValueOf(tas.IndexFromUniqueKey__c));
                    //20210511 ljh update 1832 end
                }
            }
            // 检查待保存的明细
            List<String> errorList = checkDetails(beansForCheck);
            if(!errorList.isEmpty()) {
                for (String errMsg:errorList) {
                    ApexPages.addMessage(new ApexPages.Message(ApexPages.severity.ERROR, errMsg));
                }
                return false;
            }
            if(!tasMap.isEmpty()) {
                upsert tasMap.values();
            }
            Integer tadIndex = 1;
            Map<Id, Integer> tasMaxIndex  = new Map<Id, Integer> ();
            Id lastTasId = null;
            String lastModel = '';
            String lastDep = '';
            // 20210814 ljh 管理编码 add start
            Set<Id> tadClearId = new Set<Id>();
            Map<Id, TransferApplyDetail__c> codMap = new Map<Id, TransferApplyDetail__c>();
            Map<String, List<TransferApplyDetail__c>> codeNewMap = new Map<String, List<TransferApplyDetail__c>>();
            Map<String, List<TransferApplyDetail__c>> fmnMap = new Map<String, List<TransferApplyDetail__c>>();
            List<Asset_EquipmentSet_Managment_Code__c> aesmUList = new List<Asset_EquipmentSet_Managment_Code__c>();
            Set<Id> xl0TadId = new Set<Id>();
            List<TransferApplyDetail__c> tadBMList = new List<TransferApplyDetail__c>();
            List<TransferApplyDetail__c> tadBMNewList = new List<TransferApplyDetail__c>();// 20211122 ljh SFDC-C8W3HW
            String xl0 = System.Label.xl0String;
            List<String> xl0List = xl0.split(';');
            // 20210814 ljh 管理编码 add end
            for(TransferApplySummaryBean tasBean:tasBeanList) {
                if(tasBean.wpinfoList[0].check){
                    TransferApplyDetail__c mainTad = (TransferApplyDetail__c) tasBean.wpinfoList[0].sobj;
                    if(!mainTad.Main_OneToOne__c && !mainTad.OneToOneAccessory__c) {
                        List<TransferApplyDetail__c> upsertTadSubList = new List<TransferApplyDetail__c>();
                        prepareDetails(tasBean.wpinfoList, '有效库存', intValueOf(mainTad.VF_TransferCount__c), upsertTadSubList, deleteTadList);
                        prepareDetails(tasBean.wpinfoList, '待废弃', intValueOf(mainTad.VF_TransferCount_Abandoned__c), upsertTadSubList, deleteTadList);
                        prepareDetails(tasBean.wpinfoList, '待修理', intValueOf(mainTad.VF_TransferCount_Repair__c), upsertTadSubList, deleteTadList);
                        prepareDetails(tasBean.wpinfoList, '丢失找回', intValueOf(mainTad.VF_TransferCount_Lost__c), upsertTadSubList, deleteTadList);
                        for(TransferApplyDetail__c tad: upsertTadSubList) {
                            if(tad.Cancel_Select__c) {
                                continue;
                            }
                            if(tad.Id == null) {
                                tad.TransferApply__c = parentId;
                                tad.TransferApplySummary__c = tasMap.get(tad.Fixture_Model_No__c).Id;
                            }
                            if(tad.IndexFromUniqueKey__c != null) {
                                if(!tasMaxIndex.containsKey(tad.TransferApplySummary__c)){
                                    tasMaxIndex.put(tad.TransferApplySummary__c, intValueOf(tad.IndexFromUniqueKey__c));
                                }
                                else if(tad.IndexFromUniqueKey__c > tasMaxIndex.get(tad.TransferApplySummary__c)) {
                                    tasMaxIndex.put(tad.TransferApplySummary__c, intValueOf(tad.IndexFromUniqueKey__c));
                                }
                            }
                            tad.FSD_SortInt__c = 1;
                            tad.Salesdepartment_After__c = mainTad.Salesdepartment_After__c;
                            lastTasId = tad.TransferApplySummary__c;
                            lastModel = tad.Fixture_Model_No__c;
                        }
                        upsertTadList.addAll(upsertTadSubList);
                    }
                    else {
                        tadIndex = 1;
                        lastModel = '';
                        lastDep = '';
                        for(WrapperInfo wf : tasBean.wpinfoList) {
                            TransferApplyDetail__c tad = (TransferApplyDetail__c) wf.sobj;
                            if(tad.TransferApplySummary__c == null) {
                                tad.TransferApplySummary__c = tasMap.get(mainTad.Fixture_Model_No__c + ':' + mainTad.SerialNumber__c).Id;
                            }
                            tad.TransferApply__c = parentId;
                            if(lastModel != tad.Fixture_Model_No__c) {
                                tadIndex = 1;
                                lastDep = tad.Salesdepartment_After__c;
                            }
                            if(tad.FSD_SortInt__c == null) {
                                tad.FSD_SortInt__c = 1;
                            }
                            tad.IndexFromUniqueKey__c = tadIndex++;
                            tad.Salesdepartment_After__c = lastDep;
                            upsertTadList.add(tad);
                            lastModel = tad.Fixture_Model_No__c;
                        }
                    }
                }
            }
            if(!upsertTadList.isEmpty()) {
                for(TransferApplyDetail__c tad:upsertTadList) {
                    if(tad.IndexFromUniqueKey__c == null) {
                        Integer max = tasMaxIndex.containsKey(tad.TransferApplySummary__c)?tasMaxIndex.get(tad.TransferApplySummary__c):0;
                        tad.IndexFromUniqueKey__c = max + 1;
                        tasMaxIndex.put(tad.TransferApplySummary__c, max + 1);
                    }
                    // 20210814 管理编码  start
                    // 调拨到非集中的 不修改编码
                    /*
                    20211122 ljh SFDC-C8W3HW 
                    编码规则总结 备品分类 只存在非集中到集中或者非集中到非集中
                    1.备品分类 改变重新编码
                    2.备品分类 不改变（非检测）本部改变 重新编码
                    3.备品分类 不改变（非检测）本部不改变  0系改变重新编码
                    4.备品分类 不改变（非检测）本部不改变  0系不改变(0系) 0本部 存放地改变 重新编码
                    --- 因为产品分类GISP 调拨 不发生改变 故0本部和7-11本部 存放地改变才编码 场景6不存在--- 
                    5.备品分类 不改变（非检测）本部不改变  0系不改变(!0系) 0本部 存放地改变/GISP改变 重新编码
                    6.备品分类 不改变（非检测）本部不改变  0系不改变(!0系) 1-6本部 GISP改变 重新编码
                    7.备品分类 不改变（非检测）本部不改变  0系不改变(!0系) 7-11本部 存放地改变/GISP改变 重新编码
                    */
                    if(tad.Loaner_accsessary__c == false && parentObj.RecordType.DeveloperName != 'CenterToOther'){
                        // 20211122 ljh SFDC-C8W3HW update start

                        /*if((String.isNotBlank(tad.Equipment_Type_After__c)  
                            && ((tad.Equipment_Type__c == '检测用备品' && tad.Equipment_Type_After__c != '检测用备品') || (tad.Equipment_Type__c != '检测用备品' && tad.Equipment_Type_After__c == '检测用备品'))
                         )
                            ||(String.isNotBlank(tad.Salesdepartment_After__c) && tad.Salesdepartment_After__c != tad.Salesdepartment__c)
                        ){*/
                            List<TransferApplyDetail__c> tadFsList = new List<TransferApplyDetail__c>();
                            if(fmnMap.containsKey(tad.Fixture_Model_No__c)){
                                tadFsList = fmnMap.get(tad.Fixture_Model_No__c);
                                tadFsList.add(tad);
                                fmnMap.put(tad.Fixture_Model_No__c,tadFsList);
                            }else{
                                tadFsList = new List<TransferApplyDetail__c>();
                                tadFsList.add(tad);
                                fmnMap.put(tad.Fixture_Model_No__c,tadFsList);
                            }
                        /*}else if(String.isNotBlank(tad.CodeKey__c)){
                            tadClearId.add(tad.Id);
                        }*/
                        // 20211122 ljh SFDC-C8W3HW update end
                    }
                    // 20210814 管理编码  start
                }
                // System.debug('zheli11:'+fmnMap.size());
                if(fmnMap.size() > 0){
                    List<Fixture_Set__c> fsList =  [SELECT Id, Name, Loaner_categoryII__c 
                     FROM Fixture_Set__c WHERE Name IN:fmnMap.keySet()];
                    for(Fixture_Set__c fs:fsList){
                        if(xl0List.contains(fs.Loaner_categoryII__c)){
                            for(TransferApplyDetail__c tadfs:fmnMap.get(fs.Name)){
                                xl0TadId.add(tadfs.Id);
                            }
                        }
                    }
                    for(String fmn:fmnMap.keySet()){
                        tadBMList.addAll(fmnMap.get(fmn));
                    }
                    // 20211122 ljh SFDC-C8W3HW  add start
                    // 重新设计需要编码的tadBMNewList
                    for(TransferApplyDetail__c tad:tadBMList){

                        String SalesdepartmentS = String.isNotBlank(tad.Salesdepartment_After__c)?tad.Salesdepartment_After__c:tad.Salesdepartment__c;
                        Integer SalesdepartmentI;
                        if(String.isNotBlank(SalesdepartmentS)){
                            String[] SalesdepartmentArr = SalesdepartmentS.split('\\.');
                            if(SalesdepartmentArr.size() > 0){
                                String Salesdepartment = SalesdepartmentArr[0];
                                SalesdepartmentI = Integer.valueOf(Salesdepartment);
                            }
                        }
                        // 1.备品分类 改变重新编码
                        if(String.isNotBlank(tad.Equipment_Type_After__c)   &&  tad.Equipment_Type__c != '检测用备品' && tad.Equipment_Type_After__c == '检测用备品'  
                        ){
                            tadBMNewList.add(tad);
                        // 2.备品分类 不改变（非检测）本部改变 重新编码
                        }else if( String.isNotBlank(tad.Salesdepartment_After__c) && tad.Salesdepartment_After__c != tad.Salesdepartment__c){
                            tadBMNewList.add(tad);
                        }else {
                            // 3.备品分类 不改变（非检测）本部不改变  0系改变重新编码
                            // 原来系列 第三位 是否是0
                            String IsCode0 = ''; 
                            if(String.isNotBlank(tad.EquipmentSet_Managment_Code__c)){
                                IsCode0 = tad.EquipmentSet_Managment_Code__c.substring(2,3);
                            }
                            Boolean IsCode0B  = xl0TadId.contains(tad.Id);
                            if(String.isNotBlank(IsCode0)&& ((IsCode0 == '0' && IsCode0B == false)||(IsCode0 != '0' && IsCode0B == true))
                                ){
                                tadBMNewList.add(tad);
                            }else{
                                // 4.备品分类 不改变（非检测）本部不改变  0系不改变(0系) 0本部 存放地改变 重新编码
                                // 存放地改变 暂时认为 只有备品中心调拨到备品中心才发生改变。  
                                if(IsCode0B){
                                    if(SalesdepartmentI != null && SalesdepartmentI == 0  && parentObj.RecordType.DeveloperName == 'CenterToCenter'){
                                        tadBMNewList.add(tad);
                                    }
                                }else{
                                    // 5\6\7.备品分类 不改变（非检测）本部不改变  0系不改变(！0系) 0本部和7-11本部和16本部 存放地改变 重新编码
                                    if(parentObj.RecordType.DeveloperName == 'CenterToCenter' && SalesdepartmentI != null && (SalesdepartmentI == 0 || (SalesdepartmentI > 6 && SalesdepartmentI < 12) || SalesdepartmentI == 16)){
                                        tadBMNewList.add(tad);
                                    }else if(String.isNotBlank(tad.CodeKey__c)){
                                        tadClearId.add(tad.Id);
                                    }
                                }
                            }
                            
                        } 
                    }
                    // 20211122 ljh SFDC-C8W3HW  add start end
                    // for(TransferApplyDetail__c tad:tadBMList){
                    for(TransferApplyDetail__c tad:tadBMNewList){
                        String SalesdepartmentS = String.isNotBlank(tad.Salesdepartment_After__c)?tad.Salesdepartment_After__c:tad.Salesdepartment__c;
                        if(String.isNotBlank(SalesdepartmentS)){
                            String[] SalesdepartmentArr = SalesdepartmentS.split('\\.');
                            if(SalesdepartmentArr.size() > 0){
                                String Salesdepartment = SalesdepartmentArr[0];
                                Integer SalesdepartmentI = Integer.valueOf(Salesdepartment);
                                if(SalesdepartmentI < 12 || SalesdepartmentI == 16){
                                    String key = '';
                                    // key一览明细本次  key1一览明细上次
                                    // 备品分类、本部、是否0系列、产品分类(GI/SP)、存放地
                                    List<TransferApplyDetail__c> tadTempList = new List<TransferApplyDetail__c>();
                                    // 1. 备品分类
                                    String EquipmentType = String.isNotBlank(tad.Equipment_Type_After__c)?tad.Equipment_Type_After__c:tad.Equipment_Type__c;
                                    String DestinationLocation = parentObj.RecordType.DeveloperName == 'CenterToAgency'?parentObj.From_Location__c:parentObj.Destination_location__c;
                                    if(EquipmentType == '检测用备品'){
                                        key += 'JC;'+locationMap.get(DestinationLocation);    
                                    }else{
                                        key += 'NJC;';
                                        //2.本部 
                                        key += Salesdepartment+';';
                                        //3.是否0系列
                                        // 原管理编码的第三可知是否是0系列
                                        // 0系列 还是看 型号
                                        // String IsCode0 = tad.EquipmentSet_Managment_Code__c.substring(2,3);
                                        Boolean IsCode0  = xl0TadId.contains(tad.Id);
                                        // System.debug('zheli~IsCode0:'+IsCode0+'~'+tad.EquipmentSet_Managment_Code__c+'~'+DestinationLocation);
                                        // if(IsCode0 == '0'){
                                        if(IsCode0){
                                            if(SalesdepartmentI == 0 || SalesdepartmentI == 10){
                                                key += '0;'+locationMap.get(DestinationLocation);
                                            }else {
                                                key += '0';
                                            }
                                        }else{
                                            key += 'N0;';
                                            if(SalesdepartmentI == 0 || SalesdepartmentI > 6 ){
                                                key += tad.Product_category__c+';'+locationMap.get(DestinationLocation);
                                            }else if(SalesdepartmentI < 7){
                                                key += tad.Product_category__c;
                                            }
                                        }
                                    }
                                    // System.debug('zheli~key:'+key);
                                    // key
                                    if(String.isBlank(tad.CodeKey__c) || (!String.isBlank(tad.CodeKey__c)&& !String.isBlank(key) && tad.CodeKey__c != key)){
                                        if(codeNewMap.containsKey(key)){
                                            tadTempList = codeNewMap.get(key);
                                            tadTempList.add(tad);
                                            codeNewMap.put(key,tadTempList);
                                        }else{
                                            tadTempList = new List<TransferApplyDetail__c>();
                                            tadTempList.add(tad);
                                            codeNewMap.put(key,tadTempList);
                                        }
                                    }
                                }else if(String.isNotBlank(tad.CodeKey__c)){
                                    // 本部大于等于 12清空管理编码
                                    tadClearId.add(tad.Id);
                                }
                            }
                        }
                    }
                }
                // 20210814 ljh 管理编码 add start
                if(codeNewMap.size() > 0){
                    List<Asset_EquipmentSet_Managment_Code__c> aemCodeList = [SELECT Id, key__c, code__c,   
                             LastNo__c, keyName__c, isSpecial__c, MaxLastNo__c FROM Asset_EquipmentSet_Managment_Code__c
                            WHERE key__c IN :codeNewMap.keySet() for update];
                    for(Asset_EquipmentSet_Managment_Code__c aem:aemCodeList){
                        Integer code = Integer.valueOf(aem.LastNo__c);
                        String codeManange;
                        // String codeString = 
                        if(aem.LastNo__c == aem.MaxLastNo__c){
                            // 无法编码 抛出异常
                            throw new ControllerUtil.myException('编码已满，暂时无法编码。');
                        }else if(Integer.valueOf(aem.MaxLastNo__c)-Integer.valueOf(aem.LastNo__c) < codeNewMap.get(aem.key__c).size()){
                            // 不足 抛出异常
                            throw new ControllerUtil.myException('编码内存不足，暂时无法编码。');
                        }else{
                            //正常编码
                            for(TransferApplyDetail__c tad2:codeNewMap.get(aem.key__c)){
                               if(code == 19999 || code == 29999 || code == 39999
                                   || code == 39999 || code == 49999 || code == 59999
                                    ){
                                    code = code + 2;
                                }else{
                                    code = code + 1;
                                }
                                if(aem.isSpecial__c){
                                    codeManange = aem.code__c + String.valueOf(code).leftpad(5, '0').subString(0,1)+'-'+String.valueOf(code).leftpad(5, '0').substring(1,5);
                                }else{
                                    codeManange = aem.code__c +'-'+String.valueOf(code).leftpad(5, '0').substring(1,5);
                                }
                                TransferApplyDetail__c tad3 = new TransferApplyDetail__c();
                                tad3.Asset__c = tad2.Asset__c;
                                tad3.EquipmentSet_Managment_Code_After__c= codeManange;
                                tad3.CodeKey__c = aem.key__c;
                                codMap.put(tad2.Asset__c,tad3); 
                            }
                            Asset_EquipmentSet_Managment_Code__c aesm = new Asset_EquipmentSet_Managment_Code__c();
                            aesm.Id = aem.Id;
                            aesm.LastNo__c = code;
                            aesm.EquipmentSet_Managment_Code__c = codeManange;
                            aesm.Edit_staff__c = UserInfo.getUserId();
                            aesmUList.add(aesm);
                        }
                    }
                }
                // System.debug('zheli:'+tadClearId+'~'+codMap);
                for(TransferApplyDetail__c utad:upsertTadList){
                    // System.debug('zheli:'+utad.Id);
                    if(tadClearId.contains(utad.Id)){
                       utad.EquipmentSet_Managment_Code_After__c = ''; //有值才拷贝到保有设备
                       utad.CodeKey__c = '';
                    }
                    if(codMap.containsKey(utad.Asset__c)){
                       utad.EquipmentSet_Managment_Code_After__c = codMap.get(utad.Asset__c).EquipmentSet_Managment_Code_After__c; 
                       utad.CodeKey__c = codMap.get(utad.Asset__c).CodeKey__c; 
                    }
                    // System.debug('zheli22:'+utad);
                }
                // 20210814 ljh 管理编码 add end
                //20210818 ljh 管理编码 update start
                upsert upsertTadList;
                // upsert upsertTadMList;
                update aesmUList; 
                //20210818 ljh 管理编码 update end
            }
            if(!deleteTadList.isEmpty()) {
                delete deleteTadList;
            }
            // 追加批准状态处理
            updateAddApproval();
            done = true;
            parentObj = getParentObj(false);
        }
        catch (Exception ex) {
            System.debug(ex.getStackTraceString());
            ApexPages.addMessages(ex);
            Database.rollback(sp);
            done = false;
        }
        return done;
    }
    /**
    @description 单独调拨的附属品，根据画面上输入，重新整理出更新和删除的明细列表
    @param tasBean 画面上一行
    @param transferType 调拨分类：空，待废弃，待修理，丢失找回
    @param count 实际需要的数量
    @param upsertTadList 需要更新或新建的明细
    @param deleteTadList 需要删除的明细
    */
    private void prepareDetails(List<WrapperInfo> wpinfoList, String transferType, Integer count,
                                List<TransferApplyDetail__c> upsertTadList, List<TransferApplyDetail__c> deleteTadList ) {
        List<Integer> removeIndexes = new List<Integer> ();
        for(Integer i = 0; i < wpinfoList.size(); i++) {
            TransferApplyDetail__c tad = (TransferApplyDetail__c) wpinfoList[i].sobj;
            if(tad.TransferType__c == transferType) {
                if(count > 0) {
                    upsertTadList.add(tad);
                    count--;
                }
                // 现有的明细数超过实际需要的数量，则去掉多余的
                else {
                    removeIndexes.add(i);
                }
            }
        }
        for(Integer i = removeIndexes.size() - 1; i >= 0 && wpinfoList.size() > 1; i--) {
            TransferApplyDetail__c tad = (TransferApplyDetail__c) wpinfoList[removeIndexes[i]].sobj;
            if(tad.Id != null) {
                // 批准的要做取消
                if(tad.Approved_F__c) {
                    tad.Cancel_Select__c = true;
                    tad.Cancel_Reason__c = '主动取消';
                    upsertTadList.add(tad);
                }
                else {
                    // 未批准的直接删除
                    deleteTadList.add(tad);
                }
            }
            wpinfoList.remove(removeIndexes[i]);
        }
        // 实际需要的数量超过现有的，则做追加
        if(count > 0) {
            TransferApplyDetail__c mainTad = (TransferApplyDetail__c) wpinfoList[0].sobj;
            for(Integer i = 0; i < count;i++) {
                TransferApplyDetail__c tad = new TransferApplyDetail__c();
                tad.TransferType__c = transferType;
                for(String field: FIELD_NAME_MAP.keySet()){
                    tad.put(field, mainTad.get(field));
                }
                upsertTadList.add(tad);
                WrapperInfo wf = new WrapperInfo(tad, myComponentController);
                wpinfoList.add(wf);
            }
        }
    }

    /**
    @description 检查待保存的一览，只对未保存和未审批的做检查
    @param beanList 待保存的beanList
    @return 错误信息列表
    */
    private List<String> checkDetails(List<TransferApplySummaryBean> beanList) {
        List<String> errorList = new List<String>();
        Map<Id, Integer> assetCntMap = new Map<Id, Integer>(); // 非一对一附属品的数量统计，保有设备Id->调拨数量
        Map<Id, Integer> assetAbanCntMap = new Map<Id, Integer>(); // 非一对一附属品待废弃数统计，保有设备Id->待废弃调拨数量
        Map<Id, Integer> assetRepairCntMap = new Map<Id, Integer>(); // 非一对一附属品待废弃数统计，保有设备Id->待修理调拨数量
        Map<Id, Integer> assetLostCntMap = new Map<Id, Integer>(); // 非一对一附属品丢失找回数统计，保有设备Id->丢失找回调拨数量
        Map<String, Integer> linkCntMap = new Map<String, Integer>(); // 一对一附属品link数统计，主体Id:附属品Id->调拨数量
        Map<String, Integer> linkAbandonCntMap = new Map<String, Integer>(); // 一对一附属品link数统计，主体Id:附属品Id->待废弃调拨数量
        Map<String, Integer> linkRepairCntMap = new Map<String, Integer>(); // 一对一附属品link数统计，主体Id:附属品Id->待修理调拨数量
        Map<String, String> assetModelMap = new Map<String, String>(); // assetId->型号 用于错误提醒
        for(TransferApplySummaryBean tasBean:beanList) {
            
            TransferApplyDetail__c mainTad = (TransferApplyDetail__c) tasBean.wpinfoList[0].sObj;
            if(mainTad.Main_OneToOne__c) {
                if(mainTad.Approved_F__c) {
                    continue;
                }
                if(intValueOf(mainTad.VF_TransferCount__c) > 0) {
                    Integer cnt = 0;
                    if(assetCntMap.containsKey(mainTad.Asset__c)) {
                        cnt = assetCntMap.get(mainTad.Asset__c);
                    }
                    assetCntMap.put(mainTad.Asset__c, cnt + 1);
                }
                for(WrapperInfo wf:tasBean.wpinfoList) {
                    TransferApplyDetail__c tad = (TransferApplyDetail__c) wf.sObj;
                    assetModelMap.put(tad.Asset__c, tad.Fixture_Model_No__c);
                    // bean里，wrapinfo和明细一一对应
                    if(mainTad.Main_OneToOne__c && tad.OnetoOneAccessory__c) {
                        String key = mainTad.Asset__c + ':' + tad.Asset__c;
                        Integer cnt = 0;
                        switch on tad.TransferType__c {
                            when '待废弃' {
                                if(linkAbandonCntMap.containsKey(key)) {
                                    cnt = linkAbandonCntMap.get(key);
                                }
                                linkAbandonCntMap.put(key, cnt + 1);
                            }
                            when '待修理' {
                                if(linkRepairCntMap.containsKey(key)) {
                                    cnt = linkRepairCntMap.get(key);
                                }
                                linkRepairCntMap.put(key, cnt + 1);
                            }
                            when else {
                                if(linkCntMap.containsKey(key)) {
                                    cnt = linkCntMap.get(key);
                                }
                                linkCntMap.put(key, cnt + 1);
                            }
                        }
                    }
                }
            }

            if(intValueOf(mainTad.VF_TransferCount__c)
                + intValueOf(mainTad.VF_TransferCount_Abandoned__c)
                + intValueOf(mainTad.VF_TransferCount_Repair__c)
                + intValueOf(mainTad.VF_TransferCount_Lost__c) == 0) {
                errorList.add(mainTad.Fixture_Model_No__c + '：调拨总数量不可为0!');
            }
            else if(!mainTad.Main_OneToOne__c) {
                Integer cnt = intValueOf(mainTad.VF_TransferCount__c);
                Integer abandon = intValueOf(mainTad.VF_TransferCount_Abandoned__c);
                Integer repair = intValueOf(mainTad.VF_TransferCount_Repair__c);
                Integer lost = intValueOf(mainTad.VF_TransferCount_Lost__c);
                // 用 调拨数-已审批数 来和现有可调拨数做比较
                for(WrapperInfo wf:tasBean.wpinfoList) {
                    TransferApplyDetail__c tad = (TransferApplyDetail__c) wf.sObj;
                    if(tad.Id != null && tad.Approved_F__c) {
                        switch on tad.TransferType__c {
                            when '待废弃' {
                                abandon--;
                            }
                            when '待修理' {
                                repair--;
                            }
                            when '丢失找回' {
                                lost--;
                            }
                            when else {
                                cnt--;
                            }
                        }
                    }
                }
                if(cnt > 0) {
                    assetCntMap.put(mainTad.Asset__c, cnt);
                }
                if(abandon > 0) {
                    assetAbanCntMap.put(mainTad.Asset__c, abandon);
                }
                if(repair > 0) {
                    assetRepairCntMap.put(mainTad.Asset__c, repair);
                }
                if(lost > 0) {
                    assetLostCntMap.put(mainTad.Asset__c, lost);
                }
            }
        }

        Map<Id, Asset> assetMap = new Map<Id, Asset>();
        Map<String, Fixture_OneToOne_Link__c> linkMap = new Map<String, Fixture_OneToOne_Link__c>();
        // 保有设备检查
        if(assetCntMap.size() + assetAbanCntMap.size() + assetRepairCntMap.size() + assetLostCntMap.size() > 0) {
            Set<Id> assIdSet = assetCntMap.keySet().clone();
            assIdSet.addAll(assetAbanCntMap.keySet());
            assIdSet.addAll(assetRepairCntMap.keySet());
            assIdSet.addAll(assetLostCntMap.keySet());
            String assSql = 'SELECT Id'
                          + ', Ji_Zhong_Guan_Li_Ku_Cun__c'
                          + ', Fixture_Model_No_F__c'
                          + ', TransferableAbandon_F__c'
                          + ', TransferableRepair_F__c'
                          + ', TransferableLost_F__c'
                          + ' FROM Asset ';
            assSql += this.makeSoql('','');
            assSql += ' and Id IN :assIdSet FOR UPDATE';
            assetMap = new Map<Id, Asset>((List<Asset>)Database.query(assSql));
            for(Id assetId: assIdSet) {
                if(!assetMap.containsKey(assetId)) {
                    errorList.add(assetId + '不存在或不可调拨!');
                    continue;
                }
                if(assetCntMap.containsKey(assetId)){
                    if(assetCntMap.get(assetId) > assetMap.get(assetId).Ji_Zhong_Guan_Li_Ku_Cun__c){
                        //errorList.add(assetMap.get(assetId).Fixture_Model_No_F__c + '：数量超过集中管理库存!');
                        errorList.add(assetMap.get(assetId).Fixture_Model_No_F__c + '：调拨数量不能超过有效库存!');
                    }
                }
                if(assetAbanCntMap.containsKey(assetId)){
                    if(assetAbanCntMap.get(assetId) > assetMap.get(assetId).TransferableAbandon_F__c){
                        errorList.add(assetMap.get(assetId).Fixture_Model_No_F__c + '：数量超过待废弃数(实物)!');
                    }
                }
                if(assetRepairCntMap.containsKey(assetId)){
                    if(assetRepairCntMap.get(assetId) > assetMap.get(assetId).TransferableRepair_F__c){
                        errorList.add(assetMap.get(assetId).Fixture_Model_No_F__c + '：数量超过待修理数!');
                    }
                }
                if(assetLostCntMap.containsKey(assetId)){
                    if(assetLostCntMap.get(assetId) > assetMap.get(assetId).TransferableLost_F__c){
                        errorList.add(assetMap.get(assetId).Fixture_Model_No_F__c + '：数量超过丢失盘亏数!');
                    }
                }
            }
        }
        // link里的各个数量检查
        if(linkCntMap.size() + linkAbandonCntMap.size() + linkRepairCntMap.size() > 0) {
            Set<String> linkIdSet = linkCntMap.keySet().clone();
            linkIdSet.addAll(linkAbandonCntMap.keySet());
            linkIdSet.addAll(linkRepairCntMap.keySet());
            String linkSql = 'SELECT Quantity__c, Abandoned_RealThing__c, CountForRepair__c,  Main_Asset__c'
                           + ', In_wh_Fu_Shu_Pin_You_Xiao_Ku_Cun_F__c, Accessory_Asset__c FROM Fixture_OneToOne_Link__c WHERE ';
            for(String key: linkIdSet) {
                List<String> ids = key.split(':');
                linkSql += '(Main_Asset__c = \'' + ids[0] + '\' AND Accessory_Asset__c = \'' + ids[1] + '\') OR';
            }
            linkSql = linkSql.removeEnd('OR');
            linkSql += ' FOR UPDATE';
            List<Fixture_OneToOne_Link__c> links = Database.query(linkSql);
            for(Fixture_OneToOne_Link__c link:links) {
                String key = link.Main_Asset__c + ':' + link.Accessory_Asset__c;
                linkMap.put(key, link);
            }
            for(String key:linkCntMap.keySet()) {
                List<String> ids = key.split(':');
                if(!linkMap.containsKey(key)) {
                    errorList.add(assetModelMap.get(ids[0])+':'+assetModelMap.get(ids[1]) + ' link不存在!');
                }
                else if(linkCntMap.get(key) > linkMap.get(key).In_wh_Fu_Shu_Pin_You_Xiao_Ku_Cun_F__c) {
                    errorList.add(assetModelMap.get(ids[0])+':'+assetModelMap.get(ids[1]) + ' 调拨数量超过一对一的有效库存!');
                }
                else if(linkAbandonCntMap.get(key) > linkMap.get(key).Abandoned_RealThing__c) {
                    errorList.add(assetModelMap.get(ids[0])+':'+assetModelMap.get(ids[1]) + ' 待废弃调拨数超过一对一的待废弃数!');
                }
                else if(linkRepairCntMap.get(key) > linkMap.get(key).CountForRepair__c) {
                    errorList.add(assetModelMap.get(ids[0])+':'+assetModelMap.get(ids[1]) + ' 待修理调拨数超过一对一的待修理数!');
                }
            }
        }

        return errorList;
    }
    private void removeUncheckedTasBean() {
        for(Integer i = tasBeanList.size() - 1; i >= 0; i--) {
            if(!tasBeanList[i].wpinfoList[0].check) {
                tasBeanList.remove(i);
            }
        }
    }
    private Integer intValueOf(Decimal d) {
        if(d == null) {
            return 0;
        }
        return Integer.valueOf(d);
    }
    private void updateAddApproval(){
        List<AggregateResult> add_Approvals = [
            Select Count(Id) cnt, SUM(Draft_Appended__c) Draft_Appended__c
            From TransferApplyDetail__c
           Where TransferApply__c = :parentId
             AND Cancel_Select__c = false
             AND ApplyPersonAppended_F__c = true
           Group by TransferApply__c
        ];
        Integer Draft_Appended = 0;
        Integer add_ApprovalCount = 0;
        if (!add_Approvals.isEmpty()) {
            Draft_Appended = add_Approvals[0].get('Draft_Appended__c') == null ? 0 : Integer.valueOf(add_Approvals[0].get('Draft_Appended__c'));
            add_ApprovalCount = add_Approvals[0].get('cnt') == null ? 0 : Integer.valueOf(add_Approvals[0].get('cnt'));
        }

        List<TransferApply__c> taList = new List<TransferApply__c>();

        // 有草案中的追加附属品并且申请书的状态不是草案中，&& 不是分配代替品 的需要改变状态为草案中
        if (Draft_Appended > 0 && parentObj.Add_Approval_Status__c != '草案中' && parentObj.Request_approval_time__c != null) {
            parentObj.Add_Approval_Status__c = '草案中';
            taList.add(parentObj);
        }
        // 申请书单位已经没有草案中的附属品
        else if (Draft_Appended == 0) {
            //没有追加附属品状态为空
            if (add_ApprovalCount == 0 && String.isNotBlank(parentObj.Add_Approval_Status__c)) {
                parentObj.Add_Approval_Status__c = '';
            }
            // 有追加附属品状态为草案中
            else if (add_ApprovalCount > 0  && parentObj.Add_Approval_Status__c != '草案中' && parentObj.Add_Approval_Status__c != '申请中') {
                parentObj.Add_Approval_Status__c = FixtureUtil.raStatusMap.get(FixtureUtil.RaStatus.Yi_Pi_Zhun.ordinal());
            }
            taList.add(parentObj);
        }
        if (!taList.isEmpty()) {
            FixtureUtil.withoutUpdate(taList);
        }
    }

    public PageReference turnback() {
        PageReference ret = null;
        if (!String.isBlank(this.parentId)) {
            ret = new PageReference('/' + this.parentId);
        }
        return ret;
    }

    private String makeSoql(String keyword, String assetnumber) {
        // 検索条件
        String dateToday = String.valueOf(Date.today());

        // 先检出主体和集中管理数大于0的
        String soql ='';
        soql += 'where Asset_Owner__c = \'Olympus\' AND ' + FixtureUtil.getAssetSoqlBase();
        soql += '  and RecordTypeId = \''+System.label.AssetShipmentRecordTypeId+'\'';
        soql += '  and Quantity > 0';
        soql += '  and Delete_Flag__c = False ';
        soql += '  and Equipment_Type__c != \'检测用备品\'';
        soql += '  and Freeze_sign__c = False';
        soql += '  and Internal_asset_location__c = \'' + parentObj.From_Location__c + '\'';
        soql += '  and Asset_loaner_category__c != \'耗材\'';
        soql += ' and Salesdepartment__c != \'13.CTEC教育本部\'';
        soql += ' and Salesdepartment__c != \'14.医疗人才教育培训本部\'';
        soql += ' and Salesdepartment__c != \'15.医疗法规事务和质量管理本部\'';
        if(parentObj.RecordType.DeveloperName == 'InsideCenter') {
            soql += ' and Manage_type__c = \'个体管理\' and You_Xiao_Ku_Cun__c > 0 and Loaner_accsessary__c = false';
        }
        else {
            soql += '  and (Ji_Zhong_Guan_Li_Ku_Cun__c > 0 or TransferableAbandon_F__c > 0';
            if(parentObj.RecordType.DeveloperName == 'AgencyToCenter') {
                soql += ' or TransferableLost_F__c > 0 or TransferableRepair_F__c > 0 )';
            }
            else {
                //20210507 ljh update 1834 start
                //soql += ') and ((Loaner_accsessary__c = false and Main_OneToOne__c = true) or (Loaner_accsessary__c = true and Main_OneToOne__c = false)) ';
                soql += ') and ((Loaner_accsessary__c = false and Main_OneToOne__c = true) or (Loaner_accsessary__c = true and Main_OneToOne__c = false) or (Loaner_accsessary__c = false and Main_OneToOne__c = false)) ';
                //20210507 ljh update 1834 end
            }
            soql +=' and Fixture_OneToOne_Link__c = null'; // 不是一对一个体附属品
        }

        if (!String.isBlank(keyword)) {
            String[] vals = keyword.split(' ');
             soql += ' and (';
             String fmodelno = '';
            for (String v : vals) {
                v = String.escapeSingleQuotes(v.replace('%', '\\%').replace('*', '%'));
                fmodelno += ' Product2.Fixture_Model_No_T__c like \'' + v + '\' ';
                fmodelno += ' or Product2.Name like \'' + v + '\' ';
                fmodelno += 'or';
            }
            fmodelno = fmodelno.removeEnd('or');
            soql += fmodelno + ' )';
        }

        if (!String.isBlank(assetnumber)) {
            String num = String.escapeSingleQuotes(assetnumber.replace('%', '\\%').replace('*', '%'));
            soql += ' and Internal_Asset_number_key__c like\'' + num + '\' ';
        }
        return soql;
    }

    public override void setViewList(List<sObject> queryList) {
        List<TransferApplySummaryBean> oldTasBeanList = new List<TransferApplySummaryBean>(); // 存一下勾选的保有设备
        for(TransferApplySummaryBean tasBean:tasBeanList) {
            if(tasBean.wpinfoList[0].check) {
                oldTasBeanList.add(tasBean);
            }
        }
        tasBeanList.clear();
        Set<Id> hideAssetIdSet = new Set<Id>(); // 个体管理的保有设备如果已经在明细中，则检索时不再显示
        Id lastAssetId = null;
        Id lastTasId = null;
        // 自己的数据打勾，被检索出来的数据不打勾
        if (selectedData.size() > 0) {
            List<TransferApplyDetail__c> otoTadList = new List<TransferApplyDetail__c>();
            for (Integer i = 0; i < selectedData.size(); i++) {
                TransferApplyDetail__c tad = (TransferApplyDetail__c) selectedData[i];
                // 下架前打开画面时，明细里的调拨前字段要取最新
                if(tad.DeliverySlip__c == null ) {
                    if(tad.OnetoOneAccessory__c) {
                        // 一对一的各数要从link取
                        tad.VF_You_Xiao_Ku_Cun__c = tad.Fixture_OneToOne_Link__r.In_wh_Fu_Shu_Pin_You_Xiao_Ku_Cun_F__c;
                        tad.VF_CountForRepair__c = tad.Fixture_OneToOne_Link__r.CountForRepair__c;
                        tad.VF_Abandoned_RealThing__c = tad.Fixture_OneToOne_Link__r.Abandoned_RealThing__c;
                        tad.VF_Abandoned_Inventory__c = 0;
                    }
                    else {
                        // 其它的直接从保有设备取
                        Asset ass = tad.Asset__r;
                        tad.VF_Abandoned_RealThing__c = ass.TransferableAbandon_F__c;
                        tad.VF_You_Xiao_Ku_Cun__c     = ass.Ji_Zhong_Guan_Li_Ku_Cun__c;
                        tad.VF_CountForRepair__c      = ass.TransferableRepair_F__c;
                        tad.VF_Abandoned_Inventory__c = ass.TransferableLost_F__c;
                    }
                }

                if(tad.Manage_type__c == '个体管理') {
                    hideAssetIdSet.add(tad.Asset__c);
                }
                else if(!tad.OnetoOneAccessory__c) { // 数量管理非一对一附属品，如果申请中已存在则不再在检索结果中显示
                    hideAssetIdSet.add(tad.Asset__c);
                }
                WrapperInfo wf = new WrapperInfo(tad, myComponentController);
                wf.check = true;
                wf.oldCheck = true;
                // 对已保存的明细，一对一附属品和主体装到一个bean，非一对一的按保有设备装到一个bean里
                if(tad.TransferApplySummary__c != lastTasId) {
                    // 一览变化时，新建一个bean
                    TransferApplySummaryBean tasBean = new TransferApplySummaryBean();
                    tasBean.tas.Id = tad.TransferApplySummary__c;
                    tasBeanList.add(tasBean);
                    wf.canEdit = true;
                }
                else if(tad.Asset__c != lastAssetId && !tad.OnetoOneAccessory__c) {
                    // 同一个一览内，保有设备变化时且不是一对一附属品，新建一个bean
                    TransferApplySummaryBean tasBean = new TransferApplySummaryBean();
                    tasBean.tas.Id = tad.TransferApplySummary__c;
                    tasBeanList.add(tasBean);
                    wf.canEdit = true;
                }
                else {
                    wf.check = false;
                    wf.oldCheck = false;
                    wf.canEdit = true;
                }
                lastAssetId = tad.Asset__c;
                lastTasId = tad.TransferApplySummary__c;
                tasBeanList[tasBeanList.size()-1].wpinfoList.add(wf);
            }
        }
        for(TransferApplySummaryBean tasBean: oldTasBeanList) {
            TransferApplyDetail__c tad = (TransferApplyDetail__c) tasBean.wpinfoList[0].sObj;
            if(!hideAssetIdSet.contains(tad.Asset__c) && !tad.OnetoOneAccessory__c) {
                // 打了勾但不是已保存的明细，再次显示
                tasBeanList.add(tasBean);
                hideAssetIdSet.add(tad.Asset__c);
            }
        }

        Map<Id, TransferApplySummaryBean> mainTasBeanMap = new Map<Id, TransferApplySummaryBean> (); //主体Id->一览bean
        Map<Id, Asset> availableAsset = new Map<Id, Asset> ([SELECT Id FROM Asset WHERE Id IN:queryList]); // 确认哪些设备有访问权限
        for (Integer i = 0; i < queryList.size(); i++) {
            Asset ass = (Asset)queryList[i];
            if(hideAssetIdSet.contains(ass.Id) || !availableAsset.containsKey(ass.Id)) {
                // 个体管理保有设备如果已出现在明细中，则不需要再显示
                // 没权限查看的设备也要跳过
                continue;
            }
            TransferApplySummaryBean tasBean = new TransferApplySummaryBean();

            if(ass.Main_OneToOne__c) {
                mainTasBeanMap.put(ass.Id, tasBean);
            }
            TransferApplyDetail__c tad = new TransferApplyDetail__c();
            for(String field:FIELD_NAME_MAP.keySet()) {
                tad.put(field, ass.get(FIELD_NAME_MAP.get(field)));
                //if(ass.Loaner_accsessary__c){
                //    tad.VF_You_Xiao_Ku_Cun__c = intValueOf(ass.Ji_Zhong_Guan_Li_Ku_Cun__c);
                //}
                //else {
                //    tad.VF_You_Xiao_Ku_Cun__c = ass.You_Xiao_Ku_Cun__c;
                //}
            } 
            if(tad.Manage_type__c == '个体管理') {
                if(tad.VF_CountForRepair__c > 0) {
                    tad.TransferType__c = '待修理';
                }
                else if(tad.VF_Abandoned_RealThing__c > 0 ) {
                    tad.TransferType__c = '待废弃';
                }
                else if(tad.VF_Abandoned_Inventory__c > 0) {
                    tad.TransferType__c = '丢失找回';
                }
                else {
                    tad.TransferType__c = '有效库存';
                }
            }
            WrapperInfo wf= new WrapperInfo(tad, myComponentController);
            tasBean.wpinfoList.add(wf);
            tasBeanList.add(tasBean);
        }
        if(parentObj.RecordType.DeveloperName != 'InsideCenter') {
            addOnetoOneAccessories(mainTasBeanMap);
        }
        myComponentController.page = 1;
        refreshViewList(tasBeanList);
    }

    public void saveAndSearch() {
        if(save()) {
            searchOpp();
        }
    }

    public void saveAndSearchNext() {
        if(save()) {
            searchNextCtrl();
        }
    }
    public void saveAndsearchPrevious() {
        if(save()) {
            searchPreviousCtrl();
        }
    }
    public void saveAndsearchGoPage() {
        if(save()) {
            searchGoPageCtrl();
        }
    }
    public void searchNextCtrl() {
        myComponentController.page = Math.min(myComponentController.maxPage, myComponentController.page + 1);
        refreshViewList(tasBeanList);
    }
    public void searchPreviousCtrl() {
        myComponentController.page = Math.max(1, myComponentController.page - 1);
        refreshViewList(tasBeanList);
    }
    public void searchGoPageCtrl() {
        myComponentController.page = myComponentController.goPageInt;
        refreshViewList(tasBeanList);
    }
    /**
    @description 显示beanlist
    @param beanList 要放到viewlist里的beanList
    @param k 页号
    */
    private void refreshViewList(List<TransferApplySummaryBean> beanList) {
        viewList = new List<WrapperInfo>();
        if(beanList.isEmpty()) {
            myComponentController.isDisplayPaging = false;
            return ;
        }
        Integer k = myComponentController.page;
        myComponentController.maxPage = (beanList.size() / SHOW_SIZE) + (Math.mod(beanList.size(), SHOW_SIZE) > 0 ? 1 : 0);
        myComponentController.isDisplayPaging = myComponentController.maxPage > 0;
        myComponentController.hasPrevious = (k > 1 && k <= myComponentController.maxPage);
        myComponentController.hasNext = (k < myComponentController.maxPage && myComponentController.maxPage > 0);

        Integer a = (k - 1) * Integer.valueOf(SHOW_SIZE);
        Integer b = Math.min(k * Integer.valueOf(SHOW_SIZE), beanList.size());
        Integer lineNo = 0;
        for (Integer i = a ; i < b ; i++) {
            TransferApplySummaryBean tasBean = beanList[i];
            Id lastAssetId = null;
            Id lastTasId = null;
            TransferApplyDetail__c lastTad = null;
            Integer index = 1;
            for(WrapperInfo wf: tasBean.wpinfoList) {
                TransferApplyDetail__c tad = (TransferApplyDetail__c) wf.sObj;
                if(tad.Asset__c != lastAssetId || tad.TransferApplySummary__c != lastTasId) {
                    if(tad.Id == null && tad.Manage_type__c == '数量管理' && !tad.OnetoOneAccessory__c) {
                        // 未保存的数量管理附属品
                        if(!wf.check) {
                            tad.VF_TransferCount__c = null;
                            tad.VF_TransferCount_Abandoned__c = null;
                            tad.VF_TransferCount_Repair__c = null;
                            tad.VF_TransferCount_Lost__c = null;
                            if(raAssetCountMap.containsKey(tad.Asset__c)) {
                                tad.VF_TransferCount__c = raAssetCountMap.get(tad.Asset__c).get('有效库存');
                                tad.VF_TransferCount_Abandoned__c = raAssetCountMap.get(tad.Asset__c).get('待废弃');
                                tad.VF_TransferCount_Repair__c = raAssetCountMap.get(tad.Asset__c).get('待修理');
                                tad.VF_TransferCount_Lost__c = raAssetCountMap.get(tad.Asset__c).get('丢失找回');
                            }
                        }
                    }
                    else {
                        // 已保存的明细
                        tad.VF_TransferCount__c = 0;
                        tad.VF_TransferCount_Abandoned__c = 0;
                        tad.VF_TransferCount_Repair__c = 0;
                        tad.VF_TransferCount_Lost__c = 0;
                        switch on tad.TransferType__c {
                            when '待废弃' {
                                tad.VF_TransferCount_Abandoned__c = 1;
                            }
                            when '待修理' {
                                tad.VF_TransferCount_Repair__c = 1;
                            }
                            when '丢失找回' {
                                tad.VF_TransferCount_Lost__c = 1;
                            }
                            when else {
                                tad.VF_TransferCount__c = 1;
                            }
                        }
                    }
                    lastTad = tad;
                    wf.lineNo = lineNo++;
                    viewList.add(wf);
                }
                else {
                    switch on tad.TransferType__c {
                        when '待废弃' {
                            lastTad.VF_TransferCount_Abandoned__c += 1;
                        }
                        when '待修理' {
                            lastTad.VF_TransferCount_Repair__c += 1;
                        }
                        when '丢失找回' {
                            lastTad.VF_TransferCount_Lost__c += 1;
                        }
                        when else {
                            lastTad.VF_TransferCount__c += 1;
                        }
                    }
                }
                lastAssetId = tad.Asset__c;
                lastTasId = tad.TransferApplySummary__c;
            }
        }
    }

    /**
    @description 主体关联的一对一附属品，并匹配备品配套和配套明细
    @param mainTasBeanMap 主体对应的一览bean
    */
    private void addOnetoOneAccessories(Map<Id, TransferApplySummaryBean> mainTasBeanMap) {
        if(mainTasBeanMap.isEmpty()) {
            return ;
        }
        // 获取link
        List<Fixture_OneToOne_Link__c> allLinks = [
                SELECT Id
                     , Main_Asset__c
                     , Main_Asset__r.Fixture_Model_No_F__c
                     , Accessory_Asset__c
                     , Accessory_Asset__r.Fixture_Model_No_F__c
                     , Quantity__c
                     , In_wh_Fu_Shu_Pin_You_Xiao_Ku_Cun_F__c
                     , Abandoned_RealThing__c
                     , CountForRepair__c
                  FROM Fixture_OneToOne_Link__c
                 WHERE Main_Asset__c IN: mainTasBeanMap.keySet()
            ];
        Map<Id, List<Fixture_OneToOne_Link__c>> main2LinksMap = new Map<Id, List<Fixture_OneToOne_Link__c>>(); //主体->所有link
        Set<Id> acsIdSet = new Set<Id>(); // 附属品保有设备Id
        Set<String> productModelSet = new Set<String>(); // 产品名称

        for(Fixture_OneToOne_Link__c link:allLinks) {
            if(!main2LinksMap.containsKey(link.Main_Asset__c)){
                main2LinksMap.put(link.Main_Asset__c, new List<Fixture_OneToOne_Link__c>());
            }
            List<Fixture_OneToOne_Link__c> templinks = main2LinksMap.get(link.Main_Asset__c);
            templinks.add(link);
            acsIdSet.add(link.Accessory_Asset__c);
            productModelSet.add(link.Main_Asset__r.Fixture_Model_No_F__c);
            productModelSet.add(link.Accessory_Asset__r.Fixture_Model_No_F__c);
        }
        if(acsIdSet.isEmpty()) {
            return;
        }
        // 通过产品找配套明细，并按配套分组
        List<Fixture_Set_Detail__c> fsdList = [SELECT Id
                                                    , Product2__c
                                                    , Fixture_Set__c
                                                    , Is_Body__c
                                                    , Fixture_Model_No_F__c
                                                    , SortInt__c
                                                 FROM Fixture_Set_Detail__c
                                                WHERE Fixture_Model_No_F__c IN: productModelSet
                                             ORDER BY Fixture_Set__r.LastModifiedDate DESC
                                            ];
        Map<Id, Map<String, Fixture_Set_Detail__c>> fsMap = new Map<Id, Map<String, Fixture_Set_Detail__c>>(); // 配套Id->产品型号->配套明细
        Set<String> bodyProModelSet = new Set<String>();
        for(Fixture_Set_Detail__c fsd:fsdList) {
            if(!fsMap.containsKey(fsd.Fixture_Set__c)){
                fsMap.put(fsd.Fixture_Set__c, new Map<String, Fixture_Set_Detail__c>());
            }
            Map<String, Fixture_Set_Detail__c> pro2FsdMap = fsMap.get(fsd.Fixture_Set__c);
            // 如果一个主体产品出现在多个备品配套中，那么只用最新的配套
            // fsMap变量中，旧配套中会少主体的产品Id，所以不会和一览匹配上
            if(fsd.Is_Body__c && bodyProModelSet.contains(fsd.Fixture_Model_No_F__c)) {
                continue;
            }
            pro2FsdMap.put(fsd.Fixture_Model_No_F__c, fsd);
            if(fsd.Is_Body__c) {
                bodyProModelSet.add(fsd.Fixture_Model_No_F__c);
            }

        }
        // 获取所有一对一附属品asset
        String acsSql = 'SELECT '+ String.join(FIELD_NAME_MAP.values(), ', ') + ' FROM Asset WHERE Id IN :acsIdSet';

        Map<Id, Asset> acsMap = new Map<Id, Asset>((List<Asset>)Database.query(acsSql));

        for(Id mainId:mainTasBeanMap.keySet()) {
            if(main2LinksMap.containsKey(mainId)) {
                Set<String> proInSummaryModelSet = new Set<String>(); // 用于存放一览下所有的产品型号
                for(Fixture_OneToOne_Link__c link: main2LinksMap.get(mainId)) {
                    if(acsMap.containsKey(link.Accessory_Asset__c)) {
                        // 用一对一附属品构造wrapperinfo
                        Asset acs = acsMap.get(link.Accessory_Asset__c);
                        Integer repair = intValueOf(link.CountForRepair__c);
                        Integer abandon = intValueOf(link.Abandoned_RealThing__c);
                        for(Integer i = 0; i < link.Quantity__c; i++) {
                            TransferApplyDetail__c tad = new TransferApplyDetail__c();
                            for(String field:FIELD_NAME_MAP.keySet()) {
                                tad.put(field, acs.get(FIELD_NAME_MAP.get(field)));
                            }
                            tad.VF_CountForRepair__c = intValueOf(link.CountForRepair__c);
                            tad.VF_Abandoned_RealThing__c = intValueOf(link.Abandoned_RealThing__c);
                            tad.VF_You_Xiao_Ku_Cun__c = intValueOf(link.In_wh_Fu_Shu_Pin_You_Xiao_Ku_Cun_F__c);
                            tad.VF_Abandoned_Inventory__c = 0;
                            tad.Fixture_OneToOne_Link__c = link.Id;
                            if(repair > 0) {
                                tad.TransferType__c = '待修理';
                                repair--;
                            }
                            else if(abandon > 0) {
                                tad.TransferType__c = '待废弃';
                                abandon--;
                            }
                            else {
                                tad.TransferType__c = '有效库存';
                            }
                            tad.OnetoOneAccessory__c = true;
                            TransferApplySummaryBean tasBean = mainTasBeanMap.get(mainId);
                            WrapperInfo wf = new WrapperInfo(tad, myComponentController);
                            wf.check = false;
                            wf.oldCheck = false;
                            wf.canEdit = true;
                            tasBean.wpinfoList.add(wf);
                            proInSummaryModelSet.add(link.Accessory_Asset__r.Fixture_Model_No_F__c);
                            proInSummaryModelSet.add(link.Main_Asset__r.Fixture_Model_No_F__c);
                        }
                    }
                }
                // 找出所有产品型号都匹配的配套
                Id fsId = findFS(proInSummaryModelSet, fsMap);
                if( fsId != null) {
                    TransferApplySummaryBean tasBean = mainTasBeanMap.get(mainId);
                    tasBean.tas.Fixture_Set__c = fsId;
                    for(WrapperInfo wf:tasBean.wpinfoList) {
                        TransferApplyDetail__c tad = (TransferApplyDetail__c) wf.sobj;
                        if(fsMap.get(fsId).containsKey(tad.Fixture_Model_No__c)) {
                            tad.Fixture_Set_Detail__c = fsMap.get(fsId).get(tad.Fixture_Model_No__c).Id;
                            tad.FSD_SortInt__c = fsMap.get(fsId).get(tad.Fixture_Model_No__c).SortInt__c;
                        }
                    }
                }
            }
        }
    }
    /**
    @description 根据产品Id去匹配配套
    @param proModelSet 一个一览下的产品型号Set
    @param fsMap 配套Id->产品型号->配套明细
    */
    private Id findFS(Set<String> proModelSet, Map<Id, Map<String, Fixture_Set_Detail__c>> fsMap) {
        for(Id fsId:fsMap.keySet()) {
            Boolean find = true;
            for(String proModel: proModelSet) {
                if(!fsMap.get(fsId).containsKey(proModel)) {
                    find = false;
                }
            }
            if(find && !proModelSet.isEmpty()) {
                return fsId;
            }
        }
        return null;
    }

    public List<SelectOption> getPickList(String objApi, String fieldApi) {
        Schema.DescribeFieldResult fieldResult = Schema.getGlobalDescribe().get(objApi).getDescribe().fields.getMap().get(fieldApi).getDescribe();
        List<SelectOption> pickListValuesList= new List<SelectOption>();
        List<Schema.PicklistEntry> ple = fieldResult.getPicklistValues();
        pickListValuesList.add(new SelectOption('', ''));
        pickListValuesList.add(new SelectOption('--无--', '--无--'));
        for( Schema.PicklistEntry pickListVal : ple){
            pickListValuesList.add(new SelectOption(pickListVal.getValue(), pickListVal.getLabel()));
        }
        return pickListValuesList;
    }
    private static Map<String, String> FIELD_NAME_MAP = new Map<String, String> {
        // 明细字段->asset字段
        'Asset__c'                       => 'Id',
        'Fixture_Model_No__c'            => 'Fixture_Model_No_F__c',
        'SerialNumber__c'                => 'SerialNumber',
        'Internal_Asset_number_key__c'   => 'Internal_Asset_number_key__c',
        'Internal_asset_location__c'     => 'Internal_asset_location__c',
        'Salesdepartment__c'             => 'Salesdepartment__c',
        'SalesProvince__c'               => 'SalesProvince__c',
        'Equipment_Type__c'              => 'Equipment_Type__c',
        'EquipmentSet_Managment_Code__c' => 'EquipmentSet_Managment_Code__c',
        'Main_OneToOne__c'               => 'Main_OneToOne__c',
        'Manage_type__c'                 => 'Manage_type__c',
        'Loaner_accsessary__c'           => 'Loaner_accsessary__c',
        'VF_Abandoned_RealThing__c'      => 'TransferableAbandon_F__c',
        'VF_You_Xiao_Ku_Cun__c'          => 'Ji_Zhong_Guan_Li_Ku_Cun__c',
        'VF_CountForRepair__c'           => 'TransferableRepair_F__c',
        'VF_Abandoned_Inventory__c'      => 'TransferableLost_F__c',
        'Product_category__c'            => 'Product_category__c'
    };
    public class TransferApplySummaryBean {
        public TransferApplySummary__c tas;
        public List<WrapperInfo> wpinfoList;
        public TransferApplySummaryBean() {
            tas = new TransferApplySummary__c();
            wpinfoList = new List<WrapperInfo>();
        }
    }
}