高章伟
2023-03-02 e3c02c03dd2de442bbced87236f60a13a1cd154e
force-app/main/default/classes/PCLLostProduct2AssetHandler.cls
@@ -1,229 +1,233 @@
/*
* 这个触发器需要更新完历史数据后才能部署,
* 一、删除时调用方法,传入OLD失单型号ID:
*       1、找到是这个失单型号的所有保有设备,删除掉;
*       2、这个需要做成共通方法,传进来失单报告,然后以便三、1使用;
* 二、插入时调用方法,传入NEW失单型号:
* 这个也需要写成共通方法,以供三、2使用;
*       1、前提:
*          1)失单型号的报告是失单报告或者部分失单报告;
*          2)失单型号的询价所在医院的记录类型是HP;
*       2、找到插入所有失单型号中有失单产品型号的数据;
*       3、根据数量生成保有设备,把这个保有设备的型号设置为这个保有设备;
* 三、更新:
*       1、删除:
*          1)从有产品型号更新为无产品型号;
*        2)调用一的方法,删除掉保有设备;
*       2、插入:
*          1)从无产品型号更新为有产品型号;
*          2)调用二的方法插入数据;
*       3、更新:
*          1)如果产品或者数量发生了变化,而且符合失单型号对报告的需求;
*          2)调用四的方法更新保有设备;
* 四、更新调用,传入New失单型号 list以及map;
*      1、找到这个失单型号ID的所有失单保有设备;
*       2、循环每个失单保有设备的失单数量:
*          1)先用在失单数量下的保有设备,对比一下产品,有变化加入更新数据行列;
*          2)用完这个失单下的所有保有设备,插入失单设备;
*       3、循环完如果这个失单报告还有保有设备,记录下来以供删除;
*      4、插入失单设备;
*      5、更新设备;
*      6、删除保有设备;
* */
 * 这个触发器需要更新完历史数据后才能部署,
 * 一、删除时调用方法,传入OLD失单型号ID:
 *       1、找到是这个失单型号的所有保有设备,删除掉;
 *       2、这个需要做成共通方法,传进来失单报告,然后以便三、1使用;
 * 二、插入时调用方法,传入NEW失单型号:
 * 这个也需要写成共通方法,以供三、2使用;
 *       1、前提:
 *          1)失单型号的报告是失单报告或者部分失单报告;
 *          2)失单型号的询价所在医院的记录类型是HP;
 *       2、找到插入所有失单型号中有失单产品型号的数据;
 *       3、根据数量生成保有设备,把这个保有设备的型号设置为这个保有设备;
 * 三、更新:
 *       1、删除:
 *          1)从有产品型号更新为无产品型号;
 *        2)调用一的方法,删除掉保有设备;
 *       2、插入:
 *          1)从无产品型号更新为有产品型号;
 *          2)调用二的方法插入数据;
 *       3、更新:
 *          1)如果产品或者数量发生了变化,而且符合失单型号对报告的需求;
 *          2)调用四的方法更新保有设备;
 * 四、更新调用,传入New失单型号 list以及map;
 *      1、找到这个失单型号ID的所有失单保有设备;
 *       2、循环每个失单保有设备的失单数量:
 *          1)先用在失单数量下的保有设备,对比一下产品,有变化加入更新数据行列;
 *          2)用完这个失单下的所有保有设备,插入失单设备;
 *       3、循环完如果这个失单报告还有保有设备,记录下来以供删除;
 *      4、插入失单设备;
 *      5、更新设备;
 *      6、删除保有设备;
 * */
public without sharing class PCLLostProduct2AssetHandler extends Oly_TriggerHandler {
    private Map<Id, PCLLostProduct__c> newMap;
    private Map<Id, PCLLostProduct__c> oldMap;
    private List<PCLLostProduct__c> newList;
    private List<PCLLostProduct__c> oldList;
    public PCLLostProduct2AssetHandler() {
        this.newMap = (Map<Id, PCLLostProduct__c>) Trigger.newMap;
        this.oldMap = (Map<Id, PCLLostProduct__c>) Trigger.oldMap;
        this.newList = (List<PCLLostProduct__c>) Trigger.new;
        this.oldList = (List<PCLLostProduct__c>) Trigger.old;
    }
    protected override void afterUpdate() {
        updateProduct2Asset(newList,oldMap);
    }
   private Map<Id, PCLLostProduct__c> newMap;
   private Map<Id, PCLLostProduct__c> oldMap;
   private List<PCLLostProduct__c> newList;
   private List<PCLLostProduct__c> oldList;
   public PCLLostProduct2AssetHandler() {
      this.newMap = (Map<Id, PCLLostProduct__c>) Trigger.newMap;
      this.oldMap = (Map<Id, PCLLostProduct__c>) Trigger.oldMap;
      this.newList = (List<PCLLostProduct__c>) Trigger.new;
      this.oldList = (List<PCLLostProduct__c>) Trigger.old;
   }
   protected override void afterUpdate() {
      updateProduct2Asset(newList,oldMap);
   }
    protected override void afterInsert() {
        insertLostAsset(newList);
    }
    protected override void beforedelete() {
        deleteLostAsset(oldMap.keySet());
    }
   protected override void afterInsert() {
      insertLostAsset(newList);
   }
   protected override void beforedelete() {
      deleteLostAsset(oldMap.keySet());
   }
    private void deleteLostAsset( set<id> oldIDList){
        list<Asset> delAstList = new list<Asset>();
        if(oldIDList.size()> 0){
            delAstList =
                [select id
                 from asset
                 where LostProduct__c in: oldIDList];
        }
        if(delAstList.size() > 0){
            delete delAstList;
        }
    }
   private void deleteLostAsset( set<id> oldIDList){
      list<Asset> delAstList = new list<Asset>();
      if(oldIDList.size()> 0) {
         delAstList =
         [select id
          from asset
          where LostProduct__c in: oldIDList];
      }
      if(delAstList.size() > 0) {
         delete delAstList;
      }
   }
    private void insertLostAsset(List<PCLLostProduct__c> newList){
        list<asset> InsertAssetlist = new list<asset>();
        for (PCLLostProduct__c LostProduct : newList) {
            // 部分失单或失单报告型号而且询价上的医院真是医院
            if ((LostProduct.lcrRecordType_DevName__c == 'PCL_Lost_report' ||
                 LostProduct.lcrRecordType_DevName__c == 'PCL_PartLost_report'
                ) && LostProduct.HP_RecordType_DevName__c == 'HP'
                && string.isNotBlank(LostProduct.LostProduct__c))
            {
                for(integer i = 0;i <integer.valueof(lostProduct.Quantity__c);i++){
                    InsertAssetlist.add(buildAsset (lostProduct));
                }
            }
        }
        if(InsertAssetlist.size() > 0){
            insert InsertAssetlist;
        }
    }
    private void updateProduct2Asset(List<PCLLostProduct__c> newList,
        Map<Id, PCLLostProduct__c> oldMap){
        // 要被删除数据的ID的set
        set<id> oldDelIDList = new set<id>();
        // 要被插入的保有设备的失单型号的new的list
        list<PCLLostProduct__c> newInsertList =
            new list<PCLLostProduct__c>();
        //需要走更新流程的失单型号
        List<PCLLostProduct__c> newUpdateList =
            new List<PCLLostProduct__c>();
        //需要走更新流程的失单型号IDSet
        set<ID> newUpIDSet = new set<ID>();
   private void insertLostAsset(List<PCLLostProduct__c> newList){
      list<asset> InsertAssetlist = new list<asset>();
      for (PCLLostProduct__c LostProduct : newList) {
         // 部分失单或失单报告型号而且询价上的医院真是医院
         if ((LostProduct.lcrRecordType_DevName__c == 'PCL_Lost_report' ||
              LostProduct.lcrRecordType_DevName__c == 'PCL_PartLost_report'
              ) && LostProduct.HP_RecordType_DevName__c == 'HP'
             && string.isNotBlank(LostProduct.LostProduct__c))
         {
            for(integer i = 0; i <integer.valueof(lostProduct.Quantity__c); i++) {
               InsertAssetlist.add(buildAsset (lostProduct));
            }
         }
      }
        // for循环,判断哪些需要增加、删除或更新
        for( PCLLostProduct__c NewLsP : newList){
            PCLLostProduct__c oldLsP = oldMap.get(NewLsP.id);
            //1、产品型号有值变为产品型号为空,需要删除;
            if(string.isNotBlank(oldLsP.LostProduct__c) &&
                string.isBlank(NewLsP.LostProduct__c)){
                oldDelIDList.add(NewLsP.id);
            }
            //2、产品型号为空变为产品型号有值,需要插入失单保有设备;
            if(string.isBlank(oldLsP.LostProduct__c) &&
                string.isNotBlank(NewLsP.LostProduct__c)){
                newInsertList.add(NewLsP);
            }
            // 3、如果
            //   1)新失单型号所在的报告是失单报告或者部分失单报告;
            //   2)所在询价的医院是医院
            //   3)失单型号产品不为空;
            //   4)产品更改或者数量更改;
            //  那么是需要更新的数据
            if ((NewLsP.lcrRecordType_DevName__c == 'PCL_Lost_report'
                || NewLsP.lcrRecordType_DevName__c == 'PCL_PartLost_report'
                ) && NewLsP.HP_RecordType_DevName__c == 'HP'
                && string.isNotBlank(NewLsP.LostProduct__c)
                && ( NewLsP.LostProduct__c != oldLsP.LostProduct__c
                    || NewLsP.Quantity__c != oldLsP.Quantity__c
                    )
                )
            {
                newUpdateList.add(NewLsP);
                newUpIDSet.add(NewLsP.Id);
            }
      if(InsertAssetlist.size() > 0) {
         insert InsertAssetlist;
      }
   }
   private void updateProduct2Asset(List<PCLLostProduct__c> newList,
                                    Map<Id, PCLLostProduct__c> oldMap){
      // 要被删除数据的ID的set
      set<id> oldDelIDList = new set<id>();
      // 要被插入的保有设备的失单型号的new的list
      list<PCLLostProduct__c> newInsertList =
         new list<PCLLostProduct__c>();
      //需要走更新流程的失单型号
      List<PCLLostProduct__c> newUpdateList =
         new List<PCLLostProduct__c>();
      //需要走更新流程的失单型号IDSet
      set<ID> newUpIDSet = new set<ID>();
        }
      // for循环,判断哪些需要增加、删除或更新
      for( PCLLostProduct__c NewLsP : newList) {
         PCLLostProduct__c oldLsP = oldMap.get(NewLsP.id);
         //1、产品型号有值变为产品型号为空,需要删除;
         if(string.isNotBlank(oldLsP.LostProduct__c) &&
            string.isBlank(NewLsP.LostProduct__c)) {
            oldDelIDList.add(NewLsP.id);
         }
         //2、产品型号为空变为产品型号有值,需要插入失单保有设备;
         if(string.isBlank(oldLsP.LostProduct__c) &&
            string.isNotBlank(NewLsP.LostProduct__c)) {
            newInsertList.add(NewLsP);
         }
         // 3、如果
         //   1)新失单型号所在的报告是失单报告或者部分失单报告;
         //   2)所在询价的医院是医院
         //   3)失单型号产品不为空;
         //   4)产品更改或者数量更改;
         //  那么是需要更新的数据
         if ((NewLsP.lcrRecordType_DevName__c == 'PCL_Lost_report'
              || NewLsP.lcrRecordType_DevName__c == 'PCL_PartLost_report'
              ) && NewLsP.HP_RecordType_DevName__c == 'HP'
             && string.isNotBlank(NewLsP.LostProduct__c)
             && ( NewLsP.LostProduct__c != oldLsP.LostProduct__c
                  || NewLsP.Quantity__c != oldLsP.Quantity__c
                  )
             )
         {
            newUpdateList.add(NewLsP);
            newUpIDSet.add(NewLsP.Id);
         }
        // 删除数据
        if(oldDelIDList.size() > 0){
            deleteLostAsset(oldDelIDList);
        }
        // 插入数据
        if(newInsertList.size()>0){
            insertLostAsset(newInsertList);
        }
        // 更新数据
        if(newUpdateList.size()>0){
            updateLsAHandler(newUpdateList,newUpIDSet);
        }
      }
    }
      // 删除数据
      if(oldDelIDList.size() > 0) {
         deleteLostAsset(oldDelIDList);
      }
      // 插入数据
      if(newInsertList.size()>0) {
         insertLostAsset(newInsertList);
      }
      // 更新数据
      if(newUpdateList.size()>0) {
         updateLsAHandler(newUpdateList,newUpIDSet);
      }
    private void updateLsAHandler(List<PCLLostProduct__c> newList,set<Id> newIDSet) {
   }
        //需要插入和更新的保有设备数据
        list<asset> upsertAstList = new List<asset>();
   private void updateLsAHandler(List<PCLLostProduct__c> newList,set<Id> newIDSet) {
        //需要删除的保有设备数据
        list<asset> delAstList = new List<asset>();
      //需要插入和更新的保有设备数据
      list<asset> upsertAstList = new List<asset>();
        // 构建map,以便判断是否需要删除或者更新已有保有设备;
        map<id, list<asset>> LsPID2Asset = new map<id, list<asset>>();
      //需要删除的保有设备数据
      list<asset> delAstList = new List<asset>();
        // 检索这个失单型号下面所有保有项目
        list<asset> oldAssetList = [
                select id, LostProduct__c, Product2Id,
                    Status, Asset_Owner__c, IsCompetitorProduct
                from asset
                where LostProduct__c in : newIDSet
                 ];
      // 构建map,以便判断是否需要删除或者更新已有保有设备;
      map<id, list<asset> > LsPID2Asset = new map<id, list<asset> >();
        for(asset tempAst: oldAssetList){
            list<asset> tempAstList = new List<asset>();
            if(LsPID2Asset.containsKey(tempAst.LostProduct__c)){
                tempAstList = LsPID2Asset.get(tempAst.LostProduct__c);
            }
            tempAstList.add(tempAst);
            LsPID2Asset.put(tempAst.LostProduct__c, tempAstList);
        }
        // 循环现有失单型号,
        for(PCLLostProduct__c tempLsP : newList){
            // 获取当前失单型号的所有失单保有设备
             list<asset> tempAstList = LsPID2Asset.get( tempLsP.id );
            for(integer i = 0; i < integer.valueOf(tempLsP.Quantity__c); i++){
                asset tempAst = buildAsset(tempLsP);
                // 如果当前失单型号还有值,那么获取一个更新,否则就插入
                if(tempAstList !=null && tempAstList.size() > 0){
                    asset oldAst = tempAstList.remove(0);
                    // 如果发生变化以后,才需要更新
                    if(tempAst.Product2Id != oldAst.Product2Id ||
                        tempAst.Status != oldAst.Status ||
                        tempAst.Asset_Owner__c != oldAst.Asset_Owner__c ||
                        tempAst.IsCompetitorProduct != oldAst.IsCompetitorProduct
                        ){
                        tempAst.id = oldAst.id;
                        upsertAstList.add(tempAst);
                    }
                }
                else{
                    upsertAstList.add(tempAst);
                }
            }
            // 如果还有多出来的,那么这些就是需要删除的失单保有设备
            if(tempAstList !=null && tempAstList.size()> 0){
                delAstList.addAll(tempAstList);
            }
        }
        // 插入或者更新失单保有设备
        if(upsertAstList.size() > 0){
            upsert upsertAstList;
        }
        // 删除多的失单保有设备
        if(delAstList.size() > 0){
            delete delAstList;
        }
    }
      // 检索这个失单型号下面所有保有项目
      list<asset> oldAssetList = [
         select id, LostProduct__c, Product2Id,
         Status, Asset_Owner__c, IsCompetitorProduct
         from asset
         where LostProduct__c in : newIDSet
      ];
    private asset buildAsset(PCLLostProduct__c LostProduct){
        Asset Ast = new Asset(
                        Name = '*',
                        Product2Id = LostProduct.LostProduct__c,
                        Opportunity__c = LostProduct.Opportunity__c,
                        InstallDate = LostProduct.Submit_Day__c,
                        Hospital__c = LostProduct.LostHP__c,
                        Department_Class__c = LostProduct.LostDepartment_Class__c,
                        AccountId = LostProduct.LostAccount__c,
                        Status = '使用中',
                        Asset_Owner__c = '病院資産',
                        IsCompetitorProduct = True,
                        LostProduct__c = LostProduct.id
                    );
        return ast;
    }
      for(asset tempAst: oldAssetList) {
         list<asset> tempAstList = new List<asset>();
         if(LsPID2Asset.containsKey(tempAst.LostProduct__c)) {
            tempAstList = LsPID2Asset.get(tempAst.LostProduct__c);
         }
         tempAstList.add(tempAst);
         LsPID2Asset.put(tempAst.LostProduct__c, tempAstList);
      }
      // 循环现有失单型号,
      for(PCLLostProduct__c tempLsP : newList) {
         // 获取当前失单型号的所有失单保有设备
         list<asset> tempAstList = LsPID2Asset.get( tempLsP.id );
         for(integer i = 0; i < integer.valueOf(tempLsP.Quantity__c); i++) {
            asset tempAst = buildAsset(tempLsP);
            // 如果当前失单型号还有值,那么获取一个更新,否则就插入
            if(tempAstList !=null && tempAstList.size() > 0) {
               asset oldAst = tempAstList.remove(0);
               // 如果发生变化以后,才需要更新
               if(tempAst.Product2Id != oldAst.Product2Id ||
                  tempAst.Status != oldAst.Status ||
                  tempAst.Asset_Owner__c != oldAst.Asset_Owner__c ||
                  tempAst.IsCompetitorProduct != oldAst.IsCompetitorProduct
                  ) {
                  tempAst.id = oldAst.id;
                  upsertAstList.add(tempAst);
               }
            }
            else{
               upsertAstList.add(tempAst);
            }
         }
         // 如果还有多出来的,那么这些就是需要删除的失单保有设备
         if(tempAstList !=null && tempAstList.size()> 0) {
            delAstList.addAll(tempAstList);
         }
      }
      // 插入或者更新失单保有设备
      if(upsertAstList.size() > 0) {
         upsert upsertAstList;
      }
      // 删除多的失单保有设备
      if(delAstList.size() > 0) {
         delete delAstList;
      }
   }
   private asset buildAsset(PCLLostProduct__c LostProduct){
      Asset Ast = new Asset(
         Name = '*',
         // CHAN-CCR6MW gzw 【委托】【保有设备】保有设备发货日逻辑 start
         Posting_Date__c = Date.today(),
         // CHAN-CCR6MW gzw 【委托】【保有设备】保有设备发货日逻辑 end
         Product2Id = LostProduct.LostProduct__c,
         Opportunity__c = LostProduct.Opportunity__c,
         InstallDate = LostProduct.Submit_Day__c,
         Hospital__c = LostProduct.LostHP__c,
         Department_Class__c = LostProduct.LostDepartment_Class__c,
         AccountId = LostProduct.LostAccount__c,
         Status = '使用中',
         Asset_Owner__c = '病院資産',
         IsCompetitorProduct = True,
         LostProduct__c = LostProduct.id
         );
      return ast;
   }
}