2009年12月25日金曜日

[SFDC]:親が更新されたら子、孫・・・にも反映

要件として親の項目が更新されたら子にも~とか聞いたりします。
 ※逆もありますが

ということで強引に作ってみた。

A.設定
 ・取引先の親取引先を使っています。
 ・実行する際にはフラグを利用しています。
  >チェックして保存したら実行
 ・Database.Batchableを利用して大量データにも対応しています。
 ・先祖のIDを数式で持たせ、その項目に対してLikeで検索して反映対象を取得しています。
  ParentId
  & Parent.ParentId
  & Parent.Parent.ParentId
  ・・・・.ParentId
  ・・・これはひどいww
  これが20個ぐらい続きます。
  ガチでやろうとすると、子を取得して、子を参照する孫を取得して孫を参照(以下略
  となるのですが、面倒なので今回はこのようにしています。

B.SFDC側の設定
 取引先に
  1.実行用のフラグ(batchActionFlg)
  2.さきほどの先祖のIDを連結した数式(pID)
 をカスタム項目として定義

C.Apex

面倒なので、そのままソースを貼ります。
AccountTrigger.trigger
trigger AccountTrigger on Account (Before update) {
 AccountUpdate aupObj = new AccountUpdate();
 for (Account acc : Trigger.new) {
  aupObj.execute(acc);
 }
}
AccountUpdate.cls
/**
 * バッチ呼び出しクラス
 * 実行判定を行う。
 *
 */
public class AccountUpdate {
 public void execute(Account acc) {
  System.debug('■■■■■■AccountUpdate■■■■■■');
  if (acc.batchActionFlg__c) {
   acc.batchActionFlg__c = false;
   AccountSyncBatch job = new AccountSyncBatch(acc);
   ID batchprocessid = Database.executeBatch(job);
  }
 }
}
AccountSyncBatch.cls
/**
 * バッチ
 * 更新対象の取引先を取得し、更新する。
 * 親の種別(Type),評価(Rating)を子に反映させます。
 */
global class AccountSyncBatch implements Database.Batchable{

    // 更新した親
    Account parentObj = null;

    // コンストラクタ
    public AccountSyncBatch(Account p) {
     System.debug('■■■■■■AccountSyncBatch コンストラクタ■■■■■■');
     this.parentObj = p;
    }
    
    global database.querylocator start(Database.BatchableContext bc){
     System.debug('■■■■■■AccountSyncBatch start■■■■■■');
     System.debug('□対象のObj start :' + parentObj);
     System.debug('■■検索SOQL :' + 'select Id from Account where pID__c Like \'%' + String.valueOf(parentObj.Id).substring(0,15) + '%\'');
     // 親IDが含まれる 数式は15桁IDのためIDをStringにキャストして15桁を切り出し検索条件とする。
        return Database.getQueryLocator('select Id from Account where pID__c Like \'%' + String.valueOf(parentObj.Id).substring(0,15) + '%\'');
    }

    global void execute(Database.BatchableContext bc, SObject[] objects){
     System.debug('■■■■■■AccountSyncBatch execute■■■■■■');
     System.debug('□対象のObj execute :' + parentObj);
        Account[] accns = new Account[]{};
        for(SObject s : objects){
            Account a = (Account)s;
            a.Rating = parentObj.Rating; // 評価をセット
            a.Type = parentObj.Type; // 種別をセット
            accns.add(a);
            System.debug('■ update entity:' + a);
        }
        system.debug('□□□□□□iterator done.□□□□□□ ');
        update accns;
    }
    
    global void finish(Database.BatchableContext bc){
        system.debug('□□□□□□all done.□□□□□□ ');
    }
}

これで、batchActionFlgをTrueにして保存すれば動きます。
テストメソッドとか、データローダでドカンと保存したらどうなるのよ!とかは考慮してません。
長くなりました。

もっといい実装方法があったらコメント頂けると幸いです。

0 件のコメント: