« メールの送受信の制限 | メイン | テストメソッドがアクセスできるデータが変わりました »

2012年2月27日 (月)

Apex共有で所有者と同じロールへレコードを共有する方法

Salesforceでは、組織の共有設定が「非公開」に設定されている場合、
同じロールに属するユーザが所有するレコードは参照できません。
営業部ロールにAさんとBさんが属していた場合、Aさんが所有するレコードをBさんは参照できない

一方で、「同じロールに属するユーザが所有するレコードは参照できるようにしたい
営業部の誰かが所有するレコードは、営業部全員で参照できるようにしたい)」
という要望を頂くことは結構多いような気がします。

この要望は、↓の共有ルールを作成すれば実現できます。
所有者の所属:「営業部ロール」
共有先:「営業部ロール」
アクセス権:「参照のみ」

但し、この方法だと、このルールを適用するロールの数だけ共有ルールを作成しなければなりません。また、ロールの追加や変更の度に、共有ルールを追加・変更しなければなりません。

大規模な組織などで、ロールの数が多い場合や、ロールの追加・変更が多い場合は、
下記で紹介する方法で、トリガからApex共有を使って、自動的に対応するロールにレコードを共有すると良いでしょう。

トリガでApex共有を使って、レコード共有する方法

1. トリガを作成するオブジェクトに、Apex共有の理由を作成

理由表示ラベルと理由名を設定(どちらも任意の名称でOK)して、Apex共有の理由を作成します。

ここでは、
理由表示ラベル:所有者のロールへの共有
理由名:OwnerRoleSharingReason
と設定します。

20120227_1

2. トリガ作成

オブジェクトに所有者のロールへレコードを共有するトリガを作成します。
ここでは、Item__cというカスタムオブジェクトに作成する場合のソースコードを記載します。

Trigger ShareItemTrigger on Item__c (after insert, after update) {
  // レコードIDリストの作成
  // 所有者IDリストの作成
  List<ID> recordIdList = new List<ID>();
  List<ID> ownerIdList = new List<ID>();
  for(Item__c item : Trigger.new){
    recordIdList.add(item.Id);
    ownerIdList.add(item.OwnerId);
  }

  // 共有レコード追加リストの作成の
  // 共有先ユーザ/グループの設定のところで、
  // 所有者IDに対応するグループIDを取得したいので、
  // 「所有者ID-ロールID マップ」と
  // 「ロールID-グループID マップ」を作成する
  //
  // 所有者ID-ロールID マップの作成
  Map<Id, Id> ownerIdMap = new Map<Id, Id>();
  for(User u : [Select Id, UserRoleId From User 
                Where Id = :ownerIdList]) {
    ownerIdMap.put(u.Id, u.UserRoleId);
  }

  // ロールID-グループID マップの作成
  Map<Id, Id> roleIdMap = new Map<Id, Id>();
  for(Group grp : 
    [Select Id, RelatedId From Group 
     Where RelatedId = :ownerIdMap.values() 
     and Type = 'Role']) {
     roleIdMap.put(grp.RelatedId, grp.Id);
  }

  // 共有レコード追加リストの作成
  // (共有オブジェクトに追加するレコードを作成する)
  List<Item__Share> addShareList 
    = new List<Item__Share>();
  for(Item__c item : Trigger.new) {
    Item__Share shareObj = new Item__Share();

    // 共有レコードID
    shareObj.ParentId = item.Id;

    // 共有先ユーザ/グループ
    // (所有者のロールに対応するグループIDを設定)
    shareObj.UserOrGroupId = 
      roleIdMap.get(ownerIdMap.get(item.OwnerId)); 

    // アクセス権限
    // 参照のみ : read
    // 参照・更新 : edit
    shareObj.AccessLevel = 'read';
    
    // 共有の理由
    shareObj.RowCause = 
      Schema.Item__Share.RowCause.OwnerRoleSharingReason__c;

    addShareList.add(shareObj);
  }

  // 共有レコード削除リストの作成
  List<Item__Share> delShareList =
    [Select Id From Item__Share 
     Where ParentId = :recordIdList 
     and RowCause = 
     :Schema.Item__Share.RowCause.OwnerRoleSharingReason__c];

  try {
    // 共有の理由が「所有者のロールへの共有」である
    // 共有レコードを削除してから、追加する
    delete delShareList;
    insert addShareList;
  }
  catch(System.DmlException e) {  
  }
}

トリガ作成後に、レコードを追加・更新すると、所有者のロールにレコードが共有されるようになります。

レコードの詳細画面で「共有」を押下すると、↓のように、所有者のロールへ共有されていることが分かります。

20120227_2

コメント

コメントを投稿

コメントは記事の投稿者が承認するまで表示されません。

採用情報

株式会社フレクトでは、事業拡大のため、
・Salesforce/Force.comのアプリケーション開発
・HerokuやAWSなどのクラウドプラットフォーム上
でのWebアプリケーション開発
エンジニア、マネージャーを募集中です。

未経験でも、これからクラウドをやってみたい方、
是非ご応募下さい。

フレクト採用ページへ

会社紹介

  • 株式会社フレクトは、
      ・認定コンサルタント
      ・認定上級デベロッパー
      ・認定デベロッパー
    が在籍している、セールスフォースパートナーです。
    また、heroku partnersにも登録されています。
    herokuパートナー
    株式会社フレクト
    Salesforce/Force.com
    導入支援サービス
    弊社の認定プロフェッショナルが支援致します。
    ・Visualforce/Apexによるアプリ開発
    ・Salesforceと連携するWebアプリ開発
    も承っております。
    セールスフォースご検討の際は、
    お気軽にお問合せください。

Twitter

リファレンス

■Developer's Guide(リファレンス)
・Apex  HTML | PDF | 日本語PDF | ガバナ制限
・Visualforce  HTML | PDF
・Web Services API  HTML | PDF | 日本語PDF
・Bulk API  HTML | PDF
・REST API  HTML | PDF | 日本語PDF
・Metadata API  HTML | PDF
・Migration Tool  HTML | PDF
・AJAX Toolkit  HTML | PDF
・Data Loader PDF | 日本語PDF

■早見表 (日本語)
数式
Apex
Visualforce
Web Services API
Chatter