LoginSignup
0
0

Salesforce 承認プロセス周りの自動化

Last updated at Posted at 2024-01-19

初めに

  • ビジネスプロセスにおいて、承認を取らないといけないような業務って多々あったりして、それをSalesforceで行うには承認プロセスを使うのが手っ取り早いのです。
  • しかし、この承認プロセス周りの自動化を行おうと思うと結構複雑だったのでメモしておきます。

前提

  • Chatterでの承認が有効化されていること
  • Communityページに公開するレコードに対して承認プロセスが設定されていること

やりたかった自動化1: 承認されたら承認プロセス開始時のChatterポストに承認者として、承認コメントを返信

  • 承認プロセスの管理は、ProcessInstance オブジェクトで管理される
  • 承認コメントは、ProcessInstanceHistoryオブジェクトに格納される
  • 困ったことに、これらのオブジェクトはフローからもApexトリガからもトリガ対象のオブジェクトにすることができない。。

やったこと

  • 結局、承認プロセスに自動値更新で更新された値に対してApexトリガを作った
    • 例えば、対象オブジェクトの状況が変更されたら、、みたいな形

サンプルロジック

  • ProcessDefinitionオブジェクトから対象承認プロセスのIdを取得する
  • 申請者のユーザIdを取得する(今回はテスト環境だったので、1ユーザのみに絞っているが、本来であればProcessInstanceSubmittedByIdを使用するべき)
  • ProcessInstanceオブジェクトとProcessInstanceHistoryオブジェクトをJOINさせ、トリガ対象オブジェクトのレコードIdと承認プロセスIdでクエリする
  • 取得したProcessInstanceHistoryレコードの承認者ユーザId (ActorId)と、申請者Id (SubmittedById)が違う場合、承認者のコメントのため、取得
  • トリガされたレコードの最終更新者が承認者の場合(ワークフローで承認された場合、自動値更新されているはずのため)申請者が投稿したChatterポストを取得し、FeedCommentレコードを新たに作る

ProcessInstanceHistoryオブジェクトをJOINする際は、なぜか StepsAndWorkItemsをSOQLでは指定しないといけない点に注意

SampleApexTrigger
trigger PostChatterApprovalCommentByManager on SOBject (after update) {
    for (CustomObject__c co : Trigger.New) {
        if (co.Status__c == 'Something') {

            // Get Target Approval Process Id
            ProcessDefinition pd = [SELECT Id FROM ProcessDefinition WHERE Name = 'YourApprovalProcessName'];
            // Get Submitter User Id (It is always System Admin User)
            User submittedUser = [SELECT Id FROM User WHERE LastName = 'SubmitterLastName'];

            // In order to get Approver's comment
            ProcessInstance pi = [SELECT Id, TargetObjectId, Status,
                                  (SELECT Comments, ActorId FROM StepsAndWorkItems) FROM ProcessInstance 
                                  WHERE ProcessDefinitionId = :pd.Id AND SubmittedById = :submittedUser.Id AND TargetObjectId = :co.Id];
            String comment;
            Id approverUserId;
            // Get Approver's comment
            for(ProcessInstanceHistory sawi : pi.StepsAndWorkItems) {
                System.debug('ProcessInstanceHistory record - ' + sawi);
                if(sawi.ActorId != submittedUser.Id) {
                    comment = sawi.Comments;
                    approverUserId = sawi.ActorId;
                    break;
                } 
            }
            System.debug(comment);

            // Only post chatter if approver is updated this record
            if(co.LastModifiedById == approverUserId) {
                FeedItem fi = [SELECT Id FROM FeedItem 
                               WHERE CreatedById = :submittedUser.Id AND 
                                     ParentId = :pi.TargetObjectId AND 
                                     Type = 'ApprovalPost'
                               ORDER BY CreatedDate DESC
                               LIMIT 1];
                FeedComment fc = new FeedComment();
                fc.FeedItemId = fi.Id;
                fc.CommentBody = comment;
                fc.CreatedById = approverUserId;
                insert fc;
            }
        }
    }
}

やりたかった自動化2: デフォルトだと承認プロセス開始時のChatterポストがCommunity側に表示されてしまうので、自動で社内ユーザ向けの投稿に変更したい

  • まあ、普通にそんな内部ポストが見えてしまうのはありえません
  • Helpによると、レコードを親にもつ投稿は、参照権限があれば見えてしまうらしい
  • よって、FeedItemVisibility項目をInternalUsersに変更すればOKのはず
  • 承認プロセスによって投稿されたFeedItemレコードに対して、トリガフロー、およびApexトリガ(After Update)は動作しない(ワークフロールール、あるいはコミット後にChatter投稿が実行されるから?これはよくわからなかった)

解決策

  • これはコードは不要で、トリガフローに対して非同期パスを設定すればOKだった

image.png

以上、誰かしらの参考になれば幸いです。
他にも良い方法や間違いがあれば是非是非コメントください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0