@RestResource(urlMapping = '/NFM105/*')
global with sharing class NFM105Rest  {

    global class RepairStatusUpdateRest {
        public RepairStatusUpdate RepairStatusUpdate;
    }

    // Integer batchsize = 200;  考量する必要がないと思います。
    global class RepairStatusUpdate {
        public NFMUtil.Monitoring Monitoring;
        public GeneralData[] GeneralData;
    }
    global class GeneralData {
        public String SFDCRepairNo;     //修理名称
        public String SAPRepairNo;      //SAP修理单号
        public String SAPQuotationNo;
        public String ReRepairObject;
        public String RepairOrderStatusCode;    //修理单状态编号
        public String RepairOrderStatusName;
        public String StatusUpdateDate;
        public String StatusUpdateTime;
        public String PlannedRepairFinishDate;
        public String StatusUpdatePersonName;
        public String CancellationReason;
        public String IncorrectDataComment;
        public String ReturnType;
        public String InspectType;
        //WLIG-CC78MX 【委托】NFM105接口增加OTS运单号字段 thh 20220307 start
        public String OTSRepairOrder;
        //WLIG-CC78MX 【委托】NFM105接口增加OTS运单号字段 thh 20220307 end
        public InspectionResultInformation[] InspectionResultInformation;
        public FailureInformation[] FailureInformation;
    }
    global class InspectionResultInformation {
        public String InspectionResultFlag;
        public String InspectionComment;
        public String FailureCause;
    }
    global class FailureInformation {
        public String LocationGroupName;
        public String LocationName;
        public String PhenomenonName;
        public String CauseName;
        public String DescriptionName;
    }

    @HttpPost
    global static void execute() {

        // 取得接口传输内容
        String strData = RestContext.request.requestBody.toString();
        RepairStatusUpdateRest ges = (RepairStatusUpdateRest) JSON.deserializeStrict(strData, RepairStatusUpdateRest.class);

        if (ges == null ) {
            return;
        }

        NFMUtil.Monitoring Monitoring = ges.RepairStatusUpdate.Monitoring;
        if (Monitoring == null) {
            return;
        }

        BatchIF_Log__c rowData = NFMUtil.saveRowData(Monitoring, 'NFM105', ges.RepairStatusUpdate.GeneralData);
        if (String.isBlank(rowData.Log__c) == false) {
            executefuture(rowData.Id);
        }

        // JSONを戻す
        RestResponse res = RestContext.response;
        res.addHeader('Content-Type', 'application/json');
        res.statusCode = 200;
        //String jsonResponse = '{"status": "Success", "Message":'  + gedata + '}';
        String jsonResponse = '{"status": "Success", "Message":""}';
        res.responseBody = blob.valueOf(jsonResponse);
        return;
    }

    @future
    global static void executefuture(String rowData_Id) {
        main(rowData_Id);
    }
    global static void main(String rowData_Id) {
        Integer batch_retry_max_cnt = Integer.valueOf(System.Label.batch_retry_max_cnt);
        BatchIF_Log__c rowData = [Select Id, Name, Log__c, ErrorLog__c, Log2__c, Log3__c, Log4__c, Log5__c, Log6__c, Log7__c, Log8__c, Log9__c, Log10__c, Log11__c, Log12__c, MessageGroupNumber__c, TransmissionDateTime__c, retry_cnt__c from BatchIF_Log__c where RowDataFlg__c = true and Id = :rowData_Id];
        String logstr = rowData.MessageGroupNumber__c + ' start\n';
        BatchIF_Log__c iflog = new BatchIF_Log__c();
        iflog.Type__c = 'NFM105';
        iflog.MessageGroupNumber__c = rowData.MessageGroupNumber__c;
        iflog.Log__c = logstr;
        iflog.ErrorLog__c = '';
        insert iflog;
        String rowDataStr = NFMUtil.getRowDataStr(rowData);
        List<GeneralData> generalDataList = (List<GeneralData>) JSON.deserialize(rowDataStr, List<GeneralData>.class);
        if (generalDataList == null || generalDataList.size() == 0) {
            return;
        }

        Savepoint sp = Database.setSavepoint();
        try {
            //repairNo list
            List<String> sapRepairNoList  = new List<String>();
            List<String> sfdcRepairNoList = new List<String>();
            List<String> quotationNoList  = new List<String>();
            for (GeneralData quoteInfo : generalDataList) {
                // 必須項目がない場合、処理と飛ばす
                if (quoteInfo.SAPRepairNo == null || quoteInfo.SAPRepairNo == '') {
                    iflog.ErrorLog__c += 'SAPRepairNo is required\n';
                    System.debug(Logginglevel.ERROR, 'NFM105_continue');
                    continue;
                } else {
                    sapRepairNoList.add(quoteInfo.SAPRepairNo);
                }
                if (quoteInfo.SAPQuotationNo != null && quoteInfo.SAPQuotationNo != '') {
                    quotationNoList.add(quoteInfo.SAPQuotationNo);
                }
                if (quoteInfo.SFDCRepairNo != null && quoteInfo.SFDCRepairNo != '') {
                    sfdcRepairNoList.add(quoteInfo.SFDCRepairNo.toUpperCase());
                }
            }
            System.debug('120');

            //20211109 lt start
            // Map<List<String>,List<String>> conMap = new Map<List<String>,List<String>>();
            // conMap.put(sapRepairNoList, sfdcRepairNoList);
            //20211109 lt end
            //sapの外部keyで検索
            //sap外键检索修理  sapRepairsMap

            //sfdcのnameで検索
            //sfdc名字检索修理  sfdcRepairsMap
            // List<Repair__c> sapRpairList = [select Id, Name, SAPRepairNo__c, Delivered_Product__c
            //                                 , RepairOrderStatusName__c, RepairOrderStatusCode__c
            //                                 , CancellationReason__c, IncorrectDataComment__c
            //                                 , Repair_Rank__c, Repair_Ordered_Date__c
            //                                 , Invalid_check__c, Delete_Flag__c
            //                                 , Facility_Return_Receipt_Collection_Date__c, Receipt_received_date__c
            //                                 , Return_Without_Repair_IF__c, Return_Without_Repair_Reason__c
            //                                 , Repair_Quotation_Id__c, NFM105_MessageGroupNumber__c, Repair_List_Price_formula__c
            //                                 , ReturnType__c, InspectType__c
            //                                 //add by rentx 2021-3-4 start
            //                                 ,Maintenance_Contract__r.URF_Contract__c
            //                                 ,Maintenance_Contract__c
            //                                 ,SerialNumber__c,
            //                                 Agreed_Date__c 
            //                                 //add by rentx 2021-3-4 end
            //                                 from Repair__c
            //                                 where SAPRepairNo__c in :conMap.keySet()
            //                                       OR Name in :conMap.values()
            //                                 // SAPRepairNo__c in :sapRepairNoList
            //                                 //       OR Name in :sfdcRepairNoList  //20211108 lt add
            //                                       ];
            Map<String, Repair__c> sapRepairsMap = new Map<String, Repair__c>(); //外键检索
            Map<String, Repair__c> sfdcRepairsMap = new Map<String, Repair__c>();//20211108 lt add  //名字检索
            //20211109 lt start
            for(Repair__c rpair : [select Id, Name, SAPRepairNo__c, Delivered_Product__c
                                    , RepairOrderStatusName__c, RepairOrderStatusCode__c
                                    , CancellationReason__c, IncorrectDataComment__c
                                    , Repair_Rank__c, Repair_Ordered_Date__c
                                    , Invalid_check__c, Delete_Flag__c
                                    , Facility_Return_Receipt_Collection_Date__c, Receipt_received_date__c
                                    , Return_Without_Repair_IF__c, Return_Without_Repair_Reason__c
                                    , Repair_Quotation_Id__c, NFM105_MessageGroupNumber__c, Repair_List_Price_formula__c
                                    , ReturnType__c, InspectType__c
                                    , Maintenance_Contract__r.URF_Contract__c
                                    , Maintenance_Contract_Asset_Estimate__r.URF_Series__c // 20220321 ljh 限次合同异常数据
                                    ,Maintenance_Contract__c
                                    ,SerialNumber__c
                                    ,Agreed_Date__c 
                                  from Repair__c
                                  where SAPRepairNo__c in :sapRepairNoList
                                  OR Name in :sfdcRepairNoList]
                  ){
                    if(sapRepairNoList.contains(rpair.SAPRepairNo__c) == true){
                        sapRepairsMap.put(rpair.SAPRepairNo__c, rpair);
                    }
                    if(sfdcRepairNoList.contains(rpair.Name) == true){
                        sfdcRepairsMap.put(rpair.Name, rpair);
                    }
                    
            }
            //20211109 lt end

            // for (Repair__c rpair : sapRpairList) {
            //     //sapRepairsMap.put(rpair.SAPRepairNo__c, rpair);
            // }
            //sfdcのnameで検索
            //sfdc名字检索修理
            // List<Repair__c> sfdcRpairList = [select Id, Name, SAPRepairNo__c, Delivered_Product__c
            //                                 , RepairOrderStatusName__c, RepairOrderStatusCode__c
            //                                 , CancellationReason__c, IncorrectDataComment__c
            //                                 , Repair_Rank__c, Repair_Ordered_Date__c
            //                                 , Invalid_check__c, Delete_Flag__c
            //                                 , Facility_Return_Receipt_Collection_Date__c, Receipt_received_date__c
            //                                 , Return_Without_Repair_IF__c, Return_Without_Repair_Reason__c
            //                                 , Repair_Quotation_Id__c, NFM105_MessageGroupNumber__c, Repair_List_Price_formula__c
            //                                 , ReturnType__c, InspectType__c
            //                                 //add by rentx 2021-3-4 start
            //                                 ,Maintenance_Contract__r.URF_Contract__c
            //                                 ,Maintenance_Contract__c
            //                                 ,SerialNumber__c
            //                                 ,Agreed_Date__c 
            //                                 //add by rentx 2021-3-4 end
            //                                 from Repair__c
            //                                 where Name in :sfdcRepairNoList];
            // Map<String, Repair__c> sfdcRepairsMap = new Map<String, Repair__c>();
            // for (Repair__c rpair : sfdcRpairList) {
            //     sfdcRepairsMap.put(rpair.Name, rpair);
            // }
            // System.debug('165');

            // 报价单检索修理报价 
            // List<Repair_Quotation__c> quotationList = [select Id, Name, Repair_Rank__c, Repair__c, ListPrice__c
            //         , InspectionComment__c, InspectionResultFlag__c
            //         , InspectionFailureCause__c
            //         , LatestQuotationDate__c
            //         , FirstQuotationDate__c, TotalPrice__c
            //         , DiscountType__c, DiscountAmount__c, Repair_Discount_Date__c
            //         , CafeteriaFlag__c, MessageGroupNumber__c
            //         from Repair_Quotation__c
            //         where Name in :quotationNoList
            //                                           ];
            Map<String, Repair_Quotation__c> quotationMap = new Map<String, Repair_Quotation__c>();
            for (Repair_Quotation__c quotation : [select Id, Name, Repair_Rank__c, Repair__c, ListPrice__c
                                                    , InspectionComment__c, InspectionResultFlag__c
                                                    , InspectionFailureCause__c
                                                    , LatestQuotationDate__c
                                                    , FirstQuotationDate__c, TotalPrice__c
                                                    , DiscountType__c, DiscountAmount__c, Repair_Discount_Date__c
                                                    , CafeteriaFlag__c, MessageGroupNumber__c
                                                    from Repair_Quotation__c
                                                    where Name in :quotationNoList]) {
                quotationMap.put(quotation.Name, quotation);
            }
            // 更新対応配列をセット
            Map<String, Repair__c> rprUpdateMap = new Map<String, Repair__c>();                 // SAPRepairNo__c:Repair__c
            Map<String, Asset> astUpdateMap = new Map<String, Asset>();                         // SAPRepairNo__c:Asset   TODO goto 修理のなかAssetに反映しないフラグはいりますか？超古い修理対応？
            Map<Id, Repair_Quotation__c> rqUpdateMap = new Map<Id, Repair_Quotation__c>();      // keyも修理の Id にします。複数Quotation_agreement__cの場合後優先にする
            Map<String, List<Repair_Quotation_reason__c>> quotationReasonsMap = new Map<String, List<Repair_Quotation_reason__c>>();
            Map<Id, List<Repair_reason__c>> repairReasonsMap = new Map<Id, List<Repair_reason__c>>();
            for (GeneralData quoteInfo : generalDataList) {
                Repair__c rpr = null;
                if (quoteInfo.SFDCRepairNo == null || quoteInfo.SFDCRepairNo == '') {
                    rpr = sapRepairsMap.get(quoteInfo.SAPRepairNo);
                    if (rpr == null) {
                        // SAPRepairNo を受信したけど、SFDC側レコードがない
                        iflog.ErrorLog__c += 'SAPRepairNo[' + quoteInfo.SAPRepairNo + ']NotExist\n';
                        continue;
                    }
                } else {
                    System.debug('quoteInfo.SFDCRepairNo=' + quoteInfo.SFDCRepairNo);
                    rpr = sfdcRepairsMap.get(quoteInfo.SFDCRepairNo.toUpperCase());
                    if (rpr == null) {
                        // 修理受付番号 を受信したけど、SFDC側レコードがない
                        iflog.ErrorLog__c += 'SFDCRepairNo[' + quoteInfo.SFDCRepairNo + ']NotExist(' + quoteInfo.SAPRepairNo + ')';
                        rpr = sapRepairsMap.get(quoteInfo.SAPRepairNo);
                        if (rpr == null) {
                            iflog.ErrorLog__c += 'NotExist\n';
                        }
                        continue;
                    }
                }
                // 項目転送のセット
                rpr.SAPRepairNo__c = quoteInfo.SAPRepairNo;
                if (rprUpdateMap.get(rpr.SAPRepairNo__c) == null) {
                    logstr += quoteInfo.SAPRepairNo + ':' + quoteInfo.RepairOrderStatusCode + '(' + quoteInfo.SAPQuotationNo + ')';
                    // B95の場合、見積り と 同期取るが、その ステータスの更新は、基本順番を厳密守る必要がない、ステータス更新日をいつでも連携できるようにします。
                    //                    if (rpr.NFM105_MessageGroupNumber__c > rowData.MessageGroupNumber__c) {
                    //                        iflog.ErrorLog__c += rpr.NFM105_MessageGroupNumber__c + ' done ';
                    //                        continue;
                    //                    }
                    logstr += ' ';
                    System.debug('rpr1:' + rpr);
                    rprUpdateMap.put(rpr.SAPRepairNo__c, rpr);
                } else {
                    logstr += quoteInfo.SAPRepairNo + ':' + quoteInfo.RepairOrderStatusCode + '(' + quoteInfo.SAPQuotationNo + ') ';
                    rpr = rprUpdateMap.get(rpr.SAPRepairNo__c);
                }
                if (String.isBlank(rpr.NFM105_MessageGroupNumber__c) || Integer.valueOf(rpr.NFM105_MessageGroupNumber__c) <= Integer.valueOf(rowData.MessageGroupNumber__c) ) {
                   
                    // 各ステータスが専用項目に保存してますけど、ここ１つ項目に保存して、履歴を取れるようにします
                    rpr.RepairOrderStatusName__c  = quoteInfo.RepairOrderStatusName;
                    rpr.RepairOrderStatusCode__c  = quoteInfo.RepairOrderStatusCode;
                    //update by rentx 2021-05-13 start WLIG-C2GATJ 
                    // if (quoteInfo.RepairOrderStatusCode == 'A95' || quoteInfo.RepairOrderStatusCode == 'A96') {
                    // if (quoteInfo.RepairOrderStatusCode == 'A95' || quoteInfo.RepairOrderStatusCode == 'A96' || quoteInfo.RepairOrderStatusCode == 'L80') {
                    //update by rentx 20210602 start l80并且取消修理原因不为空时设置取消
                    if (quoteInfo.RepairOrderStatusCode == 'A95' || quoteInfo.RepairOrderStatusCode == 'A96' || (quoteInfo.RepairOrderStatusCode == 'L80' && String.isNotBlank(quoteInfo.CancellationReason))) {
                    //update by rentx 20210602 end l80并且取消修理原因不为空时设置取消
                    //update by rentx 2021-05-13 end WLIG-C2GATJ 
                        //RC已返还(IF)
                        rpr.Return_Without_Repair_IF__c = true;
                        if (rpr.Return_Without_Repair_IF__c == true) {
                            // TODO katsu いる？未修理返却申請 対応時対応するかも。
                            //未修理归还理由
                            rpr.Return_Without_Repair_Reason__c = (rpr.Return_Without_Repair_Reason__c == null || rpr.Return_Without_Repair_Reason__c == '') ? 'I/F理由、確認' : rpr.Return_Without_Repair_Reason__c;
                        }
                    }
                    if (quoteInfo.RepairOrderStatusCode == 'A99') {
                        rpr.Delete_Flag__c = true;
                        rpr.Return_Without_Repair_IF__c = false;
                    } else {
                        rpr.Delete_Flag__c = false;
                    }
                    if (quoteInfo.RepairOrderStatusCode == 'B95') {
                        rpr.Return_Without_Repair_IF__c = false;
                    }

                    if (rpr.CancellationReason__c != null && !String.isBlank(rpr.CancellationReason__c)) {
                        if (rpr.Repair_Start_Date__c == null) {
                            rpr.Return_Without_Repair_IF__c = true;
                        }
                    }
                }
                // B95の場合、Repair_Quotation__c も更新
                if (quoteInfo.RepairOrderStatusCode == 'B95') {
                    Repair_Quotation__c rq = quotationMap.get(quoteInfo.SAPQuotationNo);
                    if (rq == null) {
                        iflog.ErrorLog__c += 'SAPQuotationNo[' + quoteInfo.SAPQuotationNo + ']NotExist(B95:' + quoteInfo.SAPRepairNo + ')';
                        rpr = sapRepairsMap.get(quoteInfo.SAPRepairNo);
                        if (rpr == null) {
                            iflog.ErrorLog__c += 'NotExist\n';
                        }
                        continue;
                    }
                    rqUpdateMap.put(rpr.Id, rq);        // keyも修理の Id にします。複数Quotation_agreement__cの場合後優先にする
                    rpr.Repair_List_Price__c = rq.ListPrice__c;

                    if (String.isBlank(rpr.NFM105_MessageGroupNumber__c) || Integer.valueOf(rpr.NFM105_MessageGroupNumber__c) <= Integer.valueOf(rowData.MessageGroupNumber__c)) {
                        rpr.Repair_Quotation_Id__c = rq.Id;
                    }
                    if (String.isBlank(rq.MessageGroupNumber__c) || Integer.valueOf(rq.MessageGroupNumber__c) <= Integer.valueOf(rowData.MessageGroupNumber__c)) {
                        // rq.Quotation_agreement__c = true;
                        if (quoteInfo.InspectionResultInformation != null && quoteInfo.InspectionResultInformation.size() != 0) {
                            if (quoteInfo.InspectionResultInformation.size() > 1) {
                                iflog.ErrorLog__c += 'RepairQuotation[' + quoteInfo.SAPQuotationNo + ']SFDCRepairNo[' + quoteInfo.SFDCRepairNo + '] InspectionResultInformation count is ' + quoteInfo.InspectionResultInformation.size() + '\n';
                            }
                            rq.InspectionResultFlag__c    = quoteInfo.InspectionResultInformation[0].InspectionResultFlag == 'X' ? 'OK' : 'NG';
                            rq.InspectionComment__c       = quoteInfo.InspectionResultInformation[0].InspectionComment;
                            rq.InspectionFailureCause__c  = quoteInfo.InspectionResultInformation[0].FailureCause;
                            if (String.isBlank(rpr.NFM105_MessageGroupNumber__c) || Integer.valueOf( rpr.NFM105_MessageGroupNumber__c) <= Integer.valueOf(rowData.MessageGroupNumber__c)) {
                                rpr.InspectionResultFlag__c   = rq.InspectionResultFlag__c;
                                rpr.InspectionComment__c      = rq.InspectionComment__c;
                                rpr.InspectionFailureCause__c = rq.InspectionFailureCause__c;
                            }
                        }
                        // System.debug('quotationReasonsMap.put(rq.Name):' + rq.Name);
                        List<Repair_Quotation_reason__c> quotationReasons = new List<Repair_Quotation_reason__c>();
                        quotationReasonsMap.put(rq.Name, quotationReasons);
                        List<Repair_reason__c> repairReasons = new List<Repair_reason__c>();
                        repairReasonsMap.put(rpr.Id, repairReasons);            // 複数見積りの場合後優先にする
                        if (quoteInfo.FailureInformation != null && quoteInfo.FailureInformation.size() != 0) {
                            for (FailureInformation fi : quoteInfo.FailureInformation) {
                                Repair_Quotation_reason__c qrsn = new Repair_Quotation_reason__c();
                                quotationReasons.add(qrsn);
                                qrsn.LocationGroupName__c    = fi.LocationGroupName;
                                qrsn.LocationName__c         = fi.LocationName;
                                qrsn.PhenomenonName__c       = fi.PhenomenonName;
                                qrsn.CauseName__c            = fi.CauseName;
                                qrsn.DescriptionName__c      = fi.DescriptionName;
                                Repair_reason__c rrsn = new Repair_reason__c(Repair__c = rpr.Id);
                                repairReasons.add(rrsn);
                                rrsn.LocationGroupName__c    = fi.LocationGroupName;
                                rrsn.LocationName__c         = fi.LocationName;
                                rrsn.PhenomenonName__c       = fi.PhenomenonName;
                                rrsn.CauseName__c            = fi.CauseName;
                                rrsn.DescriptionName__c      = fi.DescriptionName;
                            }
                        }
                    }
                    if (String.isBlank(rq.MessageGroupNumber__c) || Integer.valueOf(rq.MessageGroupNumber__c) <= Integer.valueOf(rowData.MessageGroupNumber__c)) {
                        rq.MessageGroupNumber__c   = rowData.MessageGroupNumber__c;
                    }
                }

                // 各状態の更新者、NFM105_MessageGroupNumber__c を見ないこと
                Datetime statusUpdateDateTime = NFMUtil.parseStr2DateTime(quoteInfo.StatusUpdateDate, quoteInfo.StatusUpdateTime);
                if (statusUpdateDateTime == null) {
                    statusUpdateDateTime = NFMUtil.parseStr2DateTimeDate(rowData.TransmissionDateTime__c + '00');
                }
                    //                if (quoteInfo.RepairOrderStatusCode == 'A10') {
                    //                    // A10-分公司受理完成  ==> NFM103にて値を設定
                    //                    rpr.BranchOfficeRecievedDate__c = statusUpdateDateTime.date();
                    //                }
                if (quoteInfo.RepairOrderStatusCode == 'A20') {
                    // A20-RC受理完成
                    rpr.Repair_Ordered_Date__c = statusUpdateDateTime.date();
                    rpr.Repair_Ordered_DateTime__c = statusUpdateDateTime;
                    rpr.Repair_Ordered_Date_PersonName__c = quoteInfo.StatusUpdatePersonName;
                } else if (quoteInfo.RepairOrderStatusCode == 'A30') {
                    // A30-受理检查完成
                    rpr.Repair_Inspection_Date__c = statusUpdateDateTime.date();
                    rpr.Repair_Inspection_DateTime__c = statusUpdateDateTime;
                    rpr.ReRepairObject_result__c = quoteInfo.ReRepairObject == 'X' ? true : false;

                    // 2020/06/08 tqz add start 
                    if (String.isBlank(rpr.NFM105_MessageGroupNumber__c) || Integer.valueOf(rpr.NFM105_MessageGroupNumber__c) <= Integer.valueOf(rowData.MessageGroupNumber__c)) {
                        if (quoteInfo.InspectionResultInformation != null && quoteInfo.InspectionResultInformation.size() > 0) {
                            rpr.InspectionResultFlag__c    = quoteInfo.InspectionResultInformation[0].InspectionResultFlag == 'X' ? 'OK' : 'NG';
                            rpr.InspectionComment__c       = quoteInfo.InspectionResultInformation[0].InspectionComment;
                            rpr.InspectionFailureCause__c  = quoteInfo.InspectionResultInformation[0].FailureCause;
                        }
                    }
                    // 2020/06/08 tqz add end 
                  
                } else if (quoteInfo.RepairOrderStatusCode == 'A95' || quoteInfo.RepairOrderStatusCode == 'A96') {
                    // A95-取消修理受理　　因没有零件等原因，RC同事不受理修理 （RC为主）
                    // A96-取消修理　　　　因报价金额高等原因，销售本部申请未修理 （销售本部申请为主）
                    rpr.Invalid_check__c = true; //修理记录无效
                    rpr.repair_cancel_date__c = statusUpdateDateTime.date();
                    rpr.repair_cancel_dateTime__c = statusUpdateDateTime;
                    rpr.CancellationReason__c = quoteInfo.CancellationReason;
                } else if (quoteInfo.RepairOrderStatusCode == 'A99') {
                    // A99-修理单关闭　　　因申请内容和实际实物信息由差异，RC驳回此次申请的修理
                    rpr.SAP_not_accept_repair_result__c = statusUpdateDateTime.date();
                    rpr.IncorrectDataComment__c = quoteInfo.IncorrectDataComment;
                } else if (quoteInfo.RepairOrderStatusCode == 'B95') {
                    Asset ast = getAstUpdate(astUpdateMap, rpr);
                    ast.Agreed_Repair__c = rpr.Id;
                    // B95-报价同意确认
                    rpr.Agreed_Date__c = statusUpdateDateTime.date();
                    rpr.Agreed_DateTime__c = statusUpdateDateTime;
                    rpr.Agreed_Date2__c = statusUpdateDateTime.date();
                    // rpr.Agreed_Date__c <== TODO goto OFSにて設定するでしょうか？
                } else if (quoteInfo.RepairOrderStatusCode == 'B99') {
                    // B99-报价同意确认取消
                    // Agreed_Date2__c は クリアしないで、２回目再度同意されたら、同意日付は上書き。
                    // Agreed_Date__c は クリアする
                    Asset ast = getAstUpdate(astUpdateMap, rpr);
                    ast.Agreed_Repair__c = null;
                    rpr.Agreed_Date__c = null;
                    rpr.Agreed_Date_Cancel__c = statusUpdateDateTime.date();
                } else if (quoteInfo.RepairOrderStatusCode == 'X30') {
                    // X30-全部分配
                    rpr.part_arrangement_complete__c = statusUpdateDateTime.date();
                    rpr.part_arrangement_complete_DateTime__c = statusUpdateDateTime;
                } else if (quoteInfo.RepairOrderStatusCode == 'C50') {
                    // C50-开始修理
                    rpr.Repair_Start_Date__c = statusUpdateDateTime.date();
                    rpr.Repair_Start_DateTime__c = statusUpdateDateTime;
                    rpr.Planned_Repair_Completed_Date__c = NFMUtil.parseStr2Date(quoteInfo.PlannedRepairFinishDate);
                } else if (quoteInfo.RepairOrderStatusCode == 'C70') {
                    // C70-修理完成
                    rpr.Repair_Completed_Date__c = statusUpdateDateTime.date();
                    rpr.Repair_Completed_DateTime__c = statusUpdateDateTime;
                } else if (quoteInfo.RepairOrderStatusCode == 'C90') {
                    // C90-最终检查
                    rpr.Repair_Final_Inspection_Date__c = statusUpdateDateTime.date();
                    rpr.Repair_Final_Inspection_DateTime__c = statusUpdateDateTime;
                    Asset ast = getAstUpdate(astUpdateMap, rpr);
                    ast.LastSFDCRepairReturn_day__c = statusUpdateDateTime.date();
                    ast.LastSFDCRepairNo__c = rpr.Name;
                    if (System.Label.Large_Repair_Rank.indexOf(rpr.Repair_Rank__c + ',') >= 0) {
                        ast.LastSFDCRepairNo_rankA__c = rpr.Name;
                        ast.LastSFDCArankRepairReturn_day__c = statusUpdateDateTime.date();
                    }
                } else if (quoteInfo.RepairOrderStatusCode == 'L99') {
                    // L99-验收单签收复核通过
                    rpr.InspectType__c = quoteInfo.InspectType;
                    // 1-验收单
                    if (quoteInfo.InspectType == '1') {
                        // 一回目のみ設定
                        if (rpr.Receipt_received_date__c == null) {
                            rpr.Receipt_received_date__c = statusUpdateDateTime.date();
                        }
                        if (rpr.Facility_Return_Receipt_Collection_Date__c == null) {
                            rpr.Facility_Return_Receipt_Collection_Date__c = statusUpdateDateTime.date();
                        }
                    }
                    // 2-收款单
                    if (rpr.Facility_Return_Receipt_Collection_Date__c == null && quoteInfo.InspectType == '2') {
                        // 一回目のみ設定
                        rpr.Facility_Return_Receipt_Collection_Date__c = statusUpdateDateTime.date();
                    }
                } else if (quoteInfo.RepairOrderStatusCode == 'L60' || quoteInfo.RepairOrderStatusCode == 'L65' || quoteInfo.RepairOrderStatusCode == 'L80') {
                    // L60-SORC修理品出库
                    // L65-OGZ修理品出库
                    // L80-RC修理品出库
                    //WLIG-CC78MX 【委托】NFM105接口增加OTS运单号字段 thh 20220307 start
                    if(String.isNotBlank(quoteInfo.OTSRepairOrder)){
                        rpr.OTSRepairOrder__c = quoteInfo.OTSRepairOrder;
                    }
                    //WLIG-CC78MX 【委托】NFM105接口增加OTS运单号字段 thh 20220307 end
                    Asset ast = getAstUpdate(astUpdateMap, rpr);
                    if (rpr.Return_Without_Repair_IF__c == true) {
                        rpr.Return_Without_Repair_Date__c = statusUpdateDateTime.date();
                        ast.Return_Without_Repair__c = rpr.Id;
                    } else {
                        ast.Return_Without_Repair__c = null;
                    }
                    ast.Agreed_Repair__c = null;
                    if (quoteInfo.RepairOrderStatusCode == 'L80') {
                        //11.RC修理品返送日
                        rpr.Repair_Shipped_Date__c = statusUpdateDateTime.date();
                        rpr.Repair_Shipped_DateTime__c = statusUpdateDateTime;
                        //回返类别
                        rpr.ReturnType__c = quoteInfo.ReturnType;
                        if (quoteInfo.ReturnType == 'A20' || quoteInfo.ReturnType == 'B30') {
                            // A20-RC/FSE直返医院
                            // B30-SORC直返医院
                            //13.★修理品用户返送日
                            rpr.Repair_Returned_To_HP_Date__c = statusUpdateDateTime.date();
                        }

                        //add by rentx 20210602 start L80并且取消修理原因不为空时,才取消
                        if (String.isNotBlank(quoteInfo.CancellationReason)) {
                        //add by rentx 20210602 end L80并且取消修理原因不为空时,才取消
                            //add by rentx 2021-05-13 start WLIG-C2GATJ 
                            rpr.Invalid_check__c = true; //修理记录无效
                            rpr.repair_cancel_date__c = statusUpdateDateTime.date();
                            rpr.CancellationReason__c = quoteInfo.CancellationReason;
                            //add by rentx 2021-05-13 end WLIG-C2GATJ   
                        }
                    }
                }
                    //                else if (quoteInfo.RepairOrderStatusCode == 'D10') {
                    //                    // D10-返品
                    //                    rpr.Return_Without_Repair_Date__c = statusUpdateDateTime.date();
                    //                    Asset ast = getAstUpdate(astUpdateMap, rpr);
                    //                    ast.Return_Without_Repair__c = rpr.Id;
                    //                }
                else if (quoteInfo.RepairOrderStatusCode == 'E10') {
                    // E10-修理单完成
                    rpr.RepairOrder_Complete_Day__c = statusUpdateDateTime.date();
                }
                //WLIG-C8TACX LY 20211206 Start
                else if (quoteInfo.RepairOrderStatusCode == 'L20') {
                    // L20-RC转SORC日
                    rpr.RcSorcDate__c = statusUpdateDateTime.date();
                    rpr.RcSorcDateTime__c = statusUpdateDateTime;
                }else if (quoteInfo.RepairOrderStatusCode == 'L25') {
                    // L25-RC转OGZ日
                    rpr.RcOgzDate__c = statusUpdateDateTime.date();
                }else if (quoteInfo.RepairOrderStatusCode == 'L30') {
                    // L30-SORC受理日
                    rpr.SorcAcceptDate__c = statusUpdateDateTime.date();
                    rpr.SorcAcceptDateTime__c = statusUpdateDateTime;
                }else if (quoteInfo.RepairOrderStatusCode == 'L40') {
                    // L40-SORC转OGZ日
                    rpr.SorcOgzDate__c = statusUpdateDateTime.date();
                    rpr.SorcOgzDateTime__c = statusUpdateDateTime;
                }else if (quoteInfo.RepairOrderStatusCode == 'L45') {
                    // L45-OGZ受理日
                    rpr.OgzAcceptDate__c = statusUpdateDateTime.date();
                    rpr.OgzAcceptDateTime__c = statusUpdateDateTime;
                }
                //WLIG-C8TACX LY 20211206 End
                if (String.isBlank(rpr.NFM105_MessageGroupNumber__c) || Integer.valueOf(rpr.NFM105_MessageGroupNumber__c) <= Integer.valueOf(rowData.MessageGroupNumber__c)) {
                    rpr.NFM105_MessageGroupNumber__c = rowData.MessageGroupNumber__c;
                }
            }

            // その他のQuoteationのQuotation_agreement__cをfalseにする
            //System.debug(Logginglevel.ERROR, 'rqUpdateMap.keySet=' + rqUpdateMap.keySet());
            List<Repair_Quotation__c> rqList = [Select Id from Repair_Quotation__c where Quotation_agreement__c = true and Repair__c IN :rqUpdateMap.keySet() and Id Not IN :rqUpdateMap.values()];
            for (Repair_Quotation__c rqfalse : rqList) {
                rqfalse.Quotation_agreement__c = false;
            }
            System.debug('rqUpdateMap1:' + rqUpdateMap);
            rqList.addAll(rqUpdateMap.values());
            if (rqList.size() > 0) {
                // TODO update false;
                upsert rqList;
            }
            if (rqUpdateMap.size() > 0) {
                Map<String, Repair_Quotation__c> rqNameMap = new Map<String, Repair_Quotation__c>();
                for (Repair_Quotation__c rq : rqUpdateMap.values()) {
                    rqNameMap.put(rq.Name, rq);
                    System.debug('rq.Name=' + rq.Name + ', rq.Repair__c=' + rq.Repair__c);
                }
                for (Repair_quotation_reason__c qrsn : [Select ActivityDescription__c, Repair_quotation__r.Name, Repair_quotation__r.Repair__c from Repair_quotation_reason__c
                                                        where Repair_quotation__r.Name IN: quotationReasonsMap.keySet() and ActivityDescription__c != null]
                    ) {
                    List<Repair_reason__c> repairReasons = repairReasonsMap.get(qrsn.Repair_quotation__r.Repair__c);
                    if (repairReasons == null) {
                        repairReasons = new List<Repair_reason__c>();
                        repairReasonsMap.put(qrsn.Repair_quotation__r.Repair__c, repairReasons);
                    }
                    repairReasons.add(new Repair_reason__c(Repair__c = qrsn.Repair_quotation__r.Repair__c,
                                                           ActivityDescription__c = qrsn.ActivityDescription__c
                                                          ));
                }
                // CHAN-BAF2VC 20190327 LHJ Start
                
                //NFM104WebService.deleteInsertReasons(rqNameMap, quotationReasonsMap, repairReasonsMap);
                NFM104Rest.deleteInsertReasons(rqNameMap, quotationReasonsMap, repairReasonsMap);
                // CHAN-BAF2VC 20190327 LHJ End
            }
            list<Repair__c> rprList = rprUpdateMap.values();
            if (rprList.size() > 0 ) {
                update rprList;
            }
            if (astUpdateMap.size() > 0 ) {
                update astUpdateMap.values();
            }



            //add by rentx 2021-3-4 start
            /*
            1.查询修理对应的合同是否为限次合同
            2.根据限次合同获取维修合同保有设备集合 拿到修理对应的限次系列  <修理id,限次系列>  <限次系列,list<维修合同保有设备>>
            3.根据限次合同查到该合同下的所有修理 
            */
            logstr += '\n rprList::'+rprList;
            // 20220321 ljh 限次合同异常数据 update start
            /*if (rprList.size() > 0) {
                //需要知道当前修理对应的设备的系列号
                Map<String,String> reurfMap = new Map<String,String>();
                //限次合同Id集合
                List<Id> contractIds = new List<Id>();
                //维修合同保有设备集合
                List<Maintenance_Contract_Asset__c> maassList = new List<Maintenance_Contract_Asset__c>();
                //限次系列 维修合同保有设备map
                Map<String,List<Maintenance_Contract_Asset__c>> urfAssMap = new Map<String,List<Maintenance_Contract_Asset__c>>();
                //限次系列 保有设备机身号
                Map<String,List<String>> urfAssNumMap = new Map<String,List<String>>();

                //限次合同下的修理集合
                List<Repair__c> reList = new List<Repair__c>();

                //查询当前修理对应的维修合同是否为限次合同
                for (Repair__c rep : rprList) {
                    if (rep.Maintenance_Contract__c != null && rep.Maintenance_Contract__r.URF_Contract__c == true && (rep.Repair_Rank__c == 'A' || rep.Repair_Rank__c == 'B' || rep.Repair_Rank__c == 'C') && rep.Agreed_Date__c != null) {
                        contractIds.add(rep.Maintenance_Contract__c);
                        reurfMap.put(rep.Id, rep.SerialNumber__c);
                    }
                }
                //
                if (contractIds.size() > 0) {
                    //查询当前限次合同下的所有维修合同保有设备
                    maassList = [select id,URF_Series_F__c,Series_RepairCount_F__c,Series_MaxRepairCount_F__c,Asset__r.SerialNumber,Asset__c,Maintenance_Contract_Asset_Estimate__c from Maintenance_Contract_Asset__c where Maintenance_Contract__c in :contractIds];
                    for (Maintenance_Contract_Asset__c maAss : maassList) {

                        //key 为修理id  value 为限次系列
                        for (String str : reurfMap.keySet()) {
                            if (reurfMap.get(str) == maAss.Asset__r.SerialNumber) {
                                reurfMap.put(str, maAss.URF_Series_F__c);
                            }
                        }

                        //key 为限次系列 value 为维修合同保有设备集合
                        if (!urfAssMap.containsKey(maAss.URF_Series_F__c)) {
                            urfAssMap.put(maAss.URF_Series_F__c, new List<Maintenance_Contract_Asset__c>());
                        }
                        urfAssMap.get(maAss.URF_Series_F__c).add(maAss);
                    }

                    //
                    Map<String,List<Repair__c>> urfRepMap = new Map<String,List<Repair__c>>();
                    //查询维修合同下的所有修理

                    reList = [select id,Repair_Rank__c,Agreed_Date__c,Maintenance_Contract__c,SerialNumber__c,Usage_Ratio_Price_Service__c from Repair__c where (Repair_Rank__c = 'A' OR Repair_Rank__c = 'B' OR Repair_Rank__c = 'C') and Agreed_Date__c <> null and Maintenance_Contract__c in :contractIds ];

                    //
                    Map<String,List<Repair__c>> assNoRepMap = new Map<String,List<Repair__c>>();

                    for (Repair__c rep : reList) {
                        for (String urf : urfAssMap.keySet()) {
                            List<Maintenance_Contract_Asset__c> mcaclist = urfAssMap.get(urf);
                            for (Maintenance_Contract_Asset__c mcac : mcaclist) {
                                if (mcac.Asset__r.SerialNumber == rep.SerialNumber__c) {
                                    if (!urfRepMap.containsKey(mcac.URF_Series_F__c)) {
                                        urfRepMap.put(mcac.URF_Series_F__c, new List<Repair__c>());
                                    }
                                    urfRepMap.get(mcac.URF_Series_F__c).add(rep);

                                    if (!assNoRepMap.containsKey(mcac.Asset__r.SerialNumber)) {
                                        assNoRepMap.put(mcac.Asset__r.SerialNumber, new List<Repair__c>());
                                    }
                                    assNoRepMap.get(mcac.Asset__r.SerialNumber).add(rep);
                                }
                            }
                        }
                    }

                    //
                    List<Maintenance_Contract_Asset_Estimate__c> updateList = new List<Maintenance_Contract_Asset_Estimate__c>();
                    // for (String urfStr : urfRepMap.keySet()) {
                    //去重
                    Set<String> urfstrs = new Set<String>();
                    urfstrs.addAll(reurfMap.values());
                    for (String urfStr : urfstrs) {
                        if (urfAssMap.containsKey(urfStr)) {
                            //获取同一系列的 维修合同/保有设备
                           List<Maintenance_Contract_Asset__c> macoAssList = urfAssMap.get(urfStr);
                           //循环该系列的设备
                           for (Maintenance_Contract_Asset__c conass : macoAssList) {
                            //判断已维修次数是否发生改变
                               if (conass.Series_RepairCount_F__c != urfRepMap.get(urfStr).size()) {
                                //如果发生改变.设置新的值;
                                   Maintenance_Contract_Asset_Estimate__c mcae = new Maintenance_Contract_Asset_Estimate__c();
                                   mcae.Id = conass.Maintenance_Contract_Asset_Estimate__c;
                                   mcae.Series_RepairCount__c = urfRepMap.get(urfStr).size();
                                   if (assNoRepMap.containsKey(conass.Asset__r.SerialNumber)) {
                                        mcae.Asset_RepairCount__c = assNoRepMap.get(conass.Asset__r.SerialNumber).size();   

                                        // LJPH-BYS895 add by rentx 2021-04-28 start  
                                        //设置设备修理金额
                                        mcae.Equipmentrepairamount__c = 0;
                                        for (Repair__c rep: assNoRepMap.get(conass.Asset__r.SerialNumber)) {
                                            mcae.Equipmentrepairamount__c += rep.Usage_Ratio_Price_Service__c;
                                        }
                                        // LJPH-BYS895 add by rentx 2021-04-28 end
                                   }

                                    // LJPH-BYS895 add by rentx 2021-04-28 start
                                    //设置系列修理金额
                                    mcae.Seriesrepairamount__c = 0;
                                    for (Repair__c rep : urfRepMap.get(urfStr)) {
                                         mcae.Seriesrepairamount__c += rep.Usage_Ratio_Price_Service__c;
                                    }
                                    // LJPH-BYS895 add by rentx 2021-04-28 end

                                   updateList.add(mcae);
                               }
                           }
                        }
                    }
                    if (updateList.size() > 0) {
                        update updateList;
                    }
                }

            }*/
            //add by rentx 2021-3-4 end
            if (rprList.size() > 0) {
                // 限次合同 map
                Map<String,Map<String,List<Repair__c>>> contractMap = new Map<String,Map<String,List<Repair__c>>>();
                //维修合同保有设备集合
                List<Maintenance_Contract_Asset__c> maassList = new List<Maintenance_Contract_Asset__c>();
                //查询当前修理对应的维修合同是否为限次合同 && 大修
                for (Repair__c rep : rprList) {
                    if (rep.Maintenance_Contract__c != null && rep.Maintenance_Contract__r.URF_Contract__c == true && (rep.Repair_Rank__c == 'A' || rep.Repair_Rank__c == 'B' || rep.Repair_Rank__c == 'C') && rep.Agreed_Date__c != null) {
                        List<Repair__c> tempRepL;
                        Map<String,List<Repair__c>> tempRepM;
                        if(contractMap.containsKey(rep.Maintenance_Contract__c)){
                            // 保有设备 和 限次系列
                            tempRepM = contractMap.get(rep.Maintenance_Contract__c);
                            if(tempRepM.containsKey(rep.Delivered_Product__c)){
                                tempRepM.get(rep.Delivered_Product__c).add(rep);
                            }
                            if(tempRepM.containsKey(rep.Maintenance_Contract_Asset_Estimate__r.URF_Series__c)){
                                tempRepM.get(rep.Maintenance_Contract_Asset_Estimate__r.URF_Series__c).add(rep);
                            }
                        }else{
                            tempRepM = new Map<String,List<Repair__c>>();
                            tempRepL.add(rep); 
                            tempRepM.put(rep.Delivered_Product__c,tempRepL);
                            tempRepM.put(rep.Maintenance_Contract_Asset_Estimate__r.URF_Series__c,tempRepL);
                        }                       
                        contractMap.put(rep.Maintenance_Contract__c,tempRepM);  
                    }
                }
                if (contractMap.size() > 0) {
                    //查询当前限次合同下的所有维修合同保有设备
                    maassList = [SELECT id , Series_RepairCount_F__c
                                , Maintenance_Contract_Asset_Estimate__c
                                , Asset__c
                                , Maintenance_Contract__c
                                , URF_Series_F__c
                                FROM Maintenance_Contract_Asset__c 
                                WHERE Maintenance_Contract__c in :contractMap.keySet()];
                    List<Maintenance_Contract_Asset_Estimate__c> updateList = new List<Maintenance_Contract_Asset_Estimate__c>();
                    for (Maintenance_Contract_Asset__c maAss : maassList) {
                        // 判断已维修次数是否发生改变
                        if (contractMap.get(maAss.Maintenance_Contract__c) != null
                            && contractMap.get(maAss.Maintenance_Contract__c).size() != 0
                            && contractMap.get(maAss.Maintenance_Contract__c).containsKey(maAss.URF_Series_F__c)
                            && maAss.Series_RepairCount_F__c != contractMap.get(maAss.Maintenance_Contract__c).get(maAss.URF_Series_F__c).size()) {
                            //如果发生改变.设置新的值;
                            Maintenance_Contract_Asset_Estimate__c mcae = new Maintenance_Contract_Asset_Estimate__c();
                            mcae.Id = maAss.Maintenance_Contract_Asset_Estimate__c;
                            mcae.Series_RepairCount__c = contractMap.get(maAss.Maintenance_Contract__c).get(maAss.URF_Series_F__c).size();
                            //设置系列修理金额
                            mcae.Seriesrepairamount__c = 0;
                            for (Repair__c rep : contractMap.get(maAss.Maintenance_Contract__c).get(maAss.URF_Series_F__c)) {
                                 mcae.Seriesrepairamount__c += rep.Usage_Ratio_Price_Service__c;
                            }
                            mcae.Asset_RepairCount__c = 0;
                            mcae.Equipmentrepairamount__c = 0;
                            if (contractMap.get(maAss.Maintenance_Contract__c).containsKey(maAss.Asset__c)) {
                                mcae.Asset_RepairCount__c = contractMap.get(maAss.Maintenance_Contract__c).get(maAss.Asset__c).size();    
                                //设置设备修理金额
                                for (Repair__c rep: contractMap.get(maAss.Maintenance_Contract__c).get(maAss.Asset__c)) {
                                    mcae.Equipmentrepairamount__c += rep.Usage_Ratio_Price_Service__c;
                                }
                            }
                            updateList.add(mcae);
                        }
                    }
                    if (updateList.size() > 0) {
                        system.debug('zheli:'+updateList);
                        update updateList;
                    }
                }
            }
            // 20220321 ljh 限次合同异常数据 update end
            //gzozw-add
            logstr += '\nend';
            rowData.retry_cnt__c = 0;
        } catch (Exception ex) {
            // エラーが発生した場合
            Database.rollback(sp);
            System.debug(Logginglevel.ERROR, 'NFM105_' + rowData.MessageGroupNumber__c + ':' + ex.getMessage());
            System.debug(Logginglevel.ERROR, 'NFM105_' + rowData.MessageGroupNumber__c + ':' + ex.getStackTraceString());
            logstr += '\n' + ex.getMessage();
            iflog.ErrorLog__c = ex.getMessage() + '\n' + ex.getStackTraceString() + '\n' + iflog.ErrorLog__c;
            if (rowData.retry_cnt__c == null) rowData.retry_cnt__c = 0;
            if (rowData.retry_cnt__c < batch_retry_max_cnt) {
                rowData.retry_cnt__c++;
                LogAutoSendSchedule.assignOneMinute();
            }
            if (rowData.retry_cnt__c >= batch_retry_max_cnt) {
                rowData.ErrorLog__c = ex.getMessage() + '\n' + ex.getStackTraceString() + '\n' + rowData.ErrorLog__c + '错误次数已经超过自动收信设定的最大次数，请手动收信';
            }
        }
        update rowData;
        iflog.Log__c = logstr;
        if (rowData.retry_cnt__c == 0) {
            iflog.retry_cnt__c = 0;
        }
        if (iflog.Log__c.length() > 131072) {
            iflog.Log__c = iflog.Log__c.subString(0, 131065) + ' ...';
        }
        if (iflog.ErrorLog__c.length() > 32768) {
            iflog.ErrorLog__c = iflog.ErrorLog__c.subString(0, 32760) + ' ...';
        }
        update iflog;
    }

    private static Asset getAstUpdate(Map<String, Asset> astUpdateMap, Repair__c rpr) {
        Asset ast = astUpdateMap.get(rpr.Delivered_Product__c);
        if (ast == null) {
            ast = new Asset(Id = rpr.Delivered_Product__c);
            astUpdateMap.put(rpr.Delivered_Product__c, ast);
        }
        return ast;
    }

}