トリガー練習例

#トリガー練習例資材
###TR_Asset(Trigger) 
```Apex:(TR_Asset)
trigger TR_Asset on Asset (after insert) {	
	new CL_AssetCloneTriggerHandler().execute();
}
```
###CL_TriggerHandler(Apex) 
```Apex:(CL_TriggerHandler)
public abstract class CL_TriggerHandler {
    public void execute() {
        switch on Trigger.operationType {
            when BEFORE_INSERT  { this.beforeInsert(Trigger.new); }
            when BEFORE_UPDATE  { this.beforeUpdate(Trigger.oldMap, Trigger.newMap); }
            when BEFORE_DELETE  { this.beforeDelete(Trigger.oldMap); }
            when AFTER_INSERT   { this.afterInsert(Trigger.newMap); }
            when AFTER_UPDATE   { this.afterUpdate(Trigger.oldMap, Trigger.newMap); }
            when AFTER_DELETE   { this.afterDelete(Trigger.oldMap); }
            when AFTER_UNDELETE { this.afterUndelete(Trigger.newMap); }
        }
    }

    @TestVisible protected virtual void beforeInsert(List<Sobject> newList) {}
    @TestVisible protected virtual void beforeUpdate(Map<Id, Sobject> oldMap, Map<Id, Sobject> newMap) {}
    @TestVisible protected virtual void beforeDelete(Map<Id, Sobject> oldMap) {}
    @TestVisible protected virtual void afterInsert(Map<Id, Sobject> newMap) {}
    @TestVisible protected virtual void afterUpdate(Map<Id, Sobject> oldMap, Map<Id, Sobject> newMap) {}
    @TestVisible protected virtual void afterDelete(Map<Id, Sobject> oldMap) {}
    @TestVisible protected virtual void afterUndelete(Map<Id, Sobject> newMap) {}

    @TestVisible protected Boolean isFieldValueChanged(SObject oldObject, SObject newObject, SObjectField field) {
        Object oldValue = getFieldValue(oldObject, field);
        Object newValue = getFieldValue(newObject, field);
        return oldValue != newValue;
    }

    @TestVisible protected Object getFieldValue(SObject obj, SObjectField field) {
        Object fieldValue = (obj != null) && (field != null) ? obj.get(field) : null;
        return fieldValue;
    }
}
```
###CL_AssetCloneTriggerHandler(Apex) 
```Apex:(CL_AssetCloneTriggerHandler)
public  with sharing class CL_AssetCloneTriggerHandler extends CL_TriggerHandler {
    /** カスタムException */
    private class CustomException extends Exception {}
    
    /** カスタムExceptionフラグ */
    public static Boolean isExceptionFlg = false;
    
    public override void afterInsert(Map<Id, SObject> newMap) {
        Asset asset = (Asset)newMap.values().get(0);
        Map<Id, Id> cloneIdMap = new Map<Id, Id>();
        
        // 概要：関連レコードコピー
        // 1.保存処理を行った納入商品レコードがコピーレコードであるかを判定する
        if (asset.isClone()) {
            try{
                // カスタムExceptionを投げる
                if (isExceptionFlg) {
                    throw new CustomException();
                }
                
                // Map<納入商品コピー先Id, 納入商品コピー元Id>
                cloneIdMap.put(asset.Id, asset.getCloneSourceId());
                
                // 2．コピー元関連レコードの取得
                Map<Id, Asset> cloneSourceMap = new Map<Id, Asset>(
                    [select 
                        id, 
                        (select id from Sagyoujyouken_Asset__r)
                     from 
                    	Asset 
                     where id in :cloneIdMap.values()
                    ]);
                
                // データ取得：作業条件（Sagyoujyouken__c）
                List<Sagyoujyouken__c> mSagyoJokenList = new List<Sagyoujyouken__c>();
                for (Asset item : cloneSourceMap.values()) {
                    mSagyoJokenList.addAll(item.Sagyoujyouken_Asset__r);
                }
                Map<Id, Sagyoujyouken__c> mSagyoJokenMap = 
                    new Map<Id, Sagyoujyouken__c>((List<Sagyoujyouken__c>)getAllFieldRecordList(Sagyoujyouken__c.SObjectType, mSagyoJokenList));
               
                // データ取得：ファイル（納入商品業務データIDリスト）
                List<Id> idList = new List<Id>();
                for (Id item : cloneSourceMap.keySet()) {
                    idList.add(item);
                }
                
                // データ検索用SOQL文作成
                String strQuery = 
                    'select Id, LinkedEntityId, ContentDocumentId, IsDeleted, SystemModstamp, ShareType, Visibility from ContentDocumentLink where LinkedEntityId = :idList';
                Map<Id, ContentDocumentLink> contentDocumentLinkMap = 
                    new Map<Id, ContentDocumentLink>((List<ContentDocumentLink>)Database.query(strQuery));
                
                // データ取得：ファイル（ContentDocumentLink）IDリスト
                List<Id> contentDocumentLinkIdList = new List<Id>();
                for (Id item : contentDocumentLinkMap.keySet()) {
                    contentDocumentLinkIdList.add(item);
                }
                
                // 3．コピー先関連レコード挿入
                List<SObject> insertList = new List<SObject>();
                
                // コピー元関連レコードを取得する
                Asset cloneSourceAsset = cloneSourceMap.get(cloneIdMap.get(asset.Id));
                
                // コピー先.作業条件 = コピー元.作業条件.clone
                for (Sagyoujyouken__c item : cloneSourceAsset.Sagyoujyouken_Asset__r) {
                    Sagyoujyouken__c cloneFrom = mSagyoJokenMap.get(item.Id);
                    Sagyoujyouken__c cloneTo = cloneFrom.clone(false, true, false, false);
                
                    // コピー先.作業条件.納入商品 = コピー先.納入商品.ID
                    cloneTo.Asset__c = asset.Id;       
                    insertList.add(cloneTo);
                }

                // コピー先.ファイル（ContentDocumentLink） = コピー元.ファイル（ContentDocumentLink）.clone
                for (Id item : contentDocumentLinkIdList) {
                    ContentDocumentLink cloneFrom = contentDocumentLinkMap.get(item);
                    ContentDocumentLink cloneTo = cloneFrom.clone(false, true, false, false);
                    
                    // コピー先.ファイル.LinkedEntityId = コピー先.納入商品.ID
                    cloneTo.LinkedEntityId = asset.Id;
                    
                    insertList.add(cloneTo);
                }
                
                // コピー先関連レコードを挿入する
                if (!insertList.isEmpty()) {
                    insert insertList;
                }
                
            } catch(Exception e) {
                asset.addError(System.Label.TR01_MSG_0001 + e.getMessage());
            }
        }
    }
    
   /**
    * 概要：項目取得
    * @parameter Schema.SObjectType
    * @parameter List<SObject>
    */
    public static List<SObject> getAllFieldRecordList(Schema.SObjectType sObjectType, List<SObject> sObjectList) {
        // 対象オブジェクトのカスタム項目を取得する
        List<String> fieldNameList = new List<String>();
        Map<String,Schema.sObjectField> sObjectFieldMap = sObjectType.getDescribe().fields.getMap();
        for(String fieldName : sObjectFieldMap.keySet()){
            fieldNameList.add(fieldName);
        }
        
        // データ検索用SOQL文作成
        String strQuery = 'select ' + String.join(fieldNameList, ',') + ' from ' + sObjectType.getDescribe().getName() + ' where Id= :sObjectList';
        
        // データを返却する
        return Database.query(strQuery);
    }
}
```