@RestResource(urlMapping = '/NFM010/*')
global with sharing class NFM010Rest  {

    global class AchievementsRest {
        public Achievements Achievements;
    }
    // Integer batchsize = 200;  考量する必要がないと思います。
    global class Achievements {
        public NFMUtil.Monitoring Monitoring;
        public Achievement[] Achievement;
    }
    global class Achievement {
        public String SoNo;
        public String QuotationCode;
        public String ReturnFlag;
        public String OverviewStatus;
        public String ContractNO;
        public String ContractReceivedDate;
        public String FirstApproveDate;
        public String SecondApproveDate;
        public String SoLatestDeliveryDate;
        public String DeliveryDate;
        public String InstallDate;
        // 20200519 LZHU-BNV6QN Start
        public String CollectionDate;
        // 20200519 LZHU-BNV6QN End
        public String Currency_x;
        public Decimal ContractAmount;
        public Decimal PaymentAmount;
        public String PaymentRate;
        public String DeliveryStatus;
        public String AssignmentStatus;
        public String PaymentStatus;
        public String InstallStatus;
        public String AuthorizationNo;
        public String ContractApplicationNo;
        public String PaymentTerms;
        public Decimal TimeLimit;
        public Decimal SalesChannel;
        // CHAN-BHFAH4 Start
        public Decimal ContractAmountNoGurantee;
        // CHAN-BHFAH4 End
        //注残类型 
        public String OrderType;
    }

    @HttpPost
    global static void execute() {

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

        if (ges == null ) {
            return;
        }

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

        BatchIF_Log__c rowData = NFMUtil.saveRowData(Monitoring, 'NFM010', ges.Achievements.Achievement);
        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, 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 = 'NFM010';
        iflog.MessageGroupNumber__c = rowData.MessageGroupNumber__c;
        iflog.Log__c = logstr;
        iflog.ErrorLog__c = '';
        insert iflog;
        String rowDataStr = NFMUtil.getRowDataStr(rowData);
        List<Achievement> achievementList = (List<Achievement>) JSON.deserialize(rowDataStr, List<Achievement>.class);
        if (achievementList == null || achievementList.size() == 0) {
            return;
        }

        // BatchIF転送表 から、コード変換のMapを作成
        Map<String, String> transferMap = new Map<String, String>();
        List<BatchIF_Transfer__c> transferList = [select Table__c,
                                  Column__c,
                                  External_value__c,
                                  Internal_value__c
                                  from BatchIF_Transfer__c
                                  where Dropped_Flag__c = false
                                          and Table__c = 'Statu_Achievements__c'];
        for (BatchIF_Transfer__c t : transferList) {
            transferMap.put(t.Column__c + t.External_value__c, t.Internal_value__c);
        }

        Savepoint sp = Database.setSavepoint();
        try {
            // 更新対応配列とMapなどをセット
            List<String> oppNoList = new List<String>();
            List<String> statu_AchievementsList = new List<String>();
            for (Achievement Achievement : achievementList) {
                if (Achievement.SoNo == null || Achievement.SoNo == '' ||
                        Achievement.QuotationCode == null || Achievement.QuotationCode == '' ||
                        Achievement.TimeLimit == null
                   ) {
                    // 必須項目がない場合、処理と飛ばす
                    continue;
                }
                oppNoList.add(Achievement.QuotationCode);
                statu_AchievementsList.add(Achievement.QuotationCode + ':' + Achievement.SoNo);
            }
            List<Opportunity> oppList = [select Id, Opportunity_No__c, Min_FirstApproveDate__c,
                                         Note_Residual_Result__c, IsImport__c
                                         from Opportunity
                                         where Opportunity_No__c in :oppNoList];
            Map<String, Opportunity> oppsMap = new Map<String, Opportunity>();
            for (Opportunity opp : oppList) {
                oppsMap.put(opp.Opportunity_No__c, opp);
            }

            // 更新対応配列をセット
            List<Statu_Achievements__c> staList = new List<Statu_Achievements__c>();
            Map<String, Statu_Achievements__c> staUpdateMap = new Map<String, Statu_Achievements__c>();

            staList = [select Id, Name, Opportunity__c,
                       Statu_Achievements_Ext__c,
                       ReturnFlag__c,
                       OverviewStatus__c,
                       ContractNO__c,
                       ContractReceivedDate__c,
                       FirstApproveDate__c,
                       LastApproveDate__c,
                       SoLatestDeliveryDate__c,
                       DeliveryDate__c,
                       InstallDate__c,
                       Collection_Day_Invoice__c,
                       CurrencyIsoCode,
                       ContractAmount__c,
                       ContractAmountNoGurantee__c, 
                       PaymentAmount__c,
                       Paid_Amount_Rate__c,
                       X30_Deposit_Day__c,
                       Deposit_In_Full_Day__c,
                       PaymentRate__c,
                       DeliveryStatus__c,
                       AssignmentStatus__c,
                       PaymentStatus__c,
                       InstallStatus__c,
                       AuthorizationNo__c,
                       ContractApplicationNo__c,
                       PaymentTerms__c,
                       UnshippedAmount__c,
                       End_User_price__c
                       from Statu_Achievements__c
                       where Statu_Achievements_Ext__c in :statu_AchievementsList];

            for (Statu_Achievements__c statu_Achievements : staList) {
                staUpdateMap.put(statu_Achievements.Statu_Achievements_Ext__c, statu_Achievements);
            }
            Map<Id, Opportunity> oppUpdateMap = new Map<Id, Opportunity>();
            for (Achievement Achievement : achievementList) {
                if (Achievement.SoNo == null || Achievement.SoNo == '') {
                    // 必須項目がない場合、処理と飛ばす
                    iflog.ErrorLog__c += 'SoNo is required\n';
                    continue;
                }
                if (Achievement.QuotationCode == null || Achievement.QuotationCode == '') {
                    // 必須項目がない場合、処理と飛ばす
                    iflog.ErrorLog__c += 'QuotationCode is required\n';
                    continue;
                }
                if (Achievement.TimeLimit == null) {
                    // 必須項目がない場合、処理と飛ばす
                    iflog.ErrorLog__c += 'TimeLimit is required\n';
                    continue;
                }
                //                Boolean returnFlag = (Achievement.ReturnFlag == null || Achievement.ReturnFlag == '') ? false : true;
                //                Date lastApproveDate = NFMUtil.parseStr2Date(Achievement.SecondApproveDate, true);
                //                if (returnFlag && lastApproveDate == null) {
                //                    iflog.ErrorLog__c += Achievement.SoNo + ' is (X), please set LastApproveDate\n';
                //                    continue;
                //                }
                Opportunity opp = oppsMap.get(Achievement.QuotationCode);
                if (opp == null) {
                    // 更新対象商談がない場合
                    iflog.ErrorLog__c += '[' + Achievement.SoNo + ']Opportunity[' + Achievement.QuotationCode + ']NotExist\n';
                    continue;
                }
                // 項目転送のセット
                Statu_Achievements__c sta = new Statu_Achievements__c();
                sta.Statu_Achievements_Ext__c = Achievement.QuotationCode + ':' + Achievement.SoNo;
                if (staUpdateMap.get(sta.Statu_Achievements_Ext__c) == null) {
                    staList.add(sta);
                    staUpdateMap.put(sta.Statu_Achievements_Ext__c, sta);
                    sta.Opportunity__c            = opp.Id;
                    logstr += Achievement.QuotationCode + ':' + Achievement.SoNo + ' ';
                } else {
                    sta = staUpdateMap.get(sta.Statu_Achievements_Ext__c);
                }
                //接收无偿出库订单类型  精琢技术 thh 2021-10-14 start
                if(Achievement.OrderType.equals('ZM16')){
                    sta.orderType__c = Achievement.OrderType;
                //接收无偿出库订单类型  精琢技术 thh 2021-10-14 end   
                // CHAN-BCPCA3 判断是否ZM 订单以及赋值具体订单类型 start
                } else if (!string.isblank(Achievement.SoNo)
                        && Achievement.SoNo.Trim().replaceAll('0', '').StartsWith('6')) {
                    if (!string.isblank(Achievement.paymentStatus)
                        && Achievement.paymentStatus.Trim().contains('退款完成')) {
                        sta.orderType__c = 'ZM17';
                    } else {
                        sta.orderType__c = 'ZM18';
                    }
                }
                // CHAN-BCPCA3 判断是否ZM 订单以及赋值具体订单类型 end
                sta.Name                      = Achievement.SoNo;
                sta.ReturnFlag__c             = (Achievement.ReturnFlag == null || Achievement.ReturnFlag == '') ? false : true;
                sta.OverviewStatus__c         = Achievement.OverviewStatus;
                sta.ContractNO__c             = Achievement.ContractNO;
                sta.ContractReceivedDate__c   = NFMUtil.parseStr2Date(Achievement.ContractReceivedDate, true);
                sta.FirstApproveDate__c       = NFMUtil.parseStr2Date(Achievement.FirstApproveDate, true);
                sta.LastApproveDate__c        = NFMUtil.parseStr2Date(Achievement.SecondApproveDate, true);
                sta.SoLatestDeliveryDate__c   = NFMUtil.parseStr2Date(Achievement.SoLatestDeliveryDate, true);
                sta.DeliveryDate__c           = NFMUtil.parseStr2Date(Achievement.DeliveryDate, true);
                sta.InstallDate__c            = NFMUtil.parseStr2Date(Achievement.InstallDate, true);
                // 20200519  ZHU-BNV6QN Start
                //sta.Collection_Day_Invoice__c = sta.InstallDate__c == null ? null : System.today();
                sta.Collection_Day_Invoice__c = NFMUtil.parseStr2Date(Achievement.CollectionDate, true);
                // 20200519  LZHU-BNV6QN End
                sta.CurrencyIsoCode           = Achievement.Currency_x == 'RMB' ? 'CNY' : Achievement.Currency_x;
                sta.ContractAmount__c         = Achievement.ContractAmount;
                // CHAN-BHFAH4 Start
                sta.ContractAmountNoGurantee__c = Achievement.ContractAmountNoGurantee;
                // CHAN-BHFAH4 End
                sta.PaymentAmount__c          = Achievement.PaymentAmount;
                System.debug(Logginglevel.ERROR, 'Paid_Amount_Rate +++++' + sta.Paid_Amount_Rate__c);
                if (String.isNotEmpty(Achievement.PaymentRate)) {
                    String payment_Rate = Achievement.PaymentRate.substring(0, Achievement.PaymentRate.lastIndexOf(','));
                    String payment_Rate_Date = Achievement.PaymentRate.substring(Achievement.PaymentRate.lastIndexOf(',') + 1);
                    System.debug(Logginglevel.ERROR, 'Paid_Amount_Rate _____' + Decimal.valueOf(payment_Rate.subString(0, payment_Rate.length() - 1)));
                    if ((sta.Paid_Amount_Rate__c == null || sta.Paid_Amount_Rate__c < 30) && Decimal.valueOf(payment_Rate.subString(0, payment_Rate.length() - 1)) >= 30.00) {
                        sta.X30_Deposit_Day__c    = NFMUtil.parseStr2Date(payment_Rate_Date, true);
                    }
                    if (Decimal.valueOf(payment_Rate.subString(0, payment_Rate.length() - 1)) == 100.00) {
                        sta.Deposit_In_Full_Day__c    = NFMUtil.parseStr2Date(payment_Rate_Date, true);
                    }
                    sta.PaymentRate__c            = Achievement.PaymentRate.substring(0, Achievement.PaymentRate.lastIndexOf(','));
                }
                sta.DeliveryStatus__c         = Achievement.DeliveryStatus;
                sta.AssignmentStatus__c       = Achievement.AssignmentStatus;
                sta.PaymentStatus__c          = Achievement.PaymentStatus;
                sta.InstallStatus__c          = Achievement.InstallStatus;
                sta.AuthorizationNo__c        = Achievement.AuthorizationNo;
                sta.ContractApplicationNo__c  = Achievement.ContractApplicationNo;
                sta.PaymentTerms__c           = Achievement.PaymentTerms;
                sta.UnshippedAmount__c        = Achievement.TimeLimit;         // NFMUtil.parseStr2Date(Achievement.TimeLimit, true) #1189の対応、UnshippedAmount__c にセット
                sta.End_User_price__c         = Achievement.SalesChannel;      // NFMUtil.getMapValue(transferMap, 'SalesChannel__c', Achievement.SalesChannel, iflog);

                // 引合の更新、最初の注残
                if (opp.Note_Residual_Result__c == '4'       // SAP Winの後、ただし有効注残がない
                        && opp.IsImport__c == False          // 是否从SFA转移的已结束询价 のデータでなはい
                        && opp.Min_FirstApproveDate__c == null
                   ) {
                    // 有効な注残かどうかの判断 Valid_Statu_Achievements__c
                    if ((sta.OverviewStatus__c == '冻结' || sta.OverviewStatus__c == '无效合同' || sta.ReturnFlag__c) == false) {
                        opp.Contract_Once_Recognize_Day__c = NFMUtil.parseStr2Date(Achievement.FirstApproveDate, true);
                        oppUpdateMap.put(opp.Id, opp);
                    }
                }
            }
            if (staList.size() > 0) {
                StaticParameter.EscapeNFM001Trigger = true;
                StaticParameter.EscapeNFM001AgencyContractTrigger = true;
                StaticParameter.EscapeNFM007Trigger = true;
                StaticParameter.EscapeOpportunityBefUpdTrigger = true;
                upsert staList Statu_Achievements_Ext__c;
                if (oppUpdateMap.size() > 0) {
                    update oppUpdateMap.values();
                }
            }
            logstr += '\nend';
            rowData.retry_cnt__c = 0;
        } catch (Exception ex) {
            // エラーが発生した場合
            Database.rollback(sp);
            System.debug(Logginglevel.ERROR, 'NFM010_' + rowData.MessageGroupNumber__c + ':' + ex.getMessage());
            System.debug(Logginglevel.ERROR, 'NFM010_' + 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 (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;
    }
}