Salesforce Loyalty Managementのカスタマイズ:ApexとAPIを活用した開発者向けガイド

役割:Salesforce 開発者


背景と応用シーン

顧客ロイヤルティは、現代のビジネスにおいて、顧客維持率を高め、顧客生涯価値 (LTV: Lifetime Value) を最大化するための重要な戦略です。Salesforce Loyalty Management は、ポイントの付与・交換、会員ランク管理、特典提供など、包括的なロイヤルティプログラムを構築・管理するための強力なプラットフォームを提供します。

標準機能だけでも多くの要件を満たすことができますが、ビジネスには独自の複雑なルールが存在することが少なくありません。例えば、以下のようなシナリオでは、開発者によるカスタマイズが必要となります。

  • 複雑なポイント計算ロジック:特定の商品カテゴリやキャンペーン期間、顧客セグメントに応じて、動的にポイント付与率を変更する。
  • 外部システムとのリアルタイム連携:POS (Point of Sale) システムや Eコマースサイトでの購入完了と同時に、リアルタイムでポイントを付与する。
  • カスタムUIの構築:Experience Cloud サイトやモバイルアプリに、会員の現在のポイント、ランク、利用可能な特典などを表示するカスタムの Lightning Web Components (LWC) を実装する。
  • バッチ処理による大量データ連携:夜間に一日分の取引データを一括で取り込み、ポイントを計算・付与する。

本記事では、Salesforce 開発者の視点から、Loyalty Management のデータモデルとプロセスを理解し、Apex や API を活用してこれらの高度な要件を実現する方法について詳しく解説します。

原理説明

Loyalty Management のカスタマイズを始める前に、その中核となるデータモデルとプロセスの流れを理解することが不可欠です。

主要なオブジェクト

Loyalty Management は、ロイヤルティプログラムの情報を格納するために、いくつかの標準オブジェクトを使用します。

  • LoyaltyProgram (ロイヤルティプログラム): プログラム全体の定義(名称、通貨など)を管理します。
  • LoyaltyProgramMember (ロイヤルティプログラム会員): プログラムに参加している顧客(取引先責任者または個人取引先)を表します。
  • LoyaltyTierGroup (ロイヤルティランクグループ) と LoyaltyTier (ロイヤルティランク): 「ブロンズ」「シルバー」「ゴールド」といった会員ランクの階層を定義します。
  • TransactionJournal (取引ジャーナル): ポイントの増減を引き起こすすべての活動(購入、返品、紹介など)を記録するオブジェクトです。これはロイヤルティ処理の入力となります。
  • LoyaltyLedger (ロイヤルティ台帳): TransactionJournal の処理結果として、会員のポイント残高を記録するオブジェクトです。これは結果であり、直接操作することは推奨されません。

処理フロー

基本的なポイント処理は、以下の流れで実行されます。

  1. イベント発生:顧客が商品を購入するなど、ポイント変動のトリガーとなるイベントが発生します。
  2. TransactionJournal の作成:開発者は、このイベント情報(購入金額、会員ID、取引日時など)をもとに TransactionJournal レコードを作成します。これは Apex、API、またはデータローダー経由で行われます。
  3. プロセスの起動:TransactionJournal が作成されると、事前に設定されたロイヤルティプログラムプロセスが起動します。このプロセスは通常、Flow で構築されます。
  4. ルールの適用と計算:Flow 内で、「購入金額100円ごとに1ポイント」といったルールが適用され、付与・減算されるポイント数が計算されます。
  5. LoyaltyLedger の更新:計算結果に基づき、システムが自動的に LoyaltyLedger レコードを作成または更新し、会員のポイント残高が変更されます。同時に、ランクアップの条件を満たしているかどうかの判定も行われます。

開発者の主な役割は、ステップ2の TransactionJournal を正確に作成すること、そして標準の Flow では実現不可能な複雑なロジックを Invocable Apex (呼び出し可能な Apex) として実装し、Flow から呼び出すことです。また、外部システムとの連携には Connect API を活用します。

示例代码

ここでは、開発者が直面する一般的なシナリオとして、「Apex を使用してプログラムに新しい会員を登録し、取引ジャーナルを作成する」方法を Salesforce 公式ドキュメントに基づいたコードで示します。

シナリオ1:Connect API を使用して会員をプログラムに登録する

外部システムやカスタムUIから顧客をロイヤルティプログラムに登録する場合、Connect API を利用するのが最も安全で効率的です。以下の Apex コードは、特定の取引先責任者を指定したプログラムに登録する例です。

// 新しい会員を登録するためのメソッド
public static void enrollMember(Id contactId, String programName) {
    // 登録リクエストの入力オブジェクトを作成
    ConnectApi.LoyaltyProgramMemberInput memberInput = new ConnectApi.LoyaltyProgramMemberInput();
    memberInput.memberType = 'Individual'; // 会員種別を「個人」に設定
    memberInput.memberId = contactId; // 関連付ける取引先責任者のID
    memberInput.enrollmentDate = System.now(); // 登録日を現在の日時に設定
    memberInput.canReceivePromotions = true; // プロモーションの受信を許可
    memberInput.canReceivePartnerPromotions = false; // パートナープロモーションは拒否

    try {
        // ConnectApi を呼び出して会員をプログラムに登録
        // 第1引数: プログラムの Developer Name
        // 第2引数: 登録情報を含む入力オブジェクト
        ConnectApi.LoyaltyProgramMemberOutput result = ConnectApi.LoyaltyManagement.enrollInProgram(programName, memberInput);

        // 結果をデバッグログに出力
        System.debug('Successfully enrolled contact ' + contactId + ' into program ' + programName);
        System.debug('New Loyalty Program Member Id: ' + result.memberId);

    } catch (ConnectApi.ConnectApiException e) {
        // エラーハンドリング
        System.debug('Error enrolling member: ' + e.getMessage());
        System.debug('Status Code: ' + e.getHttpStatusCode());
        System.debug('Error Code: ' + e.getErrorCode());
    }
}

注釈:このコードは ConnectApi.LoyaltyManagement 名前空間の enrollInProgram メソッドを使用しています。これにより、関連するすべての設定がバックグラウンドで適切に処理され、手動で `LoyaltyProgramMember` レコードを作成するよりも安全です。

シナリオ2:Apex で購入イベントの取引ジャーナルを作成する

顧客が10,000円の買い物をしたと仮定し、その取引を記録するための TransactionJournal レコードを作成します。このレコードが後続の Flow プロセスによって処理されます。

// 購入イベントに基づいて取引ジャーナルを作成するメソッド
public static void createPurchaseJournal(Id loyaltyProgramMemberId, Id loyaltyProgramId) {
    // 登録された会員のロイヤルティ通貨を取得するためのSOQLクエリ
    LoyaltyProgramCurrency lpc = [
        SELECT Id, Name FROM LoyaltyProgramCurrency
        WHERE LoyaltyProgramId = :loyaltyProgramId
        AND IsActive = true
        LIMIT 1
    ];

    // 取引ジャーナルオブジェクトのインスタンスを作成
    TransactionJournal tj = new TransactionJournal();

    // 必須項目を設定
    tj.LoyaltyProgramId = loyaltyProgramId; // 関連するロイヤルティプログラムのID
    tj.JournalTypeId = getJournalTypeId('Accrual'); // ジャーナル種別(ポイント付与)
    tj.JournalSubTypeId = getJournalSubTypeId('Purchase'); // ジャーナルサブ種別(購入)
    tj.Status = 'Pending'; // 状態を「保留中」に設定。Flowが処理すると「Processed」に変わる
    tj.ActivityDate = System.now(); // 活動日
    tj.TransactionDate = System.now(); // 取引日

    // ポイント計算の元となる情報を設定
    tj.TransactionAmount = 10000; // 取引金額
    tj.AssociatedLoyaltyProgramMemberId = loyaltyProgramMemberId; // 関連する会員のID
    tj.Points = null; // ポイント数はFlowが計算するため、ここでは設定しない
    tj.IssuingLoyaltyProgramCurrencyId = lpc.Id; // ポイントの通貨ID

    try {
        // DML操作でレコードを挿入
        insert tj;
        System.debug('Transaction Journal created successfully with Id: ' + tj.Id);
    } catch (DmlException e) {
        // エラーハンドリング
        System.debug('Error creating Transaction Journal: ' + e.getMessage());
    }
}

// ヘルパーメソッド:ジャーナル種別IDを取得
private static Id getJournalTypeId(String typeName) {
    return [SELECT Id FROM JournalType WHERE Name = :typeName LIMIT 1].Id;
}

// ヘルパーメソッド:ジャーナルサブ種別IDを取得
private static Id getJournalSubTypeId(String subTypeName) {
    return [SELECT Id FROM JournalSubType WHERE Name = :subTypeName LIMIT 1].Id;
}

注釈:このコードの最も重要な点は、Points 項目に値を設定せず、代わりに TransactionAmount のような計算の元となるデータを渡していることです。ビジネスロジック(ポイント計算)は Flow に集約させ、Apex はデータの受け渡しに専念するのがベストプラクティスです。

注意事項

Loyalty Management をカスタマイズする際には、以下の点に注意が必要です。

  • 権限: Apex コードや API を実行するユーザーには、`Loyalty Management` 権限セットライセンスと、それに対応する権限セットが割り当てられている必要があります。また、関連オブジェクト(TransactionJournal, LoyaltyProgramMember 等)への参照・作成権限も必須です。
  • API 制限: Connect API には、他の Salesforce API と同様にガバナ制限(実行回数制限)が存在します。大量のデータを扱うインテグレーションを設計する際は、Bulk API や非同期処理を検討してください。
  • TransactionJournal の不変性: 一度 `Processed` (処理済み) ステータスになった TransactionJournal は、原則として変更・削除すべきではありません。これは監査証跡としての役割を果たすためです。修正が必要な場合は、反対の取引(例:返品によるポイント減算)を行う新しい TransactionJournal を作成します。
  • 非同期処理の活用: 一度に数千件以上の取引を処理する場合、同期処理ではガバナ制限に抵触する可能性が非常に高いです。Batch Apex を使用して TransactionJournal レコードを非同期で作成・挿入することで、大量のデータを安全に処理できます。
  • エラーハンドリング: Connect API の呼び出しや DML 操作は、必ず try-catch ブロックで囲み、エラーが発生した場合の処理を実装してください。失敗したジャーナルを特定し、再処理する仕組みを設けることが重要です。

まとめとベストプラクティス

Salesforce Loyalty Management は、開発者が介入することで、その可能性を最大限に引き出すことができます。最後に、開発者としてのベストプラクティスをまとめます。

  1. まず Flow を活用する: ポイント計算やランクアップといったビジネスロジックは、可能な限り標準機能である Flow で構築します。これにより、メンテナンス性が向上し、ビジネス部門の担当者でもロジックを理解しやすくなります。Apex は、Flow では実現不可能な複雑な計算や外部連携のためにのみ使用します。
  2. TransactionJournal を信頼の源泉とする: ポイントの変動は、必ず TransactionJournal を経由して行います。LoyaltyLedger を直接操作することは避けてください。これにより、すべてのポイント変動に追跡可能な記録が残り、プログラムの透明性と一貫性が保たれます。
  3. UI とインテグレーションには Connect API を使用する: カスタム LWC や外部アプリケーションからロイヤルティデータにアクセスする際は、SOQL で直接クエリするのではなく、Connect API を使用することが推奨されます。API は将来のアップグレードに対応しており、データアクセスロジックをカプセル化してくれます。
  4. スケーラビリティを意識した設計: プログラムが成功すれば、会員数や取引量は急速に増加します。初期設計の段階から、大量データを処理することを想定し、Batch Apex や非同期処理を前提としたアーキテクチャを検討してください。

Salesforce 開発者として、これらの原理とベストプラクティスを理解し、Apex と API を適切に活用することで、標準機能の枠を超えた、企業のビジネス要件に完全に合致する、魅力的でスケーラブルなロイヤルティプログラムを構築することができるでしょう。

コメント