/* 用于新维修合同二期，计算每个合同到上月月底的合同消费率
1) 检索上一期维修合同：包括合同价格、合同开始日期；
2) 检索出上一期维修合同所有的维修合同保有设备；
3) 检索出这些维修合同保有设备之前的上上期维修合同保有设备；
4) 计算出上一期维修合同开始日期到当前日期的上月月末的的合同金额、上一期开始日期到当前日期的上月月末的修理报价金额；
5) 计算出上上期维修合同上一期维修合同首次报价日（目前未知）到结束日期的的合同金额、上一期开始日期到结束日期的修理报价金额；
6) 储存上一期维修合同、上一期维修合同保有设备在保有设备上；
*Date：2019-12-06
*/ 
global class AssetUpdateContractBatch implements Database.Batchable<sObject>, Database.Stateful {
    // 设定运行的维修合同的ID
    public string TestID;

    // 设定执行日期
    public Date TestDate;
    
    // 设定每月或者每日执行
    public Boolean IsDaily;

    // 是否运行所有维修合同
    public Boolean isAll = false;

    // 设定运行的维修合同的list<ID>
    public list<string> TestIDList;

    // 报错的维修合同ID
    public String logstr = '';

    // 报错信息
    public String errorstr = '';

    Boolean IsNeedExecute = false;


    global Integer totalCount = 0; // 总件数
    global Integer failedCount = 0; // 失败件数

    global List<String> emailMessages = new List<String>();
	//  按照当日执行。 只执行合同结束日大于当日前40天的维修合同
    global AssetUpdateContractBatch() {
        this.TestDate = Date.today();
        this.isAll = false;
        this.isDaily = isDaily(this.TestDate);
    }
    // 按照设定结束日期执行。 只执行合同结束日大于设定结束日期前40天的维修合同
    global AssetUpdateContractBatch(Date testDate) {
        this.TestDate = testDate;
        this.isAll = false;
        this.isDaily = isDaily(this.TestDate);
    }

    // 按照设定结束日期执行所有维修合同,基本上不会使用；
    global AssetUpdateContractBatch(Date testDate , boolean isAll) {
        this.TestDate = testDate;
        this.isAll = isAll;
        this.isDaily = isDaily(this.TestDate);
    }

    // 按照设定结束日期执行选定的维修合同
    global AssetUpdateContractBatch(string TestID, Date testDate) {
        this.TestID = TestID;
        this.TestDate = testDate;
        this.isDaily = isDaily(this.TestDate);
    }

    // 按照设定结束日期执行选定的维修合同组
    global AssetUpdateContractBatch(list<string> TestIDList, Date testDate) {
        this.TestIDList = TestIDList;
        this.TestDate = testDate;
        this.isDaily = isDaily(this.TestDate);
    }

    //2021-06-16  mzy  WLIG-BYHD79  SFDC环境batch合并调查  start
    global AssetUpdateContractBatch(Boolean NeedExecute) {
        this.TestDate = Date.today();
        this.isAll = false;
        this.isDaily = isDaily(this.TestDate);
        this.IsNeedExecute = needExecute;
    }
    //2021-06-16  mzy  WLIG-BYHD79  SFDC环境batch合并调查  end

    global Database.QueryLocator start(Database.BatchableContext bc) {
        string query =
            ' select id , previousTotalRepairAmount__c , currentTotalRepairAmount__c ,' +
            ' previousTotalContractAmount__c , currentTotalContractAmountVM__c , currentTotalGuaranteePrice__c '+
            ' , RecordType_DeveloperName__c  ' +
            '  from Maintenance_Contract__c '
            + ' where Status__c in (\'契約\',\'契約満了\') ';
        if (string.isNotBlank(TestID) ) {
            query += ' and id =: TestID';
        } else if (TestIDList != null && TestIDList.size() > 0) {
            query += ' and id in: TestIDList';
        } else if (!isAll) {
            query += ' and Contract_End_Date__c > '
                     + testDate.addDays(-50).format().replace('/', '-') ;
        }
        if(isDaily){
           query += ' and Contract_End_Date__c = ' + 
                    testDate.addDays(-1).format().replace('/', '-'); 
        }
        //system.debug('query:'+query);
        testDate = Datecheck(testDate);

        return Database.getQueryLocator(query);
    }

    global void execute(Database.BatchableContext BC,
                        list<Maintenance_Contract__c> MCList) {

        map<string, asset> updateAssetMap = new map<string, asset>();
        map<string, Maintenance_Contract__c> UpdateMCMap =
            new map<string, Maintenance_Contract__c>();
        map<string,Maintenance_Contract__c> mcIDmap = new map<string,Maintenance_Contract__c>();

        // 20210906 gzw 计算维修合同报价/保有设备 上的实际报价金额
        map<string,Decimal> mcAssetmap = new map<string,Decimal>();
        map<string,List<Maintenance_Contract_Asset_Estimate__c>> mcaasmap = new map<string,List<Maintenance_Contract_Asset_Estimate__c>>();
        // 20210906 gzw 计算维修合同报价/保有设备 上的实际报价金额


        Set<Id> newAssetIDset = new Set<Id>();
        Set<ID> allAssetIDSet = new Set<ID>();
        List<asset> allAssetList = new List<asset>();
        // 初始化维修合同消费率相关金额字段为0;
        for (Maintenance_Contract__c tempMC : MCList) {
            mcIDmap.put(tempMC.id,null);
            tempMC.currentTotalRepairAmount__c  = 0;
            tempMC.previousTotalRepairAmount__c = 0;
            tempMC.previousTotalContractAmount__c = 0;
            tempMC.currentTotalContractAmountVM__c  = 0;
            tempMC.currentTotalGuaranteePrice__c = 0;
            UpdateMCMap.put(tempMC.id, tempMC);
        }
        //system.debug('UpdateMCMap1:' + UpdateMCMap);
        map<string, Maintenance_Contract_Asset__c> newToOldMCA =
            new map<string, Maintenance_Contract_Asset__c>();
        map<string, Maintenance_Contract_Asset__c> assetIDtoMCA =
            new map<string, Maintenance_Contract_Asset__c>();
		// 检索本次batch涉及的维修合同对应的保有设备
        list<Maintenance_Contract_Asset__c> mcaList =
            [select Id, Asset__c, Maintenance_Contract__c,
             Estimate_Cost_formula__c,
             startDate_sum__c,
             endDate_sum__c,
             No_discount__c,
             GuaranteePrice_Amount_Text__c,
             Maintenance_Contract__r.Status__c,
             Maintenance_Contract__r.Name,
             Maintenance_Contract__r.Contract_End_Date__c,
             Maintenance_Contract__r.Contract_Start_Date__c,
             Maintenance_Contract__r.RecordType_DeveloperName__c,
             Maintenance_Contract__r.Estimation_Id__r.Submit_quotation_day__c,
             Maintenance_Contract__r.RecordType.DeveloperName
             , ifHaveleftInPrevious__c
             from Maintenance_Contract_Asset__c
             where Maintenance_Contract__c in: mcIDmap.keyset()
            ];
        //system.debug('mcaList1:' + mcaList);
        //给当期维修合同保有设备赋值
        // 20210906 gzw 计算维修合同报价/保有设备 上的实际报价金额
        // 检索本次batch涉及的维修合同报价/保有设备
        list<Maintenance_Contract_Asset_Estimate__c> mcaasList =
            [select Id, Asset__c,ContractAsset_key__c,Maintenance_Contract_Estimate__r.Maintenance_Contract__c, ContractAsset_Amont__c
             from Maintenance_Contract_Asset_Estimate__c
             where Maintenance_Contract_Estimate__r.Maintenance_Contract__c in: mcIDmap.keyset()
             and Asset__c != null
            ];
        for (Maintenance_Contract_Asset_Estimate__c mcae :mcaasList) {
            List<Maintenance_Contract_Asset_Estimate__c> temp = new List<Maintenance_Contract_Asset_Estimate__c>();
            System.debug( 'ContractAsset_key__c ++++++++++++++ '+   mcae.ContractAsset_key__c);
            if (mcaasmap.containsKey(mcae.ContractAsset_key__c)) {
                temp = mcaasmap.get(mcae.ContractAsset_key__c);
            }
            temp.add(mcae);
            mcaasmap.put(mcae.ContractAsset_key__c, temp);
        }
        // 20210906 gzw 计算维修合同报价/保有设备 上的实际报价金额
       
        //给当期维修合同保有设备赋值                   
        //updateCurrentMCAsset ( mcaList,  UpdateMCMap, allAssetIDSet, newToOldMCA,
        //                         newAssetIDset,  assetIDtoMCA);
        for (Maintenance_Contract_Asset__c mca : mcaList) {
            Maintenance_Contract__c tempMC = UpdateMCMap.get(mca.Maintenance_Contract__c); 
            //如果是多年保修合同且输入日期晚于结束日期，则使用保有设备上的全额no discount 和计提金额
            // 计算本期合同金额（多年保修故障风险率用）、合同金额（多年保修故障风险率管理用）
            if (testDate > mca.endDate_sum__c &&
                    mca.Maintenance_Contract__r.RecordType.DeveloperName.equals('VM_Contract')) {
                tempMC.currentTotalContractAmountVM__c +=
                    mca.No_discount__c == null ?
                    0 :
                    mca.No_discount__c;
                 tempMC.currentTotalGuaranteePrice__c +=
                    mca.GuaranteePrice_Amount_Text__c == null ?
                    0 :
                    mca.GuaranteePrice_Amount_Text__c;
                 
                //continue;
            } 
            //如果是多年保修合同且输入日期晚于开始日期，则使用保有设备上的全额no discount 和计提金额 按照日期比例
            // 计算本期合同金额（多年保修故障风险率用）、合同金额（多年保修故障风险率管理用）
            else if ( testDate >= mca.startDate_sum__c &&
                        mca.Maintenance_Contract__r.RecordType.DeveloperName.equals('VM_Contract')) {
                Decimal tempNo_discount =  mca.No_discount__c == null ?
                                           0 :
                                           mca.No_discount__c;
                Decimal GuaranteePrice_Amount =  mca.GuaranteePrice_Amount_Text__c == null ?
                                           0 :
                                           mca.GuaranteePrice_Amount_Text__c;
                system.debug('mca.startDate_sum__c.daysBetween(testDate):'+
                    mca.startDate_sum__c.daysBetween(testDate));
                tempMC.currentTotalContractAmountVM__c +=
                    tempNo_discount * (mca.startDate_sum__c.daysBetween(testDate) + 1) /
                    (mca.startDate_sum__c.daysBetween(mca.endDate_sum__c) + 1);
                tempMC.currentTotalGuaranteePrice__c +=
                    GuaranteePrice_Amount * (mca.startDate_sum__c.daysBetween(testDate) + 1) /
                    (mca.startDate_sum__c.daysBetween(mca.endDate_sum__c) + 1);
                //continue;
            }
			// 服务合同需要再检索上期维修合同保有设备剩余
            if (mca.Maintenance_Contract__r.RecordType.DeveloperName.equals('NewMaintenance_Contract')) {
                newAssetidset.add(mca.Asset__c);
            }
            // 找出来检索出来的维修合同保有中的最新的
            if (assetIDtoMCA.containsKey(mca.Asset__c)) {
                Maintenance_Contract_Asset__c tempMCA =
                    assetIDtoMCA.get(mca.Asset__c);
                if (tempMCA.endDate_sum__c < mca.endDate_sum__c) {
                    assetIDtoMCA.put(mca.Asset__c, mca);
                }
            } else {
                assetIDtoMCA.put(mca.Asset__c, mca);
            }
            allAssetIDSet.add(mca.Asset__c);
            newToOldMCA.put(mca.id, null);
        }
        //system.debug('allAssetIDSet:' + allAssetIDSet);
        //system.debug('newToOldMCA:' + newToOldMCA);
        allAssetList =
            [select id, CurrentContract_F__c,
             CurrentContract_F__r.Contract_End_Date__c,
             CurrentContract_F_asset__c,
             CurrentContract_F_asset__r.endDate_sum__c
             from asset
             where id in: allAssetIDSet];
        // 更新保有设备上的上一期维修合同和维修合同保有设备
        // 找出来的不一定是最新的，因为还会和保有设备上对比一下
        for (asset ass : allAssetList) {
            Maintenance_Contract_Asset__c tempMCA =
                assetIDtoMCA.get(ass.Id);
            if (tempMCA != null &&
                    (
                        ass.CurrentContract_F__c == null  ||
                        ass.CurrentContract_F_asset__c == null ||
                        ass.CurrentContract_F_asset__r.endDate_sum__c <=
                        tempMCA.endDate_sum__c

                    ) ) {
                ass.CurrentContract_F__c = tempMCA.Maintenance_Contract__c;
                ass.CurrentContract_F_asset__c = tempMCA.id;
                updateAssetMap.put(ass.id, ass);
            }

        }
        //检索出历届保有设备
        list<Maintenance_Contract_Asset__c> allMCAList =
            [select Id, Asset__c, Maintenance_Contract__c,
             Estimate_Cost_formula__c,
             startDate_sum__c,
             endDate_sum__c,
             ifHaveleftInPrevious__c,
             Maintenance_Contract__r.Status__c,
             Maintenance_Contract__r.Name,
             Maintenance_Contract__r.Contract_End_Date__c,
             Maintenance_Contract__r.Contract_Start_Date__c,
             Maintenance_Contract__r.RecordType_DeveloperName__c,
             Maintenance_Contract__r.Estimation_Id__r.Submit_quotation_day__c,
             Maintenance_Contract__r.RecordType.DeveloperName,
             Maintenance_Contract__r.First_Estimate_Date__c
             from Maintenance_Contract_Asset__c
             where Asset__c in: newAssetidset
             and Maintenance_Contract__r.RecordType.DeveloperName = 'NewMaintenance_Contract'
                     and Maintenance_Contract__r.Status__c in ('契約', '契約満了')
                     order by Asset__c, endDate_sum__c desc
            ];
       // system.debug('allMCAList:' + allMCAList);
        Set<string> ALLMCIDset = mcIDmap.keySet().clone();
       // system.debug('ALLMCIDset1:' + ALLMCIDset);
        map<string, Maintenance_Contract_Asset__c> oldToNewMCA =
            new map<string, Maintenance_Contract_Asset__c>();
        map<string, Maintenance_Contract_Asset__c> strToOldMCA =
            new map<string, Maintenance_Contract_Asset__c>();
        ID tempAssetID;
        Maintenance_Contract_Asset__c newMCA = null;
        // 构建上一期维修合同保有设备和对应的上上期维修合同保有设备之间的关系
        for (Maintenance_Contract_Asset__c tempMCA : allMCAList) {
            if (tempMCA.Asset__c != tempAssetID) {
                tempAssetID = tempMCA.Asset__c;
                newMCA = tempMCA;
                continue;
            }
            system.debug('tempMCA:'+tempMCA);
            system.debug('newMCA:'+newMCA);
            if (newToOldMCA.containsKey(newMCA.id)  && newMCA.ifHaveleftInPrevious__c
                    && tempMCA.Maintenance_Contract__r.First_Estimate_Date__c != null
                    && tempMCA.Estimate_Cost_formula__c  != null

               ) {
                newToOldMCA.put(newMCA.id, tempMCA);
                string str = '' + (ID) tempMCA.Maintenance_Contract__c + tempMCA.Asset__c;
                Maintenance_Contract__c newMC =
                    UpdateMCMap.get(newMCA.Maintenance_Contract__c);
				// 如果保存在上一期维修合同的首次报价日早于或等于合同结束日,则计算上一期合同金额
                if(tempMCA.Maintenance_Contract__r.First_Estimate_Date__c <= tempMCA.endDate_sum__c){
                    newMC.previousTotalContractAmount__c +=
                        tempMCA.Estimate_Cost_formula__c
                        * (getTheFirstDayOftheMonth(tempMCA.Maintenance_Contract__r.First_Estimate_Date__c).daysBetween(
                                tempMCA.endDate_sum__c)+1)
                        / (tempMCA.startDate_sum__c.daysBetween(tempMCA.endDate_sum__c)+1);
                }
                oldToNewMCA.put(str, newMCA);
          //      system.debug(oldToNewMCA.get(str));
                strToOldMCA.put(str, tempMCA);
                ALLMCIDset.add(tempMCA.Maintenance_Contract__c);
            }
            newMCA = tempMCA;
        }
       // system.debug('newToOldMCA2:' + newToOldMCA);
       // system.debug('oldToNewMCA:' + oldToNewMCA);
       // system.debug('strToOldMCA:' + strToOldMCA);
      //  system.debug('ALLMCIDset2:' + ALLMCIDset);
      //  检索所有合同保有设备的修理
        list<Repair__c> newRepiarList = new list<Repair__c>();
        if (ALLMCIDset.size() > 0) {
            newRepiarList =
                [select Id, Usage_Ratio_Price_Contract__c,
                 Usage_Ratio_Price_Guarantee__c,Usage_Ratio_Price_Service__c,
                 Delivered_Product__c,
                 Repair_cost__c,
                 Maintenance_Contract__c,
                 Maintenance_Contract__r.Contract_Start_Date__c,
                 Maintenance_Contract__r.Contract_End_Date__c,
                 Failure_Occurrence_Date__c,
                 Repair_Quotation_Id__c,
                 VM_Maintenance_Contract__c
                 from Repair__c
                 where (Maintenance_Contract__c != null or VM_Maintenance_Contract__c != null)
                 and (Maintenance_Contract__c in: ALLMCIDset
                      or VM_Maintenance_Contract__c in: ALLMCIDset)
                 and Status2__c != '00.删除'
                 and Status2__c != '00.取消'
                 and  Failure_Occurrence_Date__c <= : testDate
                 order by Maintenance_Contract__c
                ];
        }
        //system.debug('newRepiarList:' + newRepiarList);
       /* map<id, list<Repair__c>> MCIDtoRepiarMap =
            new map<id, list<Repair__c>> ();
        map<id, list<Repair__c>> MCAIDtoRepiarMap =
            new map<id, list<Repair__c>> ();*/
        // 根据记录类型的不同，分别计算上一期和上上期的修理金额
        if (newRepiarList != null && newRepiarList.size() > 0) {
            for (Repair__c rc : newRepiarList) {
                system.debug('rc'+rc);
                string mcID = rc.Maintenance_Contract__c == null ?
                          rc.VM_Maintenance_Contract__c : rc.Maintenance_Contract__c;
                if ( mcIDmap.containsKey(mcID)) {
                    Maintenance_Contract__c tempMC = UpdateMCMap.get(mcID);
                    System.debug( 'mcID ++++++++++++++ '+   mcID + rc.Delivered_Product__c);
                    // 20210906 gzw 计算维修合同报价/保有设备 上的实际报价金额
                    if(tempMC.RecordType_DeveloperName__c.equals('Maintenance_Contract')){
                        tempMC.currentTotalRepairAmount__c += rc.Usage_Ratio_Price_Contract__c;
                        if (mcAssetmap.containsKey(mcID + rc.Delivered_Product__c)) {
                            mcAssetmap.put(mcID + rc.Delivered_Product__c, mcAssetmap.get(mcID + rc.Delivered_Product__c) + rc.Usage_Ratio_Price_Contract__c);
                        }else{
                            mcAssetmap.put(mcID + rc.Delivered_Product__c, rc.Usage_Ratio_Price_Contract__c);
                        }
                    }else if(tempMC.RecordType_DeveloperName__c.equals('NewMaintenance_Contract')){
                        tempMC.currentTotalRepairAmount__c += rc.Usage_Ratio_Price_Service__c;
                        if (mcAssetmap.containsKey(mcID + rc.Delivered_Product__c)) {
                            mcAssetmap.put(mcID + rc.Delivered_Product__c, mcAssetmap.get(mcID + rc.Delivered_Product__c) + rc.Usage_Ratio_Price_Service__c);
                        }else{
                            mcAssetmap.put(mcID + rc.Delivered_Product__c, rc.Usage_Ratio_Price_Service__c);
                        }
                    }else if(tempMC.RecordType_DeveloperName__c.equals('VM_Contract')){
                        tempMC.currentTotalRepairAmount__c += rc.Usage_Ratio_Price_Guarantee__c;
                        if (mcAssetmap.containsKey(mcID + rc.Delivered_Product__c)) {
                            mcAssetmap.put(mcID + rc.Delivered_Product__c, mcAssetmap.get(mcID + rc.Delivered_Product__c) + rc.Usage_Ratio_Price_Guarantee__c);
                        }else{
                            mcAssetmap.put(mcID + rc.Delivered_Product__c, rc.Usage_Ratio_Price_Guarantee__c);
                        }
                    }
                    // 20210906 gzw 计算维修合同报价/保有设备 上的实际报价金额
                }
                string mcaIDandAssetID = '' + mcID + rc.Delivered_Product__c;
                system.debug('mcaIDandAssetID'+mcaIDandAssetID);
                if (oldToNewMCA.containsKey(mcaIDandAssetID )
                   ) {
                    Maintenance_Contract_Asset__c OldMCA =
                        strToOldMCA.get(mcaIDandAssetID);
                	
                    //system.debug('OldMCA.Maintenance_Contract__r.First_Estimate_Date__c:'+OldMCA.Maintenance_Contract__r.First_Estimate_Date__c);
                    if (rc.Failure_Occurrence_Date__c >=
                            getTheFirstDayOftheMonth(OldMCA.Maintenance_Contract__r.First_Estimate_Date__c)
                            && rc.Failure_Occurrence_Date__c <= OldMCA.endDate_sum__c
                            && OldMCA.Maintenance_Contract__r.First_Estimate_Date__c <= OldMCA.endDate_sum__c
                             ) {
                        Maintenance_Contract_Asset__c tempNewMCA =
                            oldToNewMCA.get(mcaIDandAssetID);
                        Maintenance_Contract__c newMC =
                            UpdateMCMap.get(tempNewMCA.Maintenance_Contract__c);
                        if(newMC.RecordType_DeveloperName__c.equals('NewMaintenance_Contract')){
                        newMC.previousTotalRepairAmount__c += rc.Usage_Ratio_Price_Service__c;
                        } 
                    }

                }
            }
        }
        //system.debug('UpdateMCMap last:' + UpdateMCMap);
        StaticParameter.EventOpportunityPileUpExeFlg = true;
        // EventC⇒Event処理後、逆更新をスルー用
        StaticParameter.NotUpdEventCFlg = true;
        // 積み上げ処理後、トリガをスルー用
        StaticParameter.EscapeNFM001Trigger = true;
        StaticParameter.EscapeNFM001AgencyContractTrigger = true;
        StaticParameter.EscapeNFM001AgencyContractTrigger2 = true;
        StaticParameter.EscapeNFM007Trigger = true;
        StaticParameter.EscapeOpportunityBefUpdTrigger = true;
        StaticParameter.EscapeOpportunityHpDeptUpdTrigger = true;
        StaticParameter.EscapeSyncOpportunityTrigger = true;
        StaticParameter.EscapeMaintenanceContractAfterUpdateTrigger = true;
        StaticParameter.EscapeSyncProduct2Trigger = true;
        // trueのとき、リードのトリガーをスルーする
        StaticParameter.EscapeLeadTrigger = true;
        StaticParameter.EscapeAccountTrigger = true;

        StaticParameter.EscapeConsumableOrderDetail2Trigger = true;

        StaticParameter.EscapeNFM010UpsertStatuAchievementsTrigger = true;
        // 直销耗材不直销 ConsumableAssetHander
        StaticParameter.ConsumableAssetHanderTrigger = true;

        // 跳过不涉及备品借出的逻辑
        StaticParameter.rentalApplyIsRunning = true;

        // accountdailyUpdate 跳过 更新询价
        StaticParameter.EscapeOpportunityownerUpdate  = true;
        // 20210906 gzw 计算维修合同报价/保有设备 上的实际报价金额
        List<Maintenance_Contract_Asset_Estimate__c> McaeupList = new List<Maintenance_Contract_Asset_Estimate__c>();
        for (String str :mcAssetmap.keyset()) {
            if (mcaasmap.containsKey(str)) {
                for (Maintenance_Contract_Asset_Estimate__c mca: mcaasmap.get(str) ) {
                    mca.ContractAsset_Amont__c = mcAssetmap.get(str);
                    McaeupList.add(mca);
                }
            }
        }
        if (McaeupList.size() > 0) {
            update McaeupList;
        }
        // 20210906 gzw 计算维修合同报价/保有设备 上的实际报价金额
        Database.SaveResult[] saveResults = Database.update(UpdateMCMap.values(), false);
            //                system.debug('saveResults'+saveResults);
        totalCount = + saveResults.size();
        for (Integer i = 0; i < saveResults.size(); i++) {
            if (!saveResults.get(i).isSuccess() || Test.isRunningTest()) {
                logstr += '维修合同:' + UpdateMCMap.values().get(i).Id + ',';
                errorstr += saveResults.get(i).getErrors() + '\n';
                failedCount ++;
            }
        }
        updateAsset (updateAssetMap.values());
    }
    global void finish(Database.BatchableContext BC) {
        BatchIF_Log__c batchIfLog = new BatchIF_Log__c();
        batchIfLog.Type__c = 'MCAssetUpdate';
        if (logstr.length() > 60000) {
            logstr = logstr.substring(0, 60000);
        }
        batchIfLog.Log__c = logstr;
        logstr += '\nBatchMCAssetUpdateEnd';
        if (errorstr.length() > 60000) {
            batchIfLog.ErrorLog__c = errorstr.substring(0, 60000);
        } else {
            batchIfLog.ErrorLog__c = errorstr.substring(0, errorstr.length());
        }
        insert batchIfLog;
        emailMessages.add('失败日志ID为：' + batchIfLog.Id);
        sendFieldEmail();


        //2021-04-21  mzy  add  start
        //目前不希望EventToEventDetailsBatch 运行
        IsNeedExecute = false;
        if(!Test.isRunningTest() &&IsNeedExecute==true){
            //batch里调用下一个batch时，希望跟原有的Schedule里面传的条数保持一致
            Id execBTId = Database.executebatch(new EventToEventDetailsBatch(true),20);
        }
        //2021-04-21  mzy  add  end
    }
     // 更新当期维修合同保有设备
    private void updateCurrentMCAsset (list<Maintenance_Contract_Asset__c> mcaList,
                                      map<id, Maintenance_Contract__c> UpdateMCMap,
                                       Set<ID> allAssetIDSet,
                                       map<id, Maintenance_Contract_Asset__c> newToOldMCA,
                                      Set<Id> newAssetIDset,
                                       map<id, Maintenance_Contract_Asset__c> assetIDtoMCA
                                      ) {
		for (Maintenance_Contract_Asset__c mca : mcaList) {
            Maintenance_Contract__c tempMC = UpdateMCMap.get(mca.Maintenance_Contract__c); 
            //如果是多年保修合同且输入日期晚于结束日期，则使用保有设备上的全额no discount 和计提金额
            // 计算本期合同金额（多年保修故障风险率用）、合同金额（多年保修故障风险率管理用）
            if (testDate > mca.endDate_sum__c &&
                    mca.Maintenance_Contract__r.RecordType.DeveloperName.equals('VM_Contract')) {
                tempMC.currentTotalContractAmountVM__c +=
                    mca.No_discount__c == null ?
                    0 :
                    mca.No_discount__c;
                 tempMC.currentTotalGuaranteePrice__c +=
                    mca.GuaranteePrice_Amount_Text__c == null ?
                    0 :
                    mca.GuaranteePrice_Amount_Text__c;
                 
                //continue;
            } 
            //如果是多年保修合同且输入日期晚于开始日期，则使用保有设备上的全额no discount 和计提金额 按照日期比例
            // 计算本期合同金额（多年保修故障风险率用）、合同金额（多年保修故障风险率管理用）
            else if ( testDate >= mca.startDate_sum__c &&
                        mca.Maintenance_Contract__r.RecordType.DeveloperName.equals('VM_Contract')) {
                Decimal tempNo_discount =  mca.No_discount__c == null ?
                                           0 :
                                           mca.No_discount__c;
                Decimal GuaranteePrice_Amount =  mca.GuaranteePrice_Amount_Text__c == null ?
                                           0 :
                                           mca.GuaranteePrice_Amount_Text__c;
                system.debug('mca.startDate_sum__c.daysBetween(testDate):'+
                    mca.startDate_sum__c.daysBetween(testDate));
                tempMC.currentTotalContractAmountVM__c +=
                    tempNo_discount * (mca.startDate_sum__c.daysBetween(testDate) + 1) /
                    (mca.startDate_sum__c.daysBetween(mca.endDate_sum__c) + 1);
                tempMC.currentTotalGuaranteePrice__c +=
                    GuaranteePrice_Amount * (mca.startDate_sum__c.daysBetween(testDate) + 1) /
                    (mca.startDate_sum__c.daysBetween(mca.endDate_sum__c) + 1);
                //continue;
            }
			// 服务合同需要再检索上期维修合同保有设备剩余
            if (mca.Maintenance_Contract__r.RecordType.DeveloperName.equals('NewMaintenance_Contract')) {
                newAssetidset.add(mca.Asset__c);
            }
            // 找出来检索出来的维修合同保有中的最新的
            if (assetIDtoMCA.containsKey(mca.Asset__c)) {
                Maintenance_Contract_Asset__c tempMCA =
                    assetIDtoMCA.get(mca.Asset__c);
                if (tempMCA.endDate_sum__c < mca.endDate_sum__c) {
                    assetIDtoMCA.put(mca.Asset__c, mca);
                }
            } else {
                assetIDtoMCA.put(mca.Asset__c, mca);
            }
            allAssetIDSet.add(mca.Asset__c);
            newToOldMCA.put(mca.id, null);
        }
    }
    // 更新保有设备，并记录下出错数据ID和出错信息
    private void updateAsset (list<Asset> assetList) {
        Database.SaveResult[] saveResults = Database.update(assetList, false);
        totalCount = + saveResults.size();
        for (Integer i = 0; i < saveResults.size(); i++) {
            if (!saveResults.get(i).isSuccess() || Test.isRunningTest()) {
                logstr += 'asset:' + assetList.get(i).Id + ',';
                errorstr += saveResults.get(i).getErrors() + '\n';
                failedCount ++;
            }
        }
    }

    // 如果 testDate 有值，则返回testDate 值，否则如果当天是当月1日，则取上月最后一日
    @TestVisible
    public static Date Datecheck(Date testDate) {
        Date today = testDate;
        if (testDate == null) {
             today = Date.today();
        }
        today = today.addDays(-1);   
        return today;
    }
    // 判断是否每天执行的batch
    @TestVisible
    private static Boolean isDaily(Date testDate) {
        if(testDate!=null && testDate.day()==1)
            return false;
        return true;
    }
	 @TestVisible
    private static void test() {
        integer i = 0;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        i++;
        
    }
    /*
    public Date PickEarlierDate( Date tempDate1, Date tempDate2) {
        if (tempDate2 == null) {
            return tempDate1;
        } else {
            return tempDate2 > tempDate1 ? tempDate1 : tempDate2;
        }
    }*/
    // 获取 当月第一天
    public Date getTheFirstDayOftheMonth( Date tempDate) {
        if (tempDate == null) {
            return null;
        } else {
            return Date.newInstance(tempDate.year(), tempDate.month(), 1);
        }
    }

    // 发送提醒邮件
    private void sendFieldEmail() {
        PretechBatchEmailUtil be = new PretechBatchEmailUtil();
        String[] toList = new String[] {UserInfo.getUserEmail()};
        String title = '更新维修合同上一期上上期消费率失败';
        String[] ccList = new String[] {};
        if (System.Test.isRunningTest()) {
            be.successMail('', 1);
        }
        if (emailMessages.size() > 0 && failedCount > 0) {
            be.failedMail(toList, ccList, title,
                          String.join(this.emailMessages, '\n'),
                          totalCount, totalCount - failedCount, failedCount,'',false);
            if(!Test.isRunningTest())
            be.send();
        }
    }
}