// RowDataを残す、batch execute にします
// 20170209の変更記録
    /*
        物料号后面添加了供应商代码，用逗号隔开，对应相关取值，验证工作
    */
global class NFM004WebService implements Database.Batchable<sObject> {
    private final Id rowData_Id;
    private final Integer startIndex;
    private final Integer dataLength;
    private final Integer executeSize = 2000;

    // Integer batchsize = 200;  考量する必要がないと思います。
    global class PurchasePrices {
        webservice NFMUtil.Monitoring Monitoring;
        webservice NFM004WebService.PurchasePrice[] PurchasePrice;
    }
    global class PurchasePrice {
        webservice String  PriceType;
        webservice String  SuppliersItemCode;
        webservice Decimal PurchasePrice;
        webservice String  Currency_x;
        webservice String  ReportedDateTime;                       // 受信しない
        webservice String  EffectiveDateFrom;
        webservice String  EffectiveDateTo;
        webservice String  PurposeOfAdvice;
    }
    
    // 非同期を見せかけ、常にreturn void
    webservice static void NFM004(NFM004WebService.PurchasePrices PurchasePrices) {
        if (PurchasePrices == null) {
            return;
        }
        NFMUtil.Monitoring Monitoring = PurchasePrices.Monitoring;
        if (Monitoring == null) {
            return;
        }
        BatchIF_Log__c rowData = NFMUtil.saveRowData(Monitoring, 'NFM004', PurchasePrices.PurchasePrice);
        if (PurchasePrices.PurchasePrice == null || PurchasePrices.PurchasePrice.size() == 0) {
            return;
        }
        NFM004WebService u = new NFM004WebService(rowData.Id, 0, PurchasePrices.PurchasePrice.size());
        Database.executeBatch(u, 1);
    }

    /**
     * batchコンスタント、パラメータを受け取る
     */
    global NFM004WebService(Id rowData_Id, Integer startIndex, Integer dataLength) {
        this.rowData_Id = rowData_Id;
        this.startIndex = startIndex;
        this.dataLength = dataLength;
    }
    global Database.Querylocator start(Database.BatchableContext BC) {
        return Database.getQuerylocator([
            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 from BatchIF_Log__c where RowDataFlg__c = true and Id = :rowData_Id
        ]);
    }
    global void execute(Database.BatchableContext BC, List<BatchIF_Log__c> scope) {
        BatchIF_Log__c rowData = scope[0];
        String logstr = rowData.MessageGroupNumber__c + ' ' + startIndex + '/' + dataLength + ' start\n';
        BatchIF_Log__c iflog = new BatchIF_Log__c();
        iflog.Type__c = 'NFM004';
        iflog.MessageGroupNumber__c = rowData.MessageGroupNumber__c;
        iflog.Log__c = logstr;
        iflog.ErrorLog__c = '';
        insert iflog;
        String rowDataStr = NFMUtil.getRowDataStr(rowData);
        List<PurchasePrice> purchasePriceList2 = (List<PurchasePrice>) JSON.deserialize(rowDataStr, List<PurchasePrice>.class);
        if (purchasePriceList2 == null || purchasePriceList2.size() == 0) {
            return;
        }
        List<PurchasePrice> purchasePriceList = new List<PurchasePrice>();
        List<String> productCodeList = new List<String>();
        for (Integer i = startIndex; (i < startIndex + executeSize && i < purchasePriceList2.size()); i++) {
            purchasePriceList.add(purchasePriceList2.get(i));
            List<String> slicList = new List<String>();
            String Cache =  purchasePriceList2.get(i).SuppliersItemCode;
            if(String.isBlank(Cache) == false){
                slicList = Cache.split(',');
            }
            if(slicList.size()>0){
                String Slice = slicList[0];
                if (String.isBlank(Slice) == false) {
                    productCodeList.add(Slice);
                }
            }else{
                if (String.isBlank(purchasePriceList2.get(i).SuppliersItemCode) == false) {
                    productCodeList.add(purchasePriceList2.get(i).SuppliersItemCode);
                }
            }
            
        }
        logstr += 'Execute Record:' + purchasePriceList.size() + '\n';

        Savepoint sp = Database.setSavepoint();
        try {
            // 更新対応配列とMapなどをセット
            Map<String, Product2> prdsMap = new Map<String, Product2>();
            for (Product2 prd : [select Id, ProductCode, ProductCode_Ext__c,
                                             Intra_Trade_Cost_RMB_1__c,
                                             Intra_Trade_Cost_RMB_Date1__c,
                                             Intra_Trade_Cost_RMB_End_Date1__c,
                                             Intra_Trade_Cost_RMB_2__c,
                                             Intra_Trade_Cost_RMB_Date2__c,
                                             Intra_Trade_Cost_RMB_End_Date2__c,
                                             Foreign_Trade_Cost_US_1__c,
                                             Foreign_Trade_Cost_US_Date1__c,
                                             Foreign_Trade_Cost_US_End_Date1__c,
                                             Foreign_Trade_Cost_US_2__c,
                                             Foreign_Trade_Cost_US_Date2__c,
                                             Foreign_Trade_Cost_US_End_Date2__c,
                                             Intra_Trade_Cost_US__c,
                                             Intra_Trade_Cost_US_Date__c,
                                             Intra_Trade_Cost_US_End_Date__c,
                                             Foreign_Trade_Cost_RMB__c,
                                             Foreign_Trade_Cost_RMB_Date__c,
                                             VenderNumber__c,
                                             Foreign_Trade_Cost_RMB_End_Date__c
                                        from Product2
                                       where ProductCode_Ext__c in :productCodeList]
                                        //经调查，MDM接口过来的数据，手动登录区分是false，没有更新为true的程序，所以，手动登陆区分应该是
                                        //手动导入数据时，手工勾上的。
                                        //经确认，主数据无需判断是否手动登录区分，请将SFDC中手动登录区分的判断去掉。
                                        //and Manual_Entry__c = False]
            ) {
                prdsMap.put(prd.ProductCode_Ext__c, prd);
            }
            
            // 更新対応配列をセット
            Map<String, Product2> prdUpdateMap = new Map<String, Product2>();
            for (NFM004WebService.PurchasePrice PurchasePrice : purchasePriceList) {
                // deleteの場合、有効期限日に前日をセット
                if (PurchasePrice.PurposeOfAdvice == '1') {
                    PurchasePrice.EffectiveDateTo = NFMUtil.formatDate2Str(Date.today().addDays(-1));
                }

                // 必須項目がない場合、処理と飛ばす
                if (PurchasePrice.SuppliersItemCode == null || PurchasePrice.SuppliersItemCode == '') {
                    iflog.ErrorLog__c += 'SuppliersItemCode is required\n';
                    continue;
                }
                /************************************************************************************/
                //          添加针对供应商的判断   Start
                /************************************************************************************/
                String SuppliersIC = '';
                String VenderNumber = '';
                List<String> SuppliersItemCodeList = new List<String>();
                if(String.isBlank(PurchasePrice.SuppliersItemCode) == false){
                    SuppliersItemCodeList = PurchasePrice.SuppliersItemCode.split(',');
                }
                //SuppliersIC = PurchasePrice.SuppliersItemCode;

                if(SuppliersItemCodeList.size()==2){
                    if(SuppliersItemCodeList[0]=='' || SuppliersItemCodeList[0]==null){
                        iflog.ErrorLog__c += 'inputString is lack of SuppliersItemCode \n';
                    }else{
                        SuppliersIC = SuppliersItemCodeList[0];
                    }
                    if(SuppliersItemCodeList[1]=='' || SuppliersItemCodeList[1]==null){
                        iflog.ErrorLog__c += 'inputString is lack of VenderNumber \n';
                    }else{
                        VenderNumber = SuppliersItemCodeList[1];
                    }
                }else{
                    SuppliersIC = PurchasePrice.SuppliersItemCode;
                    iflog.ErrorLog__c += 'Version is unCorrect \n';
                    //continue;
                }
                /************************************************************************************/
                //          添加针对供应商的判断   END
                /************************************************************************************/
                /************************************************************************************/
                //          将SuppliersItemCode替换成SuppliersIC   Start
                /************************************************************************************/

                if (PurchasePrice.PriceType == null || PurchasePrice.PriceType == '') {
                    iflog.ErrorLog__c += '[' + SuppliersIC + ']PriceType is required\n';
                    continue;
                }
                if (PurchasePrice.PurchasePrice == null) {
                    iflog.ErrorLog__c += '[' + SuppliersIC + ']PurchasePrice is required\n';
                    continue;
                }
                if (PurchasePrice.Currency_x == null || PurchasePrice.Currency_x == '') {
                    iflog.ErrorLog__c += '[' + SuppliersIC + ']Currency is required\n';
                    continue;
                }
                if (PurchasePrice.EffectiveDateFrom == null || PurchasePrice.EffectiveDateFrom == '') {
                    iflog.ErrorLog__c += '[' + SuppliersIC + ']EffectiveDateFrom is required\n';
                    continue;
                }
                if (PurchasePrice.EffectiveDateTo == null || PurchasePrice.EffectiveDateTo == '') {
                    iflog.ErrorLog__c += '[' + SuppliersIC + ']EffectiveDateTo is required\n';
                    continue;
                }

                Product2 prd = prdsMap.get(SuppliersIC);
                if (prd == null) {
                    // 更新対象商品がない場合
                    iflog.ErrorLog__c += 'Product[' + SuppliersIC + ']NotExist\n';
                    continue;
                }

                // 項目転送のセット
                prd.ProductCode = SuppliersIC;
                prd.VenderNumber__c = VenderNumber;
                if (prdUpdateMap.get(prd.ProductCode) == null) {
                    prdUpdateMap.put(prd.ProductCode, prd);
                    logstr += SuppliersIC + ' ';
                } else {
                    prd = prdUpdateMap.get(prd.ProductCode);
                }
                /************************************************************************************/
                //          将SuppliersItemCode替换成SuppliersIC   END
                /************************************************************************************/
                Date dateFrom = NFMUtil.parseStr2Date(PurchasePrice.EffectiveDateFrom, false);
                Date dateTo = NFMUtil.parseStr2Date(PurchasePrice.EffectiveDateTo, true);
                if (PurchasePrice.PriceType == 'OCM-001' && PurchasePrice.Currency_x == 'RMB') {
                    if (prd.Intra_Trade_Cost_RMB_1__c == null || prd.Intra_Trade_Cost_RMB_End_Date1__c < Date.today() || prd.Intra_Trade_Cost_RMB_Date1__c == dateFrom) {
                        prd.Intra_Trade_Cost_RMB_1__c          = PurchasePrice.PurchasePrice;
                        prd.Intra_Trade_Cost_RMB_Date1__c      = dateFrom;
                        prd.Intra_Trade_Cost_RMB_End_Date1__c  = dateTo;
                    } else if (prd.Intra_Trade_Cost_RMB_2__c == null || prd.Intra_Trade_Cost_RMB_End_Date2__c < Date.today() || prd.Intra_Trade_Cost_RMB_Date2__c == dateFrom) {
                        prd.Intra_Trade_Cost_RMB_2__c          = PurchasePrice.PurchasePrice;
                        prd.Intra_Trade_Cost_RMB_Date2__c      = dateFrom;
                        prd.Intra_Trade_Cost_RMB_End_Date2__c  = dateTo;
                    } else if (prd.Intra_Trade_Cost_RMB_Date1__c < prd.Intra_Trade_Cost_RMB_Date2__c) {
                        prd.Intra_Trade_Cost_RMB_1__c          = PurchasePrice.PurchasePrice;
                        prd.Intra_Trade_Cost_RMB_Date1__c      = dateFrom;
                        prd.Intra_Trade_Cost_RMB_End_Date1__c  = dateTo;
                    } else {
                        prd.Intra_Trade_Cost_RMB_2__c          = PurchasePrice.PurchasePrice;
                        prd.Intra_Trade_Cost_RMB_Date2__c      = dateFrom;
                        prd.Intra_Trade_Cost_RMB_End_Date2__c  = dateTo;
                    }
                } else if (PurchasePrice.PriceType == 'OHC-001' && PurchasePrice.Currency_x == 'USD') {
                    if (prd.Foreign_Trade_Cost_US_1__c == null || prd.Foreign_Trade_Cost_US_End_Date1__c < Date.today() || prd.Foreign_Trade_Cost_US_Date1__c == dateFrom) {
                        prd.Foreign_Trade_Cost_US_1__c         = PurchasePrice.PurchasePrice;
                        prd.Foreign_Trade_Cost_US_Date1__c     = dateFrom;
                        prd.Foreign_Trade_Cost_US_End_Date1__c = dateTo;
                    } else if (prd.Foreign_Trade_Cost_US_2__c == null || prd.Foreign_Trade_Cost_US_End_Date2__c < Date.today() || prd.Foreign_Trade_Cost_US_Date2__c == dateFrom) {
                        prd.Foreign_Trade_Cost_US_2__c         = PurchasePrice.PurchasePrice;
                        prd.Foreign_Trade_Cost_US_Date2__c     = dateFrom;
                        prd.Foreign_Trade_Cost_US_End_Date2__c = dateTo;
                    } else if (prd.Foreign_Trade_Cost_US_Date1__c < prd.Foreign_Trade_Cost_US_Date2__c) {
                        prd.Foreign_Trade_Cost_US_1__c         = PurchasePrice.PurchasePrice;
                        prd.Foreign_Trade_Cost_US_Date1__c     = dateFrom;
                        prd.Foreign_Trade_Cost_US_End_Date1__c = dateTo;
                    } else {
                        prd.Foreign_Trade_Cost_US_2__c         = PurchasePrice.PurchasePrice;
                        prd.Foreign_Trade_Cost_US_Date2__c     = dateFrom;
                        prd.Foreign_Trade_Cost_US_End_Date2__c = dateTo;
                    }
                } else if (PurchasePrice.PriceType == 'OCM-001' && PurchasePrice.Currency_x == 'USD') {
                    prd.Intra_Trade_Cost_US__c             = PurchasePrice.PurchasePrice;
                    prd.Intra_Trade_Cost_US_Date__c        = dateFrom;
                    prd.Intra_Trade_Cost_US_End_Date__c    = dateTo;
                } else if (PurchasePrice.PriceType == 'OHC-001' && PurchasePrice.Currency_x == 'RMB') {
                    prd.Foreign_Trade_Cost_RMB__c          = PurchasePrice.PurchasePrice;
                    prd.Foreign_Trade_Cost_RMB_Date__c     = dateFrom;
                    prd.Foreign_Trade_Cost_RMB_End_Date__c = dateTo;
                }
            }
            List<Product2> prdList = prdUpdateMap.values();
            if (prdList.size() > 0) {
                StaticParameter.EscapeSyncProduct2Trigger = true;
                update prdList;
            }
            logstr += '\nend';
        } catch(Exception ex) {
            // エラーが発生した場合
            Database.rollback(sp);
            System.debug(Logginglevel.ERROR, 'NFM004_' + rowData.MessageGroupNumber__c + ':' + ex.getMessage());
            System.debug(Logginglevel.ERROR, 'NFM004_' + rowData.MessageGroupNumber__c + ':' + ex.getStackTraceString());
            logstr += '\n' + ex.getMessage();
            iflog.ErrorLog__c = ex.getMessage() + '\n' + ex.getStackTraceString() + '\n' + iflog.ErrorLog__c;
        }
        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;
    }

    global void finish(Database.BatchableContext BC) {
        if (startIndex + executeSize < dataLength) {
            NFM004WebService u = new NFM004WebService(rowData_Id, startIndex + executeSize, dataLength);
            Database.executeBatch(u, 1);
        }
    }
}