public with sharing class ReceivingNoteWaitingReceiptController {

    public static final String NONE = system.label.StartTrading_None;
    private List<String> assetFieldApiList;
    private List<String> receivingNoteFieldApiList;

    public List<LabelValue> outputFieldList {get; set;}
    public List<LabelValue> inputFieldList {get; set;}

    public String parId {get; set;}
    public PageBean pageB {get; set;}
    public Boolean showSelectRnsButton{get;set;}
    public String showCount {get;set;}
    public Integer nowPage {get;set;}
    public Integer maxPage {get;set;}
    public Boolean canBefore {get;set;}
    public Boolean canNext {get;set;}

    //20210806 ljh 管理编码 start
    public transient static Map<String,String> locationMap;
    static {
        locationMap = new Map<String, String> {
            '北京 备品中心' => 'BJ',
            '上海 备品中心' => 'SH',
            '广州 备品中心' => 'GZ'
        };
    }
    //20210806 ljh 管理编码 end
    // 20230117 ljh DB202301096735 start
    public List<ReceivingNoteDetail__c>  rndInfo { 
        get {
            return  [select id,Fixture_Arrival_Product__c FROM ReceivingNoteDetail__c  where Fixture_Arrival_Product__c = ''  LIMIT 1 ];
        }
    }
    // 20230117 ljh DB202301096735 end

    public ReceivingNoteWaitingReceiptController() {
        parId = System.currentPageReference().getParameters().get('parId');
        nowPage = 1;
    }

    public void init() {
        try {
            Set<String> assetFieldApiSet = new Set<String>();
            Set<String> receivingNoteFieldApiSet = new Set<String>();
            outputFieldList = setFIeldSet('ReceivingNoteDetail__c', 'ReceivingNoteWaitingReceipt_L', receivingNoteFieldApiSet);
            inputFieldList = setFIeldSet('ReceivingNoteDetail__c', 'ReceivingNoteWaitingReceipt_R', receivingNoteFieldApiSet);
            addField(receivingNoteFieldApiSet, assetFieldApiSet);
            assetFieldApiList = new List<String>();
            receivingNoteFieldApiList = new List<String>();
            assetFieldApiList.addAll(assetFieldApiSet);
            receivingNoteFieldApiList.addAll(receivingNoteFieldApiSet);
            receivingNoteFieldApiList.add('Received_Confirm_Time_F__c');
            if (String.isBlank(parId)) {
                throw new ControllerUtil.myException('请传入正确的参数');
            }
            List<ReceivingNote__c> rnList = [SELECT Id
                        , Internal_asset_location__c
                        , Sales_order_number__c
                        , OrderCode__c
                        , ApprovalNumber__c
                        , DateOfDelivery__c
                        // 20210312 you WLIG-BV8CHF start
                        //, ReceivingNoteNo__c
                        , ReceivingNoteNo_New__c
                        // 20210312 you WLIG-BV8CHF end
                        //, Status__c
                        , Asset_loaner_category__c
                        , RN_Status__c
                        , QRId__c
                     FROM ReceivingNote__c
                    WHERE Id = :parId];
            if (rnList.size() == 0) {
                throw new ControllerUtil.myException('收货清单Id不存在');
            }
            pageB = new PageBean(rnList[0], assetFieldApiList, receivingNoteFieldApiList);
            if (rnList[0].Asset_loaner_category__c == '耗材'){
                showSelectRnsButton = false;
            }
            else{
                showSelectRnsButton = true;
            }
            pageB.rn.Asset_loaner_category__c = null;

            getShowCountOps();
            changePage();
            String message = ApexPages.currentPage().getParameters().get('message');
            if(String.isNotBlank(message)){
                ApexPages.Message vfApplyMsg = new ApexPages.Message(ApexPages.severity.INFO, message);
                ApexPages.addMessage(vfApplyMsg);
            }
        }
        catch (Exception e) {
            ApexPages.addMessages(e);
        }
    }

    public List<SelectOption> getShowCountOps() {
        String countStr = System.Label.ReceivingNoteWaitingReceipt_Show_Count;
        List<String> countStrList = countStr.split(':');
        if (String.isBlank(showCount)) {
            showCount = countStrList[1];
        }
        List<SelectOption> opList = new List<SelectOption>();
        for (String str : countStrList[0].split(',')) {
            Integer iStr = Integer.valueOf(str);
            opList.add(new SelectOption(str, str));
        }
        return opList;
    }

    public void nextPage() {
        if (nowPage < maxPage) {
            nowPage ++;
            changePage();
        }
    }

    public void beforePage() {
        if (nowPage > 0) {
            nowPage --;
            changePage();
        }
    }

    private void changePage() {
        maxPage = Integer.valueOf((pageB.rowBList.size() / Integer.valueOf(showCount)));
        maxPage += Math.mod(pageB.rowBList.size(), Integer.valueOf(showCount)) > 0 ? 1 : 0;
        Integer showC = Integer.valueOf(showCount);
        Integer i = (nowPage - 1) * showC;
        Integer k = (pageB.rowBList.size() - i) > showC ? showC : (pageB.rowBList.size() - i);
        pageB.showBList = new List<RowBean>();
        System.debug(k);
        for (Integer j = i; j < i + k; j ++) {
            pageB.showBList.add(pageB.rowBList[j]);
        }
        pageB.currentPageRecordCnt = pageB.showBList.size();
        System.debug(nowPage);
        System.debug(maxPage);
        canNext = nowPage < maxPage;
        canBefore = nowPage > 1;
    }

    public List<SelectOption> getStatusOps() {
        List<FixtureUtil.RNDStatus> rndList = new List<FixtureUtil.RNDStatus>();
        rndList.add(FixtureUtil.RNDStatus.Dai_Shu_Ju_Que_Ren);
        rndList.add(FixtureUtil.RNDStatus.Yi_Shu_Ju_Que_Ren);
        rndList.add(FixtureUtil.RNDStatus.Yi_Shou_Huo_Que_Ren);
        rndList.add(FixtureUtil.RNDStatus.Yi_Qing_Dian);
        rndList.add(FixtureUtil.RNDStatus.Qing_Dian_NG);
        rndList.add(FixtureUtil.RNDStatus.Yi_Yan_Shou);
        rndList.add(FixtureUtil.RNDStatus.Yan_Shou_NG);
        rndList.add(FixtureUtil.RNDStatus.Dai_Ru_Ku_Zhi_Shi);
        rndList.add(FixtureUtil.RNDStatus.Yi_Ru_Ku_Zhi_Shi);
        rndList.add(FixtureUtil.RNDStatus.Yi_Ru_Ku);
        List<SelectOption> opList = new List<SelectOption>();
        opList.add(new SelectOption('', '--无--'));
        for (FixtureUtil.RNDStatus sNum : rndList) {
            String value = FixtureUtil.RNDStatusMap.get(sNum.ordinal());
            opList.add(new SelectOption(value, value));
        }
        return opList;
        //return getPlickList('ReceivingNote__c', 'Status__c');
    }

    public List<SelectOption> getcategoryOps() {
        return getPlickList('ReceivingNote__c', 'Asset_loaner_category__c');
    }
    public List<SelectOption> getSalesdepartmentOps() {
        List<SelectOption>  options = getPlickList('ReceivingNoteDetail__c', 'Salesdepartment__c');
        // 显示为空白，值为'x'，适用时保持原样
        options.add(0, new SelectOption('x',''));
        return options;
    }
    public List<SelectOption> getSalesProvinceOps() {
        List<SelectOption>  options = getPlickList('ReceivingNoteDetail__c', 'SalesProvince__c');
        // 显示为空白，值为'x'，适用时保持原样
        options.add(0, new SelectOption('x',''));
        return options;
    }
    public List<SelectOption> getProductCategoryOps() {
        List<SelectOption>  options = getPlickList('ReceivingNoteDetail__c', 'Product_category__c');
        // 显示为空白，值为'x'，适用时保持原样
        options.add(0, new SelectOption('x',''));
        return options;
    }
    public List<SelectOption> getEquipmentTypeOps() {
        List<SelectOption>  options = getPlickList('ReceivingNoteDetail__c', 'Equipment_Type__c');
        // 显示为空白，值为'x'，适用时保持原样
        options.add(0, new SelectOption('x',''));
        return options;
    }
    public List<SelectOption> getManageTypeOps() {
        List<SelectOption>  options = getPlickList('ReceivingNoteDetail__c', 'Manage_type__c');
        // 显示为空白，值为'x'，适用时保持原样
        options.add(0, new SelectOption('x',''));
        return options;
    }
    public List<SelectOption> getUnknowSerialNOProductOps() {
        List<SelectOption>  options = getPlickList('ReceivingNoteDetail__c', 'unknow_serial_NO_product__c');
        // 显示为空白，值为'x'，适用时保持原样
        options.add(0, new SelectOption('x',''));
        return options;
    }
    public List<SelectOption> getLoanerAccsessaryOps() {
        List<SelectOption>  options = getPlickList('ReceivingNoteDetail__c', 'Loaner_accsessary__c');
        // 显示为空白，值为'x'，适用时保持原样
        options.add(0, new SelectOption('x',''));
        return options;
    }

    public void search() {
        System.debug(assetFieldApiList);
        String wher = '';
        if (String.isNotBlank(pageB.status)) {
            wher += ' AND RND_Status__c = \'' + String.escapeSingleQuotes(pageB.status) + '\'';
        }

        if (String.isNotBlank(pageB.rn.Asset_loaner_category__c)) {
            wher += ' AND Asset_loaner_category_F__c = \'' + String.escapeSingleQuotes(pageB.rn.Asset_loaner_category__c) + '\'';
        }

        if (String.isNotBlank(pageB.fixture_Model_No)) {
            wher += ' AND Fixture_Model_No_F__c Like \'%' + String.escapeSingleQuotes(pageB.fixture_Model_No) + '%\'';
        }
        nowPage = 1;
        pageB.search(wher, assetFieldApiList, receivingNoteFieldApiList);
        changePage();
    }
    public void changeFixModel() {
        pageB.fixMode = true;
    }

    private void addField(Set<String> receivingNoteFieldApiSet, Set<String> assetFieldApiSet) {
        receivingNoteFieldApiSet.add('Id');
        receivingNoteFieldApiSet.add('Name');
        receivingNoteFieldApiSet.add('RNDAssert__c');
        receivingNoteFieldApiSet.add('ReceivingNoteSummary__c');
        receivingNoteFieldApiSet.add('Loaner_accsessary__c');
        receivingNoteFieldApiSet.add('DataConfirmation__c');
        receivingNoteFieldApiSet.add('unknow_serial_NO_product__c');
        receivingNoteFieldApiSet.add('ReceivingNoteSummary__r.ReceivingNote__c');
        receivingNoteFieldApiSet.add('ReceivingNoteSummary__r.Select_Fixture_Set_Key__c');
        receivingNoteFieldApiSet.add('ReceivingNoteSummary__r.Package_Status__c');
        receivingNoteFieldApiSet.add('Asset_loaner_category_F__c');
        receivingNoteFieldApiSet.add('Change_Point__c');
        receivingNoteFieldApiSet.add('ReceivingNoteSummary__r.Received_Confirm_Time__c');
        receivingNoteFieldApiSet.add('AcceptanceTime__c');
        receivingNoteFieldApiSet.add('DataConfirmationStaff__c');
        receivingNoteFieldApiSet.add('DataConfirmationTime__c');
        receivingNoteFieldApiSet.add('ReceivingNoteSummary__r.Wei_DataConfirmation_Cnt__c');
        receivingNoteFieldApiSet.add('Fixture_Arrival_Process__c');
        receivingNoteFieldApiSet.add('Fixture_Arrival_Product__c');
        receivingNoteFieldApiSet.add('Default_Fixture_Arrival_Process__c');
        receivingNoteFieldApiSet.add('Default_Fixture_Arrival_Product__c');
        receivingNoteFieldApiSet.add('Product_Arrival_Product__c');
        receivingNoteFieldApiSet.add('Set_Arrival_Product__c');
        receivingNoteFieldApiSet.add('RND_Status__c');
        receivingNoteFieldApiSet.add('Fixture_Set_Detail__c');
        receivingNoteFieldApiSet.add('RNDAssert__r.Consumable_Guaranteen_end__c');
        //20210809 ljh 管理编码 add start
        receivingNoteFieldApiSet.add('CodeKey__c');
        receivingNoteFieldApiSet.add('Internal_asset_location__c');
        receivingNoteFieldApiSet.add('Fixture_Model_No_F__c');
        receivingNoteFieldApiSet.add('Salesdepartment_F__c');
        receivingNoteFieldApiSet.add('Product_category_F__c');
        receivingNoteFieldApiSet.add('Equipment_Type_F__c');
        //20210809 ljh 管理编码 add end
        //20210816 rentx add start
        receivingNoteFieldApiSet.add('Fixture_Set_Detail__r.Is_Body__c');
        //20210816 rentx add end
    }

    private List<SelectOption> getPlickList(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('', NONE));
        for( Schema.PicklistEntry pickListVal : ple){
            pickListValuesList.add(new SelectOption(pickListVal.getValue(), pickListVal.getLabel()));
        }
        return pickListValuesList;
    }

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

        for (FieldSetMember fsm : fsmList) {
            if (objApi == 'Asset') {
                fieldApiSet.add('RNDAssert__r.' + fsm.getFieldPath());
            }
            else {
                fieldApiSet.add(fsm.getFieldPath());
            }
            lvList.add(new LabelValue(fsm.getLabel(), fsm.getFieldPath()));
        }
        return lvList;
    }

    // 适用区域信息提示
    public void showApplyMsg() {
        String applyMsg = ApexPages.currentPage().getParameters().get('applyMsg');
        String applyMsgType = ApexPages.currentPage().getParameters().get('applyMsgType');
        String applyErrorLabel = ApexPages.currentPage().getParameters().get('applyErrorLabel');
        if(applyMsgType == 'Fail') {
            ApexPages.Message vfApplyMsg = new ApexPages.Message(ApexPages.severity.ERROR, applyMsg);
            ApexPages.addMessage(vfApplyMsg);
            System.debug('applyMsg===' + applyMsg);
            System.debug('applyMsgType===' + applyMsgType);
            System.debug('applyErrorLabel===' + applyErrorLabel);
            if(applyErrorLabel != null) {
                System.debug('applyErrorLabel===' + applyErrorLabel);
            }
        } else {
            ApexPages.Message vfApplyMsg = new ApexPages.Message(ApexPages.severity.INFO, applyMsg);
            ApexPages.addMessage(vfApplyMsg);
        }
    }

    // 保存画面上的数据
    public PageReference saveRecord() {
        try {
            List<ReceivingNoteDetail__c> rndList = new List<ReceivingNoteDetail__c>();
            PageReference pageRef = Page.ReceivingNoteWaitingReceipt;
            pageRef.getParameters().put('parId',parId);
            pageRef.setRedirect(true);
            Datetime now = System.Now();
            String userId = Userinfo.getUserId();
            Map<Id, ReceivingNoteDetail__c>  originRndMap= new Map<Id, ReceivingNoteDetail__c> (
                [
                    SELECT Id
                         , DataConfirmation__c
                         , Received_Confirm_Time_F__c
                      FROM ReceivingNoteDetail__c
                     WHERE ReceivingNote__c =:parId
                ]
            );
            // 20210804 ljh 管理编码 add start
            Map<Id, ReceivingNoteDetail__c> codeMap = new Map<Id, ReceivingNoteDetail__c>();
            Map<String,List<Id>> fsMap = new Map<String,List<Id>>();
            List<Id> rIdList = new List<Id>();
            List<Id> rIdAList = new List<Id>();
            Map<String,List<Id>> fsAssetMap = new Map<String,List<Id>>();
            Set<Id> xl0Id = new Set<Id>();
            Set<Id> xl0AssetId = new Set<Id>();
            Map<String, List<ReceivingNoteDetail__c>> codeNewMap = new Map<String, List<ReceivingNoteDetail__c>>();
            Set<Id> RNDClearId = new Set<Id>();
            Map<Id, ReceivingNoteDetail__c> rndMap = new Map<Id, ReceivingNoteDetail__c>();
            List<Asset_EquipmentSet_Managment_Code__c> aesmUList = new List<Asset_EquipmentSet_Managment_Code__c>();
            String xl0 = System.Label.xl0String;
            List<String> xl0List = xl0.split(';');
            // 20210804 ljh 管理编码 add end
            Integer a = 0;
            for (RowBean rowB : pageB.showBList) {
                rowB.rnd.Product_Arrival_Product__c = rowB.rnd.Default_Fixture_Arrival_Product__c;
                // 合并またはなしを選択するとき、备品入库产品をクリアする
                if ('合并' == rowB.rnd.Fixture_Arrival_Process__c
                    || String.isBlank(rowB.rnd.Fixture_Arrival_Process__c)
                ) {
                    rowB.rnd.Fixture_Arrival_Product__c = null;
                }
                if (rowB.checked) {
                    //add by rentx 20210727 新品收货_集中备品_建立数据逻辑限制  start
                    // 20211027 ljh update SFDC-C7ZD9J start
                    //备品用途附属品为“TURE”时，备品管理编码填充时不可提交；备品用途附属品为“FASLE”时，备品管理编码不填充不可提交；
                    // if (rowB.rnd.Loaner_accsessary__c == 'TRUE' && String.isNotBlank(rowB.rnd.EquipmentSet_Managment_Code__c)) {
                    //     rowB.rnd.EquipmentSet_Managment_Code__c.addError('无需填写备品管理编码');
                    //     a ++ ;
                    // }
                    // 20211027 ljh update SFDC-C7ZD9J end
                    //有配套的带过来后如果改错了，要报错。
                    // if ((rowb.peiTao == 'FALSE' && rowb.rnd.Loaner_accsessary__c == 'TRUE') || (rowb.peiTao == 'TRUE' && rowb.rnd.Loaner_accsessary__c == 'FALSE')) {
                    //     rowB.rnd.Loaner_accsessary__c.addError('备品用途附属品不正确');
                    //     a ++ ;
                    // }
                    // if (rowB.rnd.Loaner_accsessary__c == 'FALSE' && String.isBlank(rowB.rnd.EquipmentSet_Managment_Code__c)) {
                    //     rowB.rnd.EquipmentSet_Managment_Code__c.addError('必须填写备品管理编码');
                    //     a ++ ;
                    // }
                    // 当无机身号码设备TRUE且备品用途附属品为TRUE，且管理种类为个体管理时，不可提交，报错管理种类（可不区分报错名称）
                    if (rowb.rnd.unknow_serial_NO_product__c == 'TRUE' && rowb.rnd.Loaner_accsessary__c == 'TRUE' &&rowb.rnd.Manage_type__c == '个体管理') {
                        rowB.rnd.Manage_type__c.addError('管理种类有误');
                        a ++ ;
                    }
                    //备品类别 = 耗材 不适用 add by rentx 20210913 start
                    if (showSelectRnsButton) {
                        //当无机身号码设备为FALSE或备品用途附属品为FALSE，且管理种类为数量管理时，不可提交，报错管理种类（可不区分报错名称）
                        if ((rowb.rnd.unknow_serial_NO_product__c == 'FALSE' || rowb.rnd.Loaner_accsessary__c == 'FALSE') && rowb.rnd.Manage_type__c == '数量管理') {
                            rowB.rnd.Manage_type__c.addError('管理种类有误');
                            a ++ ;
                        }
                    }
                    //备品类别 = 耗材 不适用 add by rentx 20210913 end
                    // 备品分类 = 检测用备品时，所在地区（本部）只能选择0.备品中心，选择其他本部时报错提示【检测用备品的所在地区（本部）应为0.备品中心】
                    if (rowb.rnd.Equipment_Type__c == '检测用备品' && rowb.rnd.Salesdepartment__c != '0.备品中心') {
                        rowB.rnd.Equipment_Type__c.addError('检测用备品的所在地区（本部）应为0.备品中心');
                        a ++ ;
                    }
                    //add by rentx 20210727 新品收货_集中备品_建立数据逻辑限制  end

                    if(originRndMap.containsKey(rowB.rnd.Id)) {
                        ReceivingNoteDetail__c originRnd = originRndMap.get(rowB.rnd.Id);
                        if(originRnd.DataConfirmation__c && originRnd.Received_Confirm_Time_F__c != null) {
                            throw new ControllerUtil.myException('【' + rowB.rnd.Name + '】已收货确认，不可勾选和修改');
                        }
                    }
                    else {
                        throw new ControllerUtil.myException('【' + rowB.rnd.Name + '】不存在，请刷新画面重试');
                    }
                    if(rowB.rnd.DataConfirmation__c){
                        rowB.rnd.DataConfirmationTime__c = now;
                        rowB.rnd.DataConfirmationStaff__c = userId;
                    }
                    else {
                        rowB.rnd.DataConfirmationTime__c = null;
                        rowB.rnd.DataConfirmationStaff__c = null;
                    }
                    //20210804 ljh 管理编码 start
                    /*
                    ⭐备品用途附属品=FALSE
                    */
                    if( String.isNotBlank(rowb.rnd.Loaner_accsessary__c) && rowb.rnd.Loaner_accsessary__c == 'FALSE'){
                        if(String.isBlank(rowb.rnd.RNDAssert__c)
                            || (String.isBlank(rowb.rnd.Salesdepartment_F__c) && String.isBlank(rowb.rnd.Salesdepartment__c))
                            || (String.isBlank(rowb.rnd.Product_category_F__c) && String.isBlank(rowb.rnd.Product_category__c))
                            || (String.isBlank(rowb.rnd.Equipment_Type_F__c) && String.isBlank(rowb.rnd.Equipment_Type__c))
                            ){
                            // throw new ControllerUtil.myException('【' + rowB.rnd.Name + '】没有对应的保有设备或者配套，管理编码无法编码');
                        }else{
                            System.debug('zheli00');
                            if(fsMap.containsKey(rowB.rnd.Fixture_Model_No_F__c)){
                                rIdList = fsMap.get(rowB.rnd.Fixture_Model_No_F__c);
                                rIdList.add(rowB.rnd.Id);
                                fsMap.put(rowB.rnd.Fixture_Model_No_F__c,rIdList);
                            }else{
                                rIdList = new List<Id>();
                                rIdList.add(rowB.rnd.Id);
                                fsMap.put(rowB.rnd.Fixture_Model_No_F__c,rIdList);
                            }
                            if(fsAssetMap.containsKey(rowb.rnd.Fixture_Model_No_F__c)){
                                rIdAList = fsAssetMap.get(rowb.rnd.Fixture_Model_No_F__c);
                                rIdAList.add(rowb.rnd.RNDAssert__c);
                                fsAssetMap.put(rowb.rnd.Fixture_Model_No_F__c,rIdAList);
                            }else{
                                rIdAList = new List<Id>();
                                rIdAList.add(rowb.rnd.RNDAssert__c);
                                fsAssetMap.put(rowb.rnd.Fixture_Model_No_F__c,rIdAList);
                            }
                            codeMap.put(rowb.rnd.RNDAssert__c,rowB.rnd);
                        }
                    }
                    // 20211027 ljh add SFDC-C7ZD9J start
                    else{
                        if(String.isNotBlank(rowb.rnd.Loaner_accsessary__c) && rowb.rnd.Loaner_accsessary__c == 'TRUE' 
                            && (String.isNotBlank(rowb.rnd.CodeKey__c) || String.isNotBlank(rowb.rnd.EquipmentSet_Managment_Code__c))
                        ){
                            RNDClearId.add(rowb.rnd.Id);
                        } 
                    }
                    // 20211027 ljh add SFDC-C7ZD9J end
                    //20210804 ljh 管理编码 end
                    rndList.add(rowB.rnd);
                }
            }

            //update by rentx 20210727 新品收货_集中备品_建立数据逻辑限制  start
            if (a > 0) {
                return null;
            }
            //update by rentx 20210727 新品收货_集中备品_建立数据逻辑限制  end
            //20210804 ljh 管理编码 start
            /*
            ⭐备品用途附属品=FALSE
            备品分类 、备品存放地、所在地区(本部)、产品分类、备品管理编码系列
            1.需要判断保有设备是否已有管理编码
            1.1有 需要看相关字段是否发生改变
            1.2无 新生成
            */
            if(fsMap.size() > 0){
                List<Fixture_Set__c> fsdList =  [SELECT Id, Name,Loaner_categoryII__c 
                 FROM Fixture_Set__c WHERE Name IN:fsMap.keySet()];
                for(Fixture_Set__c fs:fsdList){
                    if(xl0List.contains(fs.Loaner_categoryII__c)){
                        for(String fsm:fsMap.get(fs.Name)){
                            xl0Id.add(fsm);
                        }
                    }
                }
                List<Fixture_Set__c> fsList =  [SELECT Id, Name, Loaner_categoryII__c 
                 FROM Fixture_Set__c WHERE Name IN:fsAssetMap.keySet()];
                for(Fixture_Set__c fs:fsList){
                    if(xl0List.contains(fs.Loaner_categoryII__c)){
                        for(String fsa:fsAssetMap.get(fs.Name)){
                            xl0AssetId.add(fsa);
                        }
                    }
                }
            }
            if(codeMap.size()>0){
                List<Asset> AssetList =  [SELECT Id, Name,Equipment_Type__c,Internal_asset_location__c,Salesdepartment__c,
                 Product_category__c,EquipmentSet_Managment_Code__c 
                 FROM Asset WHERE Id IN:codeMap.keySet()];
                 /**
                 备品分类  Equipment_Type__c
                 备品存放地 Internal_asset_location__c
                 所在地区(本部) Salesdepartment__c
                 产品分类 Product_category__c
                 */
                for(Asset ass:AssetList){
                    ReceivingNoteDetail__c RNde = codeMap.get(ass.Id);
                    List<ReceivingNoteDetail__c> RNdeList = new List<ReceivingNoteDetail__c>();
                    // key1 保有设备上 key2一览明细本次 key3一览明细上次 
                    String key1 = '';
                    // 1. 备品分类
                    if(String.isNotBlank(ass.Equipment_Type__c) && ass.Equipment_Type__c == '检测用备品'){
                        key1 += 'JC;'+locationMap.get(ass.Internal_asset_location__c);    
                    }else if(String.isNotBlank(ass.Equipment_Type__c)){
                        key1 += 'NJC;';
                        //2.本部 
                        if(String.isNotBlank(ass.Salesdepartment__c)){
                            String[] SalesdepartmentArr = ass.Salesdepartment__c.split('\\.');
                            if(SalesdepartmentArr.size() > 0){
                                String Salesdepartment = SalesdepartmentArr[0];
                                key1 += Salesdepartment+';';
                                //3.是否0系列
                                Integer SalesdepartmentI = Integer.valueOf(Salesdepartment);
                                if(xl0AssetId.contains(ass.Id)){
                                    if(SalesdepartmentI == 0 || SalesdepartmentI == 10){
                                        key1 += '0;'+locationMap.get(ass.Internal_asset_location__c);
                                    }else{
                                        key1 += '0';
                                    }
                                }else{
                                    key1 += 'N0;';
                                    if(SalesdepartmentI == 0 || (SalesdepartmentI > 6 && SalesdepartmentI < 12) || SalesdepartmentI == 16){
                                        key1 += ass.Product_category__c+';'+locationMap.get(ass.Internal_asset_location__c);
                                    }else if(SalesdepartmentI < 7){
                                        key1 += ass.Product_category__c;
                                    }
                                }
                            }
                        }
                    }
                    
                    // 备品运输单一览明细 key 
                    String key2 = '';
                    // 1. 备品分类
                    system.debug('zheli01:'+RNde.Equipment_Type__c);
                    if((String.isNotBlank(RNde.Equipment_Type__c) && RNde.Equipment_Type__c == '检测用备品')
                        || (String.isBlank(RNde.Equipment_Type__c) && String.isNotBlank(RNde.Equipment_Type_F__c) && RNde.Equipment_Type_F__c == '检测用备品')
                        ){
                        key2 += 'JC;'+locationMap.get(RNde.Internal_asset_location__c);    
                    }else{
                        key2 += 'NJC;';
                        //2.本部
                        String SalesdepartmentS = String.isNotBlank(RNde.Salesdepartment__c)?RNde.Salesdepartment__c:RNde.Salesdepartment_F__c;
                        if(String.isNotBlank(SalesdepartmentS)){
                            String[] SalesdepartmentArr = SalesdepartmentS.split('\\.');
                            if(SalesdepartmentArr.size() > 0){
                                String Salesdepartment = SalesdepartmentArr[0];
                                System.debug('zheli33:'+SalesdepartmentS+'~'+SalesdepartmentArr);
                                key2 += Salesdepartment+';';
                                //3.是否0系列
                                Integer SalesdepartmentI = Integer.valueOf(Salesdepartment);
                                if(xl0Id.contains(RNde.Id)){
                                    if(SalesdepartmentI == 0 || SalesdepartmentI == 10){
                                        key2 += '0;'+locationMap.get(RNde.Internal_asset_location__c);
                                    }else{
                                        key2 += '0';
                                    }
                                }else{
                                    key2 += 'N0;';
                                    key2 += String.isNotBlank(RNde.Product_category__c)?RNde.Product_category__c:RNde.Product_category_F__c;
                                    if(SalesdepartmentI == 0 || (SalesdepartmentI > 6 && SalesdepartmentI < 12) || SalesdepartmentI == 16){
                                        key2 +=';'+locationMap.get(RNde.Internal_asset_location__c);
                                    }
                                }
                            }
                        }
                    }
                    System.debug('zheli:'+key2);
                    String key3 = RNde.CodeKey__c;
                    if(String.isNotBlank(key3)){
                        if(key2 != key3 && key1 != key2){
                            if(codeNewMap.containsKey(key2)){
                                RNdeList = codeNewMap.get(key2);
                                RNdeList.add(RNde);
                                codeNewMap.put(key2,RNdeList);
                            }else{
                                RNdeList = new List<ReceivingNoteDetail__c>();
                                RNdeList.add(RNde);
                                codeNewMap.put(key2,RNdeList);
                            }
                        }else if(key2 != key3 && key2 == key1){
                            RNDClearId.add(RNde.Id);//清空上次管理编码和保有设备编码一样了 有管理编码公式 空=保有设备管理编码
                        }
                    }else {
                        if(codeNewMap.containsKey(key2)){
                            RNdeList = codeNewMap.get(key2);
                            RNdeList.add(RNde);
                            codeNewMap.put(key2,RNdeList);
                        }else{
                            RNdeList = new List<ReceivingNoteDetail__c>();
                            RNdeList.add(RNde);
                            codeNewMap.put(key2,RNdeList);
                        }
                    }
                }
            }
            //重新编码
            // 20212103 ljh SFDC-C8ZATE start
            List<Asset_EquipmentSet_Managment_Code__c> aemCodeList = new List<Asset_EquipmentSet_Managment_Code__c>();
            Map<String,Asset_EquipmentSet_Managment_Code__c> oldCodeMap = new Map<String,Asset_EquipmentSet_Managment_Code__c>();
            // 20212103 ljh SFDC-C8ZATE end
            if(codeNewMap.size() > 0){
                // 20212103 ljh SFDC-C8ZATE start
                // List<Asset_EquipmentSet_Managment_Code__c> aemCodeList = [SELECT Id, key__c, 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(ReceivingNoteDetail__c rnde1: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);
                            }
                            ReceivingNoteDetail__c rnde2 = new ReceivingNoteDetail__c();
                            rnde2.Id = rnde1.Id;
                            rnde2.EquipmentSet_Managment_Code__c= codeManange;
                            rnde2.CodeKey__c = aem.key__c;
                            rndMap.put(rnde1.Id,rnde2); 

                        }
                        oldCodeMap.put(aem.Id,aem); // 20212103 ljh SFDC-C8ZATE end
                        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);
                    }
                }
            }
            //20210804 ljh 管理编码 end
            
            if (rndList.size() > 0) {
                //20210804 ljh 管理编码 start
                for(ReceivingNoteDetail__c rnd:rndList){
                    if(RNDClearId.contains(rnd.Id)){
                       rnd.EquipmentSet_Managment_Code__c = ''; //有管理编码公式 空=保有设备管理编码
                       rnd.CodeKey__c = ''; // 20211027 ljh add SFDC-C7ZD9J start
                    }
                    if(rndMap.containsKey(rnd.Id)){
                       rnd.EquipmentSet_Managment_Code__c = rndMap.get(rnd.Id).EquipmentSet_Managment_Code__c; 
                       rnd.CodeKey__c = rndMap.get(rnd.Id).CodeKey__c; 
                    }
                }
                //20210804 ljh 管理编码 end
                // 20212103 ljh SFDC-C8ZATE start
                // 判断此时此刻的值 是否和最初的值是否一样，不一样提示
                List<Asset_EquipmentSet_Managment_Code__c> aemCodeNowList = [SELECT Id, key__c, code__c,   
                        LastNo__c, keyName__c, isSpecial__c, MaxLastNo__c FROM Asset_EquipmentSet_Managment_Code__c
                        WHERE Id IN :aesmUList];
                for(Asset_EquipmentSet_Managment_Code__c codeNow:aemCodeNowList){
                    //if(oldCodeMap.containsKey(codeNow.Id)){
                    if(oldCodeMap.get(codeNow.Id).LastNo__c != codeNow.LastNo__c){
                        // 提示有问题稍后重试
                        throw new ControllerUtil.myException('编码数据异常，请稍后重试!');
                    }
                    //}
                }        
                update aesmUList; //20210809 ljh 管理编码
                // 20212103 ljh SFDC-C8ZATE end
                update rndList; 
                // update aesmUList; //20210809 ljh 管理编码
                pageRef.getParameters().put('message','已保存');
            }
            return pageRef;
        }
        catch (Exception e) {
            ApexPages.addMessages(e);
        }
        return null;
    }

    public PageReference SelectRNS() {
        try {
            List<String> rowId = new List<String>();
            String rdId;
            String snumber;
            Set<String> selectKey = new Set<String>();
            Set<String> modelKey = new Set<String>();
            Boolean haveCheck = false;
            Boolean direct = true;
            Map<Id, ReceivingNoteDetail__c>  originRndMap= new Map<Id, ReceivingNoteDetail__c> (
                [
                    SELECT Id
                         , DataConfirmation__c
                         , Received_Confirm_Time_F__c
                      FROM ReceivingNoteDetail__c
                     WHERE ReceivingNote__c =:parId
                ]
            );
            for (RowBean rowB : pageB.rowBList) {
                if (rowb.checked) {
                    if(originRndMap.containsKey(rowB.rnd.Id)) {
                        ReceivingNoteDetail__c originRnd = originRndMap.get(rowB.rnd.Id);
                        if(originRnd.DataConfirmation__c && originRnd.Received_Confirm_Time_F__c != null) {
                            throw new ControllerUtil.myException('【' + rowB.rnd.Name + '】已收货确认，不可勾选和修改');
                        }
                    }
                    else {
                        throw new ControllerUtil.myException('【' + rowB.rnd.Name + '】不存在，请刷新画面重试');
                    }
                    if(String.isblank(rowB.rnd.RNDAssert__c)){
                        throw new ControllerUtil.myException('存在不带保有设备的明细,不可以选择配套');
                    }
                    if(String.isBlank(rowB.rnd.Asset_loaner_category_F__c) || rowB.rnd.Asset_loaner_category_F__c == '耗材') {
                        throw new ControllerUtil.myException('备品类别是空或耗材,没有配套信息');
                    }
                    rowId.add(rowB.rnd.ReceivingNoteSummary__c);
                    if (selectKey.isEmpty()) {
                        selectKey.add(rowB.rnd.ReceivingNoteSummary__r.Select_Fixture_Set_Key__c);
                        modelKey.add(rowB.rnd.Fixture_Model_No_F__c);
                    }
                    //if (selectKey.contains(rowB.rnd.ReceivingNoteSummary__r.Select_Fixture_Set_Key__c) == false) {
                    //    throw new ControllerUtil.myException('明细所在一览的【备品配套】或【最后修改人】或【最后修改时间】不一致,不可以一起选择配套');
                    //}
                    if (modelKey.contains(rowB.rnd.Fixture_Model_No_F__c) == false) {
                        throw new ControllerUtil.myException('有不统一的备品配套明细型号一起选择,不可以一起选择配套');
                    }
                    rdId = rowB.rnd.ReceivingNoteSummary__r.ReceivingNote__c;
                    if (String.isBlank(snumber)) {
                        snumber = rowB.rnd.Id;
                    }
                    if(String.isNotBlank(rowB.rnd.Fixture_Set_Detail__c)){
                        direct = false;
                    }
                    haveCheck = true;
                }
            }
            if (haveCheck == false) {
                throw new ControllerUtil.myException('请选择收货清单一览明细');
            }
            PageReference pg = new PageReference('/apex/ReceivingNoteSummarySelect?pt_recid=' + rdId + '&raesid=' + String.join(rowId, ','));
            pg.setRedirect(true);
            pg.getParameters().put('pt_recid', rdId);
            pg.getParameters().put('raesid', String.join(rowId, ','));
            pg.getParameters().put('direct', String.valueOf(direct));

            return pg;
        }
        catch (Exception e) {
            ApexPages.addMessages(e);
        }
        return null;
    }

    /**
    @description 取消按钮Action
                 OLY_OCM-768 指摘【取消】按钮的功能是关闭画面，此处为提高覆盖率而注释掉
    */
    //public PageReference cancelRecord() {
    //    try {
    //        Set<String> rnsIdList = new Set<String>();
    //        for (RowBean rowB : pageB.rowBList) {
    //            if (rowB.checked) {
    //                rnsIdList.add(rowB.rnd.ReceivingNoteSummary__c);
    //            }
    //        }
    //        List<ReceivingNoteDetail__c> rndList = [SELECT Id
    //                 FROM ReceivingNoteDetail__c
    //                WHERE RNDAssert__c = null
    //                  AND ReceivingNoteSummary__c = :rnsIdList];
    //        if (rndList.size() > 0) {
    //            delete rndList;
    //        }
    //        else {
    //            ApexPages.Message vfApplyMsg = new ApexPages.Message(ApexPages.severity.WARNING, '没有需要取消的收货清单配套一览');
    //            ApexPages.addMessage(vfApplyMsg);
    //        }
    //        search();
    //    }
    //    catch (Exception e) {
    //        ApexPages.addMessages(e);
    //    }
    //    pageB.fixMode = false;
    //    return null;
    //}

    // 型号提醒邮件Action
    public void sendEmail() {
        Savepoint sp = Database.setSavepoint();
        try{
            String emailBody = System.currentPageReference().getParameters().get('emailBody');
            String templateBody = '【自由填写内容】\n{0}\n';
                   templateBody += '备品配套明细型号：\n';
            emailBody = String.format(templateBody, new List<String> {emailBody});
            String emailMsg = '';
            for (RowBean rowB : pageB.showBList) {
                if (rowB.checked) {
                   emailMsg += rowB.rnd.Fixture_Model_No_F__c + '\n';
                }
            }
            if (String.isNotBlank(emailMsg)) {
                // 20231129 ljh DB202311669319 start
                // pageB.rn.Model_Reminder_Email_Text__c = null;
                // update pageB.rn;
                // pageB.rn.Model_Reminder_Email_Text__c = emailBody  + emailMsg;
                // update pageB.rn;
                // System.debug('zhelizheli:'+pageB.rn);
                ReceivingNote__c rn = New ReceivingNote__c();
                ReceivingNote__c rnNew = New ReceivingNote__c();
                rn.Id = pageB.rn.Id;
                rn.Model_Reminder_Email_Text__c = null;
                update rn;
                rnNew.Id = pageB.rn.Id;
                rnNew.Model_Reminder_Email_Text__c = emailBody  + emailMsg;
                update rnNew;
                // 20231129 ljh DB202311669319 end
                ApexPages.Message vfApplyMsg = new ApexPages.Message(ApexPages.severity.INFO, '已发送');
                ApexPages.addMessage(vfApplyMsg);
            }
            else {
                throw new ControllerUtil.myException('请选择型号提醒邮件明细');
            }
        }
        catch (Exception e) {
            Database.rollback(sp);
            ApexPages.addMessages(e);
        }
    }


    public class PageBean {
        /* ------------ 复数编辑用 ------------ */
        public ReceivingNoteDetail__c assetInput {get{
            if (assetInput == null) {
                assetInput = [SELECT Id
                         FROM ReceivingNoteDetail__c
                        LIMIT 1];
                assetInput = new ReceivingNoteDetail__c(Id = assetInput.Id);
            }
            return assetInput;
        } set;}

        /* ------------ 检索用 ------------ */
        public ReceivingNote__c rn {get; set;}
        public String fixture_Model_No {get; set;}
        public String status {get;set;}

        /* ------------  显示用 ------------ */
        public String dateOfDelivery {get; set;}

        /* ------------ 明细一覧 ------------ */
        public List<RowBean> rowBList {get; set;}
        public List<RowBean> showBList {get; set;}

        /* ------------ 记录用 ------------ */
        public Boolean fixMode {get; set;}
        public Integer currentPageRecordCnt {get; set;}

        public PageBean() {
            rn = new ReceivingNote__c();
            rowBList = new List<RowBean>();
            showBList = new List<RowBean>();
            fixMode = false;
            currentPageRecordCnt = 0;
        }

        public PageBean(ReceivingNote__c rnObj, List<String> assetFieldApiList, List<String> receivingNoteFieldApiList) {
            rn = rnObj;
            dateOfDelivery = rnObj.DateOfDelivery__c == null ? '' : rnObj.DateOfDelivery__c.format();
            rowBList = new List<RowBean>();
            showBList = new List<RowBean>();
            fixMode = false;
            search(null, assetFieldApiList, receivingNoteFieldApiList);
        }

        public void search(String wher, List<String> assetFieldApiList, List<String> receivingNoteFieldApiList) {
            wher = String.isBlank(wher) ? '' : wher;
            System.debug(assetFieldApiList);
            String soql = 'SELECT '
                    + String.join(assetFieldApiList, ',')
                    + (assetFieldApiList.size() > 0 ? ',' : '')
                    + String.join(receivingNoteFieldApiList, ',')
                 + ' FROM ReceivingNoteDetail__c '
                + ' WHERE ReceivingNoteSummary__r.ReceivingNote__c = \'' + rn.Id + '\'' + wher
                  + ' AND Delete_Flag__c = false '
                + ' ORDER BY ReceivingNoteSummary__c, ReceivingNoteDetailNo__c, RNDAssert__c nulls last';
            rowBList = new List<RowBean>();
            showBList = new List<RowBean>();
            System.debug(soql);
            List<ReceivingNoteDetail__c> rndList = Database.query(soql);
            Integer i = 0;
            // DB202306213019 【P5: 新品入库时根据订单编码自动判断产品分类】 20230625 by lc add Start
            String GISPStr = rn.OrderCode__c.split('-')[1];
            String defaultGISP = null;
            // 只有固定资产需要默认产品分类
            if (rn.Asset_loaner_category__c == '固定资产') {
                if (GISPStr.contains('GI')) {
                    defaultGISP = 'GI';
                } else if (GISPStr.contains('SP')) {
                    defaultGISP = 'SP';
                } else {
                    defaultGISP = '';
                }
            }
            // DB202306213019 【P5: 新品入库时根据订单编码自动判断产品分类】 20230625 by lc add End
            for (ReceivingNoteDetail__c rnd : rndList) {
                rowBList.add(new RowBean(rnd, i, defaultGISP));
                i ++;
            }
            
            currentPageRecordCnt = showBList.size();
        }
    }

    public class RowBean {
        public Boolean checked {get; set;}
        public Boolean canChange {get; set;}
        public Boolean dataConfirmation {get; set;}
        public String canChangeField {get; set;}
        public String canNotChangeField {get; set;}
        public Integer lineNo {get; set;}
        public Boolean haveAsset {get; set;}
        public ReceivingNoteDetail__c rnd {get; set;}

        //add by rentx 20210809 start 新品收货_集中备品_建立数据逻辑限制
        public String peiTao {get; set;}
        //add by rentx 20210809 end 新品收货_集中备品_建立数据逻辑限制

        public RowBean() {
            checked = false;
            rnd = new ReceivingNoteDetail__c();
            canChange = true;
            dataConfirmation = false;
            canChangeField = '';
            peiTao = '';
        }

        public RowBean(ReceivingNoteDetail__c rnd1, Integer lineNo1, String defaultGISP) {
            rnd = rnd1;
            checked = false;
            canChange = true;
            dataConfirmation = rnd1.DataConfirmation__c;
            lineNo = lineNo1;
            // 产品入库产品 是 空, 说明是第一次打开画面 而且 没有保存过
            if (null == rnd.Product_Arrival_Product__c
                && String.isBlank(rnd.Fixture_Arrival_Process__c)
            ) {
                rnd.Fixture_Arrival_Process__c = rnd.Default_Fixture_Arrival_Process__c;
                rnd.Fixture_Arrival_Product__c = rnd.Default_Fixture_Arrival_Product__c;
            }
            // 收货确认过的明细不可编辑
            if( rnd.DataConfirmation__c && rnd.Received_Confirm_Time_F__c != null) {
                canChange = false;
            }

            // DB202306213019 【P5: 新品入库时根据订单编码自动判断产品分类】 20230625 by lc add Start
            if (defaultGISP != null && rnd.Loaner_accsessary__c == 'FALSE') {
                rnd.Product_category__c = defaultGISP;
            }
            // DB202306213019 【P5: 新品入库时根据订单编码自动判断产品分类】 20230625 by lc add End

            if (rnd1.Asset_loaner_category_F__c == '耗材') {
                canChangeField = 'Salesdepartment__c, DataConfirmation__c, Equipment_Type__c';
            }
            else{
                canChangeField = '';
            }
            canNotChangeField = 'SerialNumber_Origin__c, SerialNumber__c, Change_Point__c, PeriodOfUse_Final__c';
            // 数据确认后、备品入库处理、备品入库产品が変更不可とする
            if ('待数据确认' != rnd1.RND_Status__c) {
                canNotChangeField += ', Fixture_Arrival_Process__c, Fixture_Arrival_Product__c';
            }
            haveAsset = String.isNotBlank(rnd1.RNDAssert__c);
            //add by rentx 202108 start
            peiTao = rnd1.Loaner_accsessary__c;
            //add by rentx 202108 end

        }
    }

    public class LabelValue {
        public String label {get; set;}
        public String value {get; set;}

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

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

}