tyoshikawa1106のブログ

- Force.com Developer Blog -

SFDC:Lightningメールと必須チェック判定

Lightningメールと必須チェック判定についてです。Lightnignメールの送信コンポーネントはページレイアウト設定で追加できますが、デフォルトでは件名など一部の項目が必須項目として扱われていません。

f:id:tyoshikawa1106:20200115072039p:plain


必須項目にしたい場合はグローバルアクションのレイアウト設定で設定できます。
f:id:tyoshikawa1106:20200115072340p:plain

f:id:tyoshikawa1106:20200115072212p:plain


件名部分は必須設定しておくと良いと思います。
f:id:tyoshikawa1106:20200115072315p:plain:w300

SFDC:Lightningメールで商談メール送信を試してみました

Lightningメールで商談メール送信を試してみました。商談に関する定形メールを送付できる便利機能です。

f:id:tyoshikawa1106:20200112132512p:plain


最初にやっておくのはこちら。商談に取引先責任者の情報を紐付けます。(標準では取引先責任者ロールのオブジェクトで紐付けますが今回は主となる一人の顧客情報が必要になるのでカスタム項目で用意します。)

f:id:tyoshikawa1106:20200112132904p:plain

データ型はこんな感じ。

  • 主取引先責任者 = 参照項目
  • 顧客名 = 数式
  • 顧客メールアドレス = 数式


Lighntingメールテンプレートでは関連エンティティで商談を選択すれば商談項目を使えるメールテンプレートを作成できます。
f:id:tyoshikawa1106:20200112133259p:plain


参照項目はID値が差し込まれると思うので顧客名などは数式で用意します。
f:id:tyoshikawa1106:20200112133334p:plain


作成したテンプレートは商談のLightningメール送信コンポーネントで呼び出せます。
f:id:tyoshikawa1106:20200112133535p:plain


商談メールのときの注意点として宛先が自動セットできないという点があります。(標準機能としては商談と取引先責任者は紐付きがないため) この問題に対処するため、先程用意した主取引先責任者のメールアドレスを表示できる数式項目を画面に表示しておきます。ユーザはそのアドレスを宛先にコピーして利用します。
f:id:tyoshikawa1106:20200112133819p:plain


宛先が自動セットされないという点については少し手間がかかりますが、コピペできるようになっていればそれほど負担はないと思います。またメールアドレスから候補が一覧で表示されるので入力ミスも防止できます。


LighntingメールではCCやBCCも設定でき、社内ユーザや任意のメールアドレスへの送付も可能です。ただしCCやBCCに社内宛に送付した場合、そちらで開封するとLightningメールの開封履歴に残ってしまうので、基本的には顧客のみに送付するほうが良いと思います。

SFDC:Lightningメールテンプレートの署名の差し込みを試してみました

Lightningメールテンプレートの署名の差し込みを試してみました。共通のメールテンプレートを用意しつつ各ユーザごとに任意の署名を差し込める便利機能です。Winter'20からできるようになったみたいです。

f:id:tyoshikawa1106:20200112124958p:plain

リリースノート

事前の設定

初期設定として私の設定ページの私のメール設定で自分の署名をSalesforceに登録する必要があります。
f:id:tyoshikawa1106:20200112125107p:plain

Lighntingメールテンプレート側の設定

「{{{Sender.Signature}}}」という記述で署名を差し込めますが、差し込み項目の挿入機能で挿入するときは、送信者のメニュー内にあるメールの署名を選択すると差し込めます。
f:id:tyoshikawa1106:20200112125242p:plain


※差し込み項目の挿入機能はこちらのアイコンのこと
f:id:tyoshikawa1106:20200112130945p:plain:w300


差し込み結果はこんな感じです。
f:id:tyoshikawa1106:20200112125419p:plain


この機能を設定してみて気づいたのですが、Lightningメールには開封履歴を確認できる機能があります。この機能はHTMLメールで送付する際に何も表示されない画像をメール内に差し込みその画像が表示されると開封されたという記録が確認できる仕組みのようです。この画像ですが通常は受信者側が気にならないようになっていますが、一部の環境では画像ファイルが自動ダウンロードされないメール設定となっている場合があります。その場合は「☓」アイコンがメール内に表示される挙動となっています。


メールの末尾に差し込まれるため、署名差し込み後は一つ改行をいれておくと☓アイコンが署名の一段下に表示されるので、自動ダウンロードが無効になっている場合でも違和感を多少抑えることができると思います。

メール末尾に署名を差込して、改行がない場合
--------------------------
 署名
--------------------------☒
メール末尾に署名を差込して、改行がある場合
--------------------------
 署名
--------------------------
☒

関連

SFDC:Apex開発で「SandboxPostCopy」インターフェースを試してみました

Apex開発で「SandboxPostCopy」インターフェースを試してみました。SandboxPostCopyインターフェースはSandboxを作成もしくは更新時に任意のApex処理を実行できる機能です。

f:id:tyoshikawa1106:20191217184348p:plain

SandboxPostCopy インターフェース


今回は数式項目内で現在の組織が本番環境かSandbox組織かを判別するためのフラグをカスタム設定で用意し、SandboxPostCopyの処理でチェックをオフにする用途で利用してみました。

カスタム設定を用意

用意したカスタム設定はこちら。チェックボックス項目を保持するだけのシンプルな設定です。
f:id:tyoshikawa1106:20191217184812p:plain

f:id:tyoshikawa1106:20191217184931p:plain

Apexコード

開発者ガイドに記載されたサンプルコードはこちらです。『implements SandboxPostCopy』の宣言を行い、実行処理は『runApexClass』メソッドに記載すればいいようでした。
f:id:tyoshikawa1106:20191217185044p:plain


上記サンプルを参考につくってみたコードがこちらになります。
f:id:tyoshikawa1106:20191217185253p:plain


実行処理はrunApexClassメソッドに記載すれば良いのですが、今後実行処理が増えていった際にメンテナンス性が低下しないように細かい処理は別のメソッドに記載しました。


SOQLクエリはDaoクラスに記載しています。カスタム設定もオブジェクト扱いなのでSOQLクエリで取得することが可能です。
f:id:tyoshikawa1106:20191217185611p:plain


SandboxPostCopyインターフェースのテストクラスはこんな感じ。
f:id:tyoshikawa1106:20191217185846p:plain


『Test.testSandboxPostCopyScript』関数をつかってテストするようです。引数で組織IDなど渡す必要があるみたいですが、サンプルをそのまま使えば特に問題ありませんでした。


「SandboxPostCopy」インターフェースのApexコードはこんな感じで実装できました。実際に使用するときにはSandbox作成時にApexクラスを指定する箇所があるのでそこでクラス名を入力する形で設定できます。実行後ですが管理者アカウント宛に実行結果の通知メールが届きました。そのメールで実行時のエラー有無の確認が可能でした。

サンプルコード

PrepareMySandbox.cls
public with sharing class PrepareMySandbox implements SandboxPostCopy {
    
    private PrepareMySandboxDao dao = new PrepareMySandboxDao();
    
    /**
     * runApexClass
     */
    public void runApexClass(SandboxContext context) {
        // カスタム設定:組織設定情報の更新
        this.doUpdateOrgSettingInfo();
    }
    
    /**
     * カスタム設定:組織設定情報の更新
     */
    @TestVisible
    private void doUpdateOrgSettingInfo() {
        // カスタム設定:組織設定情報の取得
        OrgSettingInfo__c orgSettingInfo = this.dao.getOrgSettingInfo();
        // カスタム設定:組織設定情報の取得結果判定
        if (String.isEmpty(orgSettingInfo.Id)) return;
        // 本番組織フラグのチェックOFF
        orgSettingInfo.IsProductOrg__c = false;
        // UPDATE
        update orgSettingInfo;
    }
}
PrepareMySandboxTest.cls
@isTest
private class PrepareMySandboxTest {
    
    private static User testAdminUser = CommonTester.getLoginUser();
    
    /**
     * runApexClass
     */
    @isTest static void runApexClassTest() {
        
        System.runAs(testAdminUser) {
            
            Test.startTest();
            
            // testSandboxPostCopyScript
            Test.testSandboxPostCopyScript(new PrepareMySandbox(), UserInfo.getOrganizationId(), UserInfo.getOrganizationId(), UserInfo.getOrganizationName());
            
            Test.stopTest();
        }
    }
    
    /**
     * カスタム設定:組織設定情報の更新
     */
    @isTest static void doUpdateOrgSettingInfoest() {
        
        System.runAs(testAdminUser) {
            
            OrgSettingInfo__c orgSettingInfo = CommonTester.createOrgSettingInfo(false);
            orgSettingInfo.IsProductOrg__c = true;
            insert orgSettingInfo;
            
            Test.startTest();
            
            // カスタム設定:組織設定情報の更新
            PrepareMySandbox cls = new PrepareMySandbox();
            cls.doUpdateOrgSettingInfo();
            
            Test.stopTest();
            
            OrgSettingInfo__c result = [SELECT Id,IsProductOrg__c FROM OrgSettingInfo__c WHERE Id =: orgSettingInfo.Id LIMIT 1];
            System.assert(orgSettingInfo.IsProductOrg__c, false);
        }
    }
}

※Daoクラスは省略します。

SFDC:組織IDをつかった本番組織とSandbox組織の判定について

組織IDをつかった本番組織とSandbox組織の判定についてです。Sandbox組織では数式の値をテスト用に変更したかったので組織IDをつかってフラグを用意してみました。

f:id:tyoshikawa1106:20191216075215p:plain

IF($Organization.Id == '00DX0000000XXXX'
,true
,false
)


これでSandbox組織作成時に値を変更しなくても大丈夫と思ったのですが、この組織IDを表す「'00DX0000000XXXX'」という文字列ですが、Sandbox組織作成時に自動でSandbox組織のIDに置換される仕組みが用意されているみたいです。数式だからかなと思ったのですがカスタム表示ラベル内で値を定義しても同様に置換されるみたいでした。
※組織ID「'00DX0000000XXXX'」は仮の値です。実際のIDは設定の組織のページで確認できます。


組織IDをつかって本番環境とSandbox組織は上記の仕様があるみたいなので、利用時には少し注意が必要そうです。ちなみにSandbox組織作成時には特定のApexクラスの処理を実行する仕組みが用意されています。SandboxPostCopy インターフェースの仕組みをつかった方法です。

f:id:tyoshikawa1106:20191216075727p:plain

SandboxPostCopy インターフェース


組織IDの文字列判定はちょっと難しそうなので、今回は本番とSandboxのフラグをカスタム設定にもたせて、SandboxPostCopy機能でApexコードを実行してSandbox作成時にフラグを更新する方法で対処しようと思いました。

SFDC:Apexで数値項目の文字数取得を試してみました

Apexで数値項目の文字数取得を試してみました。

項目の文字数取得に関してですが「テキスト型」項目の場合は次のように「.Length」で取得できます。

// テキスト型はLength()で取得可
Schema.DescribeFieldResult F = Account.Site.getDescribe();
Integer lengthOfField = F.getLength();
System.debug(lengthOfField);
// 別の書き方
System.debug(Schema.SObjectType.Account.Fields.Site.Length);

f:id:tyoshikawa1106:20191213074109p:plain

f:id:tyoshikawa1106:20191213074146p:plain


「数値型」項目の場合は「.Length」でも0になります。

// 数値型はLength()で取得不可
Schema.DescribeFieldResult F = Account.NumberOfEmployees.getDescribe();
Integer lengthOfField = F.getLength();
System.debug(lengthOfField);
// 別の書き方
System.debug(Schema.SObjectType.Account.Fields.NumberOfEmployees.Length);

f:id:tyoshikawa1106:20191213074330p:plain

f:id:tyoshikawa1106:20191213074355p:plain


「数値型」項目の場合は「.Precision」で取得できます。ただし、小数点以下の値も加算されていました。

// 数値型はPrecision()で取得可
Schema.DescribeFieldResult F = Account.SampleNumber__c.getDescribe();
Integer lengthOfField = F.getPrecision();
System.debug(lengthOfField);
// 別の書き方
System.debug(Schema.SObjectType.Account.Fields.SampleNumber__c.Precision);

f:id:tyoshikawa1106:20191213074830p:plain

f:id:tyoshikawa1106:20191213074935p:plain


少数点以下の値を取得する場合は「Scale」で取得できます。

// 数値型の少数点以下はScale()で取得可
Schema.DescribeFieldResult F = Account.SampleNumber__c.getDescribe();
Integer lengthOfField = F.getScale();
System.debug(lengthOfField);
// 別の書き方
System.debug(Schema.SObjectType.Account.Fields.SampleNumber__c.Scale);

f:id:tyoshikawa1106:20191213075423p:plain


「Precision」で数値型の文字数の設定情報は取得できましたが、文字数取得の目的は入力フォームなどで入力文字数の判定利用などが目的だと思うので、そういった目的には少し使いづらいみたいです。


また、標準の数値項目の場合は「Precision」でも取得できないようでした。

// 標準項目の数値型はPrecision()で取得不可?
Schema.DescribeFieldResult F = Account.NumberOfEmployees.getDescribe();
Integer lengthOfField = F.getPrecision();
System.debug(lengthOfField);
// 別の書き方
System.debug(Schema.SObjectType.Account.Fields.NumberOfEmployees.Precision);

f:id:tyoshikawa1106:20191213080604p:plain

おまけ

Schema関数で取得できる項目の設定情報です。

取得処理
Schema.DescribeFieldResult F = Account.SampleNumber__c.getDescribe();
System.debug(F);
取得結果

Schema.DescribeFieldResult[getByteLength=0
getCalculatedFormula=null
getCompoundFieldName=null
getController=null
getDataTranslationEnabled=null
getDefaultValue=null
getDefaultValueFormula=null
getDigits=0
getFilteredLookupInfo=null
getInlineHelpText=null
getLabel=サンプル数値
getLength=0
getLocalName=SampleNumber__c
getMask=null
getMaskType=null
getName=SampleNumber__c
getPrecision=16
getReferenceTargetField=null
getRelationshipName=null
getRelationshipOrder=null
getScale=4
getSoapType=DOUBLE
getSobjec

参考

SFDC:Apex開発で日付型や数値型をテキスト型に形式指定で変換する方法について

日付型や数値型をテキスト型に形式指定で変換する方法についてです。テキスト型に変換するだけなら「String.valueOf」関数で対応できます。

f:id:tyoshikawa1106:20191208110529p:plain


日付型をString.valueOf関数でテキスト型に変換すると「2019-12-08」のようにハイフン区切りで変換されます。
f:id:tyoshikawa1106:20191208110539p:plain


Apexクラスの処理で利用する分には問題ありませんが、変換後の値をユーザに見せたい場合でハイフン区切りではなく通常の日付形式のスラッシュ区切りにしたい場合は「format」関数を利用することで対応可能です。

String nowDateString = nowDate.format();

f:id:tyoshikawa1106:20191208111011p:plain


実行結果はこちら。
f:id:tyoshikawa1106:20191208111109p:plain


数値型も形式指定が可能です。format関数でテキスト型に変換するとカンマ区切りのテキスト形式に変換できます。
f:id:tyoshikawa1106:20191208111456p:plain


実行結果はこちら。
f:id:tyoshikawa1106:20191208111522p:plain


ちなみに日時型の場合はカスタマイズ性が少し高いです。(Java の SimpleDateFormatで変換される)
f:id:tyoshikawa1106:20191208112249p:plain

実行結果はこちら。
f:id:tyoshikawa1106:20191208112309p:plain


Apex開発で日付型や数値型をテキスト型に形式指定で変換する方法についてはこんな感じ。

参考