Mark Hammer's blog

SalesforceやTrailheadに関する情報を投稿しているブログです。

Salesforce Tips: 商品スケジュールについて調べた細かいコト

某所にて商品スケジュールについて質問があり、そこで商品スケジュールについていろいろ調べたのでブログに投稿しようと思ったら、約6年前に詳しく他の方のブログに書かれてました。

tyoshikawa1106.hatenablog.com

そこで、ここでは上述のブログに記載されてない細かいコトを書こうと思います。

「全商品に対して有効化」ってナニ?

f:id:mark-hammer:20190616225623p:plain
商品スケジュール設定画面(保存前)

商品スケジュール設定画面には、「数量スケジュール」、「収益スケジュール」それぞれに対し「有効化」と「全商品に対して有効化」2つのチェックボックスがあります。
このうち、「有効化」と「全商品に対して有効化」両方のチェックボックスを入れて「保存」をクリックすると、

f:id:mark-hammer:20190616225639p:plain
商品スケジュール設定画面(保存後)

「有効化」のチェックボックスはチェックが残りますが、「全商品に対して有効化」のチェックは消えます。
いくら「全商品に対して有効化」にチェックを入れて保存しても、保存後には消えます。

このチェックボックス項目は何をしているのかというと、このヘルプ(英語) によれば、

  • 「全商品に対して有効化」は、チェックを入れて保存をクリックした時点の全ての商品に対し、該当スケジュール(数量、収益)を有効化する設定である。
  • 「全商品に対して有効化」にチェックを入れて保存した後に追加された商品は商品スケジュールが有効化されていないので、個別に有効化するか再度「全商品に対して有効化」にチェックを入れて保存する必要がある。

とのことでした。

商品画面で見ると、以下のようになります。

f:id:mark-hammer:20190616225809p:plain
「全商品に対して有効化」前
f:id:mark-hammer:20190616225843p:plain
「全商品に対して有効化」後

ということで、「全商品に対して有効化」のチェックボックスが消えるのは、「そういうものです」というのが答えになります。

商品スケジュールを編集可能なユーザ

商品スケジュールは、商談と商品を結びつける「商談商品」オブジェクトのレコード画面で設定します。
この「商談商品」は、プロファイルの「標準オブジェクト権限」セクションにはありません。

では、どこで編集権限が設定されるのかというと、このドキュメント に書いてありました。

商談の商談品目を作成または更新するには、Opportunity レコードの「編集」権限が必要です。

ということで、ユーザに対し商談の編集権限を与えてみると、商品スケジュールを設定可能になりました。

f:id:mark-hammer:20190616231137p:plain
商談の編集権限がない場合

f:id:mark-hammer:20190616231201p:plain
商談の編集権限がある場合

Salesforceに不正ログインしたらどうなるの?

はじめに

以前、Twitterを見ていたら「電車でSalesforceを見てる人がいて、ユーザIDとパスワードが丸見えだった」というTweetを見かけました。
それを見た私は、こんなTweetをしました。

さて、仮にユーザIDとパスワードが分かったとして、Salesforceにログインすることはできるのでしょうか。
そして、不正ログインされた場合、そのアクセス内容は分かるのでしょうか。

ふつうはユーザIDとパスワードだけではログインできない

Salesforceで特にセキュリティ設定を行っていない場合、Salesforceに初めてアクセスするPCからログインすると、以下のような確認コード入力画面が表示されます。

確認コード入力画面

これは、過去Salesforceにログインしたことがない端末からログインが試みられた場合の二段階認証の意味があります。
この確認コード入力が必要になっているため、通常はユーザIDとパスワードが分かっただけではログインはできません。

でも確認コード入れたくない

しかし、セキュリティ対策の常ですが多くの人はこう思っているでしょう。

「確認コード入力面倒くさい。」と。

そして、「この確認コード入力をなしにする方法はないか」と探します。

この確認コード入力を無効にするには、このヘルプにも記載されている通り、以下の方法があります。

このうち、組織の信頼済み IP 範囲の設定では全IPアドレス範囲を一度に指定することはできませんが、プロファイルのログインIPアドレスの制限では0.0.0.0~255.255.255.255のように、IPアドレス指定範囲の制限はありません。
そのため、多くの人は下記サイトのように、プロファイルのログインIPアドレスの制限にて0.0.0.0~255.255.255.255を指定して確認コード入力を回避します。

salesforce-blog.com

ただ、確認コードをなしとすれば、当然ユーザIDとパスワードが分かっただけでログイン可能となります。
このように、「デフォルトのセキュリティ対策を利便性のために弱める」ことで、不正ログインは可能となるのです。

ログイン履歴と操作ログはどうやって見るの?

先のTweetで、私は「どんな環境でもログイン履歴と操作ログは取っていて、消せない」と書きました。
では、どうやってそれらのログを見るのでしょうか。

ログイン履歴

ログイン履歴 では、過去6か月間のユーザのログイン履歴が参照できます。
具体的には、

  • ログイン時刻
  • アクセス元IPアドレス
  • 状況(ログイン成功、失敗)

の情報が取得できます。

もし、アクセス元IPアドレスに会社で使用可能としているもの以外のIPアドレスがあり、かつ状況が「成功」となっていたら、そのログインは不正ログインの可能性大です。

操作ログ

Salesforceの操作履歴を取得する方法について、イベントモニタリング があります。

これはSalesforce内で発生したイベントごとに、ログが取得できるものとなります。 具体的には、

  • ログイン
  • ログアウト
  • 各画面へのアクセス内容
  • レポートのエクスポート

など、「どのユーザがいつどのようなページを見たか」、また「どのユーザが、いつどのレポートをエクスポートしたか」、といった情報が取得できます。

しかし、このイベントモニタリング、Developer Edition 以外では有料のオプションを購入しないとアクセスできないものになります。
では、イベントモニタリング用オプションを購入していない組織では操作履歴は取得できないのでしょうか。。

実は、イベントモニタリング用オプションを購入していない組織でも、同様のログを取得できる方法はあります。
こちらのヘルプ によると、イベントモニタリング用オプションを購入していない場合でも過去 90 日間のログ情報を取得できます。
なお、こちらの方法でも費用は発生します。
「費用が発生してもいいので、どうしても操作ログを見たい!」という方向けですね。

おわりに

Salesforceにログインして何らかの操作をした場合、(期間制限はありますが)ログは取得可能であることをお伝えしました。

しかし、そもそも不正なログインをさせない方法を取った方が良いのは言うまでもありません。
例えば、

  • 確認コード入力が面倒なのであれば、組織の信頼済み IP 範囲の設定で会社のIPアドレスを細かく指定して、「会社からのアクセスは確認コード入力不要」とする。
  • そもそも社外でSalesforceにログインさせない。

といった方法があります。

万が一があった場合に、この投稿が何かのお役に立てば幸いです。

Trailhead モジュール:Apex エンタープライズパターン: ドメインおよびセレクタレイヤ

※この内容は2019/6時点のものです。

ドメインレイヤの原則について

https://trailhead.salesforce.com/ja/content/learn/modules/apex_patterns_dsl/apex_patterns_dsl_learn_dl_principles

  • 説明:日本語
  • Challenge:日本語選択問題

Apex でのドメインレイヤの原則の適用

https://trailhead.salesforce.com/ja/content/learn/modules/apex_patterns_dsl/apex_patterns_dsl_apply_dl_principles

  • 説明:日本語
  • Challenge:英語ハンズオン

【Challenge要約】

  • 「fflib_SObjectDomain」クラスを継承した基本ドメインクラス「Accounts」を作成してください。
  • 全てのトリガーメソッドに対して「fflib_SObjectDomain」クラス内の「triggerHandler」メソッドを呼び出すように実装した、取引先(Account)オブジェクト用のApexトリガ「AccountsTrigger」を作成してください。
  • レコードが作成されたときに、初期値として説明(Description)項目に「Domain classes rock!」という値を設定するロジックを実装してください。
  • レコードが更新されたときに、「Domain classes rock!」と説明(Description)項目値の間のレーベンシュタイン距離を計算する更新ロジックを実装してください。
    • レーベンシュタイン距離の計算にはApex Stringメソッド「getLevenshteinDistance(stringToCompare)」を使用してください。
    • 計算結果は年間売上(Annual Revenue)項目に保存してください。

セレクタレイヤの原則について

https://trailhead.salesforce.com/ja/content/learn/modules/apex_patterns_dsl/apex_patterns_dsl_learn_selector_l_principles

  • 説明:日本語
  • Challenge:日本語選択問題

Apex でのセレクタレイヤの原則の適用

https://trailhead.salesforce.com/ja/content/learn/modules/apex_patterns_dsl/apex_patterns_dsl_apply_selector_l_principles

  • 説明:日本語
  • Challenge:英語ハンズオン

【Challenge要約】

  • 取引先(Account)オブジェクトのセレクタクラス「AccountsSelector」を作成してください。
    • IDが入るset型パラメータを引数とし、取引先レコードのリストを返り値とする「selectById」メソッドを実装してください。
    • セレクタ基本クラスを、取引先名(Name)、説明(Description)、および年間売上(AnnualRevenue)の各項目値を取得するよう実装してください。

Trailhead モジュール:Apex エンタープライズパターン: サービスレイヤ

※この内容は2019/6時点のものです。

関心の分離について

https://trailhead.salesforce.com/ja/content/learn/modules/apex_patterns_sl/apex_patterns_sl_soc

  • 説明:日本語
  • Challenge:日本語選択問題

サービスレイヤの原則について

https://trailhead.salesforce.com/ja/content/learn/modules/apex_patterns_sl/apex_patterns_sl_learn_sl_principles

  • 説明:日本語
  • Challenge:日本語選択問題

Apex でのサービスレイヤの原則の適用

https://trailhead.salesforce.com/ja/content/learn/modules/apex_patterns_sl/apex_patterns_sl_apply_sl_principles

  • 説明:日本語
  • Challenge:英語ハンズオン

【Challenge要約】

  • Apexクラス「CaseService」を作成してください。
    • ケースIDが入るset型パラメータとクローズ理由が入るstring型パラメータを引数とする、void型のstaticメソッド「closeCases」を実装して下さい。
  • REST API用 Apexクラス「CaseCloseResource」を作成してください。
    • URLマッピングは「/case/*/close」(*にはIDが入る)としてください。
    • クローズ理由が入るstring型パラメータを受け入れ、Idとクローズ理由を「CaseService.closeCases」サービスメソッドに渡すPOST用メソッド「closeCase」を実装してください。

作業単位の原則について

https://trailhead.salesforce.com/ja/content/learn/modules/apex_patterns_sl/apex_patterns_sl_learn_uow_principles

  • 説明:日本語
  • Challenge:日本語選択問題

Apex での作業単位の原則の適用

https://trailhead.salesforce.com/ja/content/learn/modules/apex_patterns_sl/apex_patterns_sl_apply_uow_principles

  • 説明:日本語
  • Challenge:英語ハンズオン

【Challenge要約】

  • テストクラス「UnitOfWorkTest」、及びテストメソッド「challengeComplete」を作成してください。
  • データベース更新のために「commitWork」メソッドを呼び出してください。
  • チャレンジを確認する前に最低1回テストを実行してください。以下のアサーションをパスする必要があります。
    • System.assertEquals(100, [Select Id from Account].size());
    • System.assertEquals(500, [Select Id from Contact].size());
    • System.assertEquals(500, [Select Id from Note].size());

Trailhead モジュール:Identity for Mobile-Centric Customers

※この内容は2019/6時点のものです。

Explore Mobile-First Identity

https://trailhead.salesforce.com/ja/content/learn/modules/identity-for-mobile-centric-customers/identity_mfi_basics

  • 説明:英語
  • Challenge:英語選択問題

Set Up Mobile-First Login and Sign-Up

https://trailhead.salesforce.com/ja/content/learn/modules/identity-for-mobile-centric-customers/identity_mfi_clicks

  • 説明:英語
  • Challenge:英語ハンズオン

【Challenge要約】

このChallengeには新しいTrailhead Playground組織が必要です。ページの一番下にスクロールし、「起動」の左にある下矢印をクリックしてメニューから「Trailhead Playground を作成」を選択してください。

  • 「External Identity User」プロファイルをコピーし、「NTO Customer」プロファイルを作成してください。
  • 「Custom User」プロファイルに、「Private Objects」オブジェクトの「すべて表示」権限を付与してください。
  • 新規取引先「NTO Customers」を作成してください。
  • コミュニティ管理者となるあなたのユーザに、ロール「NTO Customer Manager」を割り当ててください。
  • 新規コミュニティ「NTO Customers」を作成してください。
  • コミュニティ「NTO Customers」のメンバーに「NTO Customer」プロファイルを追加してください。
  • コミュニティのロゴを、あなたの自由に選んでください。
  • 背景画像を https://identitycms.herokuapp.com/promo-transparent.jpg に設定してください。
  • ログインページ設定で「ログイン検出ページ」、登録ページ設定で「設定可能なセルフ登録ページ」を設定してください。登録ページ設定での「ユーザの項目」は「名」、「メール」を設定してください。
  • 「NTO Customers」コミュニティにサインアップしてください。
    • 「名」は「Sarah」、「メール」はあなたのメールアドレスを使用してください。
  • サインアップしたアカウントでコミュニティ「NTO Customers」のホームページにアクセスした後、ログアウトし、再ログインを行ってください。

※筆者注:Challengeで記載されていない設定項目は、ユニット内の手順を参照してください。

Customize Mobile-First Login with Code

https://trailhead.salesforce.com/ja/content/learn/modules/identity-for-mobile-centric-customers/identity_mfi_code

  • 説明:英語
  • Challenge:英語選択問題

Track Progress with Reports and Dashboards

https://trailhead.salesforce.com/ja/content/learn/modules/identity-for-mobile-centric-customers/identity_mfi_reports

  • 説明:英語
  • Challenge:英語選択問題

Trailhead モジュール:Unit Testing on the Lightning Platform

※この内容は2019/6時点のものです。

Learn About Why We Test

https://trailhead.salesforce.com/ja/content/learn/modules/unit-testing-on-the-lightning-platform/why-we-test

  • 説明:英語
  • Challenge:英語ハンズオン

【Challenge要約】

Generate Data for Tests

https://trailhead.salesforce.com/ja/content/learn/modules/unit-testing-on-the-lightning-platform/generate-data-for-tests

  • 説明:英語
  • Challenge:英語ハンズオン

【Challenge要約】

  • このCSVファイルをダウンロードし、静的リソースとしてアップロードしてください。静的リソースの名前は「Mock_Data」としてください。
  • 新しいテストクラス「myDataGenerationTests」を作成してください。
  • テストクラスに、静的リソース「Mock_Data」のCSVデータを取引先オブジェクトに取り込む @testSetup メソッドを作成してください。
  • テストクラスに、取引先が15レコード存在することをチェックするテストメソッドを作成してください。

Write Positive Tests

https://trailhead.salesforce.com/ja/content/learn/modules/unit-testing-on-the-lightning-platform/positive-tests

  • 説明:英語
  • Challenge:英語ハンズオン

【Challenge要約】

  • Apexクラス「AccountWrapper_Tests」に「isHighPrority()」メソッドの正常系テストを行うためのテストメソッドを追加してください。
  • テストデータを生成するために、@testSetup メソッドを使用してください。
  • 単体テストを実行し、Apexクラス「AccountWrapper」のコードカバレッジを85%以上にしてください。

Write Negative Tests

https://trailhead.salesforce.com/ja/content/learn/modules/unit-testing-on-the-lightning-platform/negative-tests

  • 説明:英語
  • Challenge:英語ハンズオン

【Challenge要約】

  • 新しいApexクラス「Calculator_Tests」を作成してください。
  • Apexクラス「Calculator_Tests」に、Apexクラス「Calculator」の正常系テスト、異常系テストを実装してください。
  • テストデータを生成するために、@testSetupメソッドを使用してください。
  • 単体テストを実行し、Calculator.clsのコードカバレッジを100%にしてください。

Write Permission-Based Tests

https://trailhead.salesforce.com/ja/content/learn/modules/unit-testing-on-the-lightning-platform/permission-based-tests

  • 説明:英語
  • Challenge:英語ハンズオン

【Challenge要約】

  • 「Custom: Support Profile」プロファイルをコピーし、「Custom User」プロファイルを作成してください。
  • 「Custom User」プロファイルに、「Private Objects」オブジェクトの「すべて表示」権限を付与してください。
  • 新しいApexクラス「PositivePermission_tests」を作成してください。
  • 「Custom User」プロファイルのユーザーが、自分が所有者でない「Private Objects」オブジェクトのレコードにアクセスできることを示す単体テストを作成してください。
  • 単体テストを実行し、すべて成功することを確認してください。

Write Tests for Your Lightning Components

https://trailhead.salesforce.com/ja/content/learn/modules/unit-testing-on-the-lightning-platform/lightning-component-tests

  • 説明:英語
  • Challenge:英語選択問題

Use Mocks and Stub Objects

https://trailhead.salesforce.com/ja/content/learn/modules/unit-testing-on-the-lightning-platform/mock-stub-objects

  • 説明:英語
  • Challenge:英語ハンズオン

【Challenge要約】

  • Apexクラス「ExternalSearch_Tests」に、HTTPステータスコード500を返す単体テスト用メソッドを追加してください。
  • 単体テストを実行し、Apexクラス「ExternalSearch」のコードカバレッジを100%にしてください。

Trailhead モジュール:App Development Without Limits

※この内容は2019/6時点のものです。

Learn About Daily Rate Limits

https://trailhead.salesforce.com/ja/content/learn/modules/app-development-without-limits/app-development-without-limits-rate

  • 説明:英語
  • Challenge:英語ハンズオン

【Challenge要約】

  • 「標準ユーザ」プロファイルをコピーし、「Data Entry - No API Access」プロファイルを作成してください。
    • 「システム管理者権限」セクションにある「API の有効化」のチェックを外し、保存してください。
  • (まだ作成していない場合は)「Limits Trail Connected App」接続アプリケーションを作成してください。
    • 接続アプリケーション名:Limits Trail Connected App
    • API参照名:Limits_Trail_Connected_App
    • 取引先責任者 メール:あなたのメールアドレス
    • 「Web アプリケーション設定」セクションの「開始URL」:https://trailhead.salesforce.com
  • 「Limits Trail Connected App」接続アプリケーションへのアクセス許可を割り当てた権限セット「Connected App Access」を作成してください。

Avoid Concurrency

https://trailhead.salesforce.com/ja/content/learn/modules/app-development-without-limits/app-development-without-limits-concurrency

  • 説明:英語
  • Challenge:英語ハンズオン

【Challenge要約】

  • この未管理パッケージをインストールしてください。インストールに失敗する場合はこの記事(英語)の手順に従ってください。
  • 設定画面より、Apexクラス「CalloutController」を探してください。
  • Apexクラス「CalloutController」を以下の通り編集してください。
    • 既存のコールアウト部分のコードを、新しくContinuationクラスの変数 con を使用してコールバックハンドラ「processResponse」を呼び出すよう変更してください。
    • サーバからのレスポンスを待つためのコールバックハンドラとして、「processResponse()」メソッドを追加してください。

Tune Transactions

https://trailhead.salesforce.com/ja/content/learn/modules/app-development-without-limits/app-development-without-limits-transactions

  • 説明:英語
  • Challenge:英語ハンズオン

【Challenge要約】

  • まだインストールしていない場合は、この未管理パッケージをインストールしてください。インストールに失敗する場合はこの記事(英語)の手順に従ってください。
  • 設定画面より、Apexクラス「TrailLoop」を探してください。
  • AllBadThings()」メソッドを以下の通り編集し、保存してください。
    • if文をSOQLのWhere句で置き換えてください。
    • update文をfor文の外に出してください。
    • メソッド名を「AllGoodThings()」に変更してください。

※筆者注: 設定を正しく実施しても

System.QueryException: List has no rows for assignment to SObject

というエラーが発生する場合は、Challenge用組織のユーザ言語を[English]に変更し、再度Challengeの確認を実施してください。
これはChallengeチェック時に SELECT Id FROM Profile WHERE Name = 'System Administrator' LIMIT 1 というSOQLが実行されますが、ユーザ言語が日本語だとプロファイル名が「システム管理者」となるため、SOQL結果が0件になるのが原因と思われます。

Trailhead モジュール:Visualforce Mobile

※この内容は2019/6時点のものです。

Salesforce アプリケーションでの Visualforce の使用開始

https://trailhead.salesforce.com/ja/content/learn/modules/visualforce_mobile_salesforce1/visualforce_mobile_salesforce1_intro

  • 説明:日本語
  • Challenge:日本語選択問題

ナビゲーションメニューへの Visualforce ページの追加

https://trailhead.salesforce.com/ja/content/learn/modules/visualforce_mobile_salesforce1/visualforce_mobile_salesforce1_nav_menu

  • 説明:日本語
  • Challenge:英語ハンズオン

【Challenge要約】

  • ページ名を「HelloMobile」としたVisualforceページを作成してください。
  • Visualforceページに「Hello mobile world」の文字列を表示するよう、コードを記述してください。
  • Visualforceページ「HelloMobile」をSalesforceモバイルアプリケーションで利用可能にしてください。
  • Visualforceページ「HelloMobile」を、タブ名を「HelloMobile」としたタブで表示するようにしてください。また、このタブをSalesforceナビゲーションに追加してください。

Salesforce Lightning Design System を使用した Visualforce ページのスタイル設定

https://trailhead.salesforce.com/ja/content/learn/modules/visualforce_mobile_salesforce1/visualforce_mobile_salesforce1_lightning_design

  • 説明:日本語
  • Challenge:英語ハンズオン

【Challenge要約】

  • ページ名を「MobileContactList」としたVisualforceページを作成してください。
  • VisualforceページにLightning Design Systemをインポートしてください。
  • Lightning Design SystemのName Value Listユーティリティクラスを使用してください。
  • 取引先責任者(Contact)の標準リストコントローラを使用してください。recordSetVar 属性には"contacts"を指定してください。
  • ”apex:repeat”コンポーネントを使用し、取引先責任者(Contact)のリストを反復処理してください。var 属性には “c” を設定してください。
  • Visualforceページに、取引先責任者(Contact)の「取引先責任者名(Name)」、「電話(Phone)」項目の値を表示してください。
  • Salesforceモバイルアプリケーションで使用できるよう設定してください。
  • 作成したVisualforceページを「MobileContacts」タブに含めてください。また、「MobileContacts」タブをSalesforce アプリケーションナビゲーションメニューに追加してください。

Visualforce ページを使用したグローバルアクションの実装

https://trailhead.salesforce.com/ja/content/learn/modules/visualforce_mobile_salesforce1/visualforce_mobile_salesforce1_actions_global

  • 説明:日本語
  • Challenge:英語ハンズオン

【Challenge要約】

  • 表示ラベルを「My Business Card」、名前を「My_Business_Card」としたグローバルアクションを作成してください。
  • 作成したグローバルアクションには、Visualforceページ「BusinessCard」を関連付けしてください。
  • Visualforceページ「BusinessCard」はモバイルアプリケーションで利用可能としてください。
  • Visualforceページ「BusinessCard」には、適切なVisualforceグローバル変数を用いて以下の項目を表示してください。
    • ログインユーザの名(FirstName)
    • ログインユーザの姓(LastName)
    • ログインユーザのメール(Email)
    • ログインユーザの電話(Phone)
    • ログインユーザの役職(Title)
  • 作成したVisualforceページに、Eメールアドレスを入力するための入力フィールドと、連絡先情報を他のユーザに素早くメール送信することを可能にする「送信」ボタンを作成してください。(この機能追加は任意です。)

Visualforce ページを使用したオブジェクト固有のアクションの実装

https://trailhead.salesforce.com/ja/content/learn/modules/visualforce_mobile_salesforce1/visualforce_mobile_salesforce1_actions_object

  • 説明:日本語
  • Challenge:英語ハンズオン

【Challenge要約】

  • ページ名を「ShowAssistantInfo」としたVisualforceページを作成してください。
  • Visualforceページ「ShowAssistantInfo」には取引先責任者の標準コントローラを使用してください。
  • Visualforceページ「ShowAssistantInfo」にアシスタントの名前と電話番号を表示するため、それぞれ該当する取引先責任者標準項目を使用してください。
  • Visualforceページ「ShowAssistantInfo」に 'tel:'ハイパーリンク を用いてアシスタント電話番号を表示してください。
  • 取引先責任者オブジェクトのオブジェクト固有アクションを作成してください。アクションの表示ラベルは「Call Assistant」、名前を「Call_Assistant」としてください。
  • 「Call Assistant」アクションにはVisualforceページ「ShowAssistantInfo」を使用してください。
  • 「Call Assistant」アクションを取引先責任者ページレイアウト「Contact Layout」に追加してください。

ページレイアウトとモバイルカードでの Visualforce ページの使用

https://trailhead.salesforce.com/ja/content/learn/modules/visualforce_mobile_salesforce1/visualforce_mobile_salesforce1_layouts_cards

  • 説明:日本語
  • Challenge:英語ハンズオン

【Challenge要約】

  • ページ名を「OpportunityStageTips」としたVisualforceページを作成してください。
  • Visualforceページ「OpportunityStageTips」に対し、商談のフェーズ項目値(「Prospecting」、「Needs Analysis」、「Proposal/Price Quote」、「Negotiation/Review」)ごとに、そのフェーズに合ったアドバイスを個別に表示するようにしてください。各フェーズに表示するための任意のプレースホルダコンテンツを使用できます。
  • Visualforceページ「OpportunityStageTips」には商談の標準コントローラを使用してください。
  • Visualforceページ「OpportunityStageTips」を商談ページレイアウト「Opportunity Layout」のモバイルカードに追加してください。

ユーザインターフェースのガイドラインの採用

https://trailhead.salesforce.com/ja/content/learn/modules/visualforce_mobile_salesforce1/visualforce_mobile_salesforce1_ui_guidelines

  • 説明:日本語
  • Challenge:日本語選択問題

CSS および JavaScript モバイルフレームワークの使用

https://trailhead.salesforce.com/ja/content/learn/modules/visualforce_mobile_salesforce1/visualforce_mobile_salesforce1_mobile_frameworks

  • 説明:日本語
  • Challenge:日本語選択問題

フィード追跡から大量データのリカバリをやってみた

はじめに

Salesforceにて項目値の変更を記録する機能は項目履歴管理フィード追跡がありますが、データローダから簡単に項目値の変更履歴をエクスポートできる項目履歴管理と違い、フィード追跡は容易に変更履歴をエクスポートすることができません。
今回は項目履歴管理が使えず、フィード追跡から大量データのリカバリが必要になった場合の手順を記載します。

f:id:mark-hammer:20190602222948p:plain
画面では簡単に更新内容が分かるのに…

状況

  • ある日、特定日時に大量の取引先責任者レコードにある「取引先」項目値が削除されていることに気づいた。
  • 項目履歴管理は使用しておらず、デフォルトで設定されていたフィード追跡により各レコードに取引先名変更のChatter投稿がなされていた。
  • そのChatter投稿をもとに手作業でリカバリすることはできるが、対象レコードが数千件存在するため、データローダ等で一括リカバリしたい。

フィード追跡からのリカバリが難しい理由

項目履歴管理の場合はリカバリに必要な「対象レコードID」「変更前の値」「変更後の値」が1オブジェクトで取得可能です。

取引先責任者履歴のイメージ図

一方、フィード追跡の場合、

  • 「対象レコードID」と「該当フィード追跡の投稿を示すChatter投稿ID」を持つフィード項目(FeedItem)
  • 「該当フィード追跡の投稿を示すChatter投稿ID」と「変更前の値」「変更後の値」を持つフィード追跡履歴(FeedTrackedChange)

が別オブジェクトとなっているため、リカバリにはこの2オブジェクトの紐づけが必要となります。

f:id:mark-hammer:20190603234213p:plain
フィード追跡関連オブジェクトのイメージ図

これがフィード追跡からのリカバリを難しくしている一方で、この紐づけさえできればフィード追跡からでもリカバリはできる、ということになります。

リカバリ手順

データのエクスポート

フィード追跡からのリカバリに必要な2オブジェクトのうち、FeedTrackedChangeはウィークリーエクスポートから、FeedItemはデータローダからのExportが必要となります。

ウィークリーエクスポート

Salesforce からバックアップデータをエクスポートする のヘルプに従いエクスポートを実行します。
「エクスポートデータ」で選択するオブジェクトは、今回は FeedTrackedChange だけでよいです。*1
「画像、ドキュメント、および添付ファイルを含める」、「Salesforce Files および Salesforce CRM Content ドキュメントバージョンを含める」はお好みで選択してください。画像ファイルが多いとバックアップに時間がかかるので、画像、ドキュメント、添付ファイルのバックアップがとりたい方以外は不要だと思います。

f:id:mark-hammer:20190602225429p:plain
ウィークリーエクスポート 選択画面

エクスポートが完了するとzipファイルがダウンロードできるようになるので、ダウンロードして解凍し、FeedTrackedChange.csvが存在することを確認します。

データローダ

Chatter フィードのデータをエクスポートする のヘルプに従い「フィード項目 (FeedItem)」オブジェクトをエクスポートします。
以下、エクスポートしたファイル名をFeedItem.csvとします。

f:id:mark-hammer:20190602225346p:plain
データローダ Export画面

データリカバリー用CSVファイル作成

「データのエクスポート」で取得したデータの内容は以下です。(今回の作業に必要な項目のみ抜粋)

  • FeedTrackedChange.csv
    • FeedItemId: フィード追跡の投稿を示すChatter投稿ID
    • FieldName: 値が変更された項目のAPI参照名。取引先責任者オブジェクトにある「取引先」項目の場合は"Account"。
    • DataType: 変更された項目の型。文字列の場合は"TEXT"、参照関係の場合は"EntityId"。「取引先」項目のフィード追跡では、取引先名のうちテキスト分の"TEXT"、取引先レコードID分の"EntityId"と、2レコード作成されます。
    • OldValueString: (「取引先」項目の場合)変更前のレコードID
    • NewValueString: (「取引先」項目の場合)変更後のレコードID
    • OldValueLastName: (「取引先」項目の場合)変更前の取引先名
    • NewValueLastName: (「取引先」項目の場合)変更後の取引先名
  • FeedItem.csv
    • ID: Chatter投稿ID
    • PARENTID: Chatter投稿がどのレコードに投稿されたかを示すレコードID(取引先責任者の場合は"003"から始まる)。Chatter投稿がフィード追跡の場合は、値が変更されたレコードのIDを指す。
    • TYPE: Chatter投稿の種類。フィード追跡の場合は"TrackedChange"。

ここで、FeedTrackedChange.csvのFeedItemIdとFeedItem.csvのIDが同じ場合、その行は同じフィード追跡のChatter投稿の内容を指しています。
なので、FeedTrackedChange.csvのFeedItemIdとFeedItem.csvのIDで突合せを行い、一致するFeedItem.csvのPARENTID(=対象レコードID)とFeedTrackedChange.csvのOldValueString(=対象レコードの変更前の値)を取得できれば、データリカバリー用CSVファイルを作成できます。

今回のデータリカバリーに使うCSVファイルに必要な項目、及び対象となるエクスポートデータの項目は以下です。(その他項目はあってもいいですが、インポート時には使いません。)

  • リカバリー対象レコードID
    • FeedItem.csvのPARENTID
  • リカバリーしたい「取引先」項目のレコードID
    • FeedTrackedChange.csvのOldValueString

データインポート

データローダを使用したデータの挿入、更新、または削除 のヘルプを参考に、最初のメニューで"Update"を選択して取引先責任者(Contact)オブジェクトのレコードを更新します。 Step3: Mapping は以下の通り選択します。

Field Column Header Name
(FeedItem.csvのPARENTID部分のヘッダ名) Id
(FeedTrackedChange.csvのOldValueString部分のヘッダ名) AccountId

f:id:mark-hammer:20190602225347p:plain
データローダ Update画面

サンプルを用いた例

ここでは、「取引先責任者レコードIDが"003xxxxxxxxxxx2BBB"の【取引先名】項目が消された」という前提とします。 この場合、FeedTrackedChange.csv、FeedItem.csvは以下のようになります。(IDはサンプル、不要項目は省略)

  • FeedTrackedChange.csv
ID PARENTID TYPE
0D5xxxxxxxxxxx1AAA 003xxxxxxxxxxx2BBB TrackedChange
  • FeedItem.csv
FeedItemId FieldName DataType OldValueString NewValueString OldValueLastName NewValueLastName
0D5xxxxxxxxxxx1AAA Account Text サンプル取引先
0D5xxxxxxxxxxx1AAA Account EntityId 001xxxxxxxxxxx3CCC

上記データから、「取引先責任者レコードIDが"003xxxxxxxxxxx2BBB"の【取引先名】項目が【サンプル取引先】(ID:001xxxxxxxxxxx3CCC)から空データになった」ことが分かります。
ここから、リカバリー対象レコードIDであるFeedItem.csvのPARENTID(="003xxxxxxxxxxx2BBB")とリカバリーしたい「取引先」項目のレコードIDであるFeedTrackedChange.csvのOldValueString(="001xxxxxxxxxxx3CCC")を取り出し、以下のRecoveryData.csvを作成します。

  • RecoveryData.csv
    • ヘッダ名はデータローダでの取引先責任者Updateに使用する項目に合わせています。
Id AccountId
003xxxxxxxxxxx2BBB 001xxxxxxxxxxx3CCC

このRecoveryData.csvを使って、データローダで取引先責任者へのUpdateを実施します。

おわりに

今回は項目履歴管理が使えない状況でデータリカバリをしてみましたが、項目履歴管理が使えればデータローダからのExport1回でリカバリが可能になるため、項目履歴管理 のヘルプを参考に項目履歴管理の設定をすることを強くお勧めします。

*1:が、バックアップも兼ねて「すべてのデータを含める」を選択することを強くお勧めします。

Salesforce資格更新バッジ取得後もWebassessorに反映されないので問い合わせてみた

はじまり

私はSalesforce資格のうち、認定アドミニストレータとPlatform アプリケーションビルダーを持っているので、都度Trailheadで資格更新用のバッジを取得しています。 trailhead.salesforce.com

Spring'19の更新バッジは4/23に全て取得し、認定アドミニストレータは4/26に反映されたのですが、、

Platform アプリケーションビルダーの更新反映がGW明けても来ない。。

とりあえず2週間待っても反映されなければ問い合わせてもよかろう、ということで待ってみたのですが結局反映されず、問い合わせることにしたのでした。

問い合わせてみた

問い合わせ先ですが、以前Webassessorから届いた資格更新反映のメールの中に、

Have Questions? - ご質問がある場合
認定資格プログラムついてのお問い合わせは Webassessor ログイン ID を明記のうえ jcert [at] salesforce.com までお問い合わせください。

とあったので、そのメールアドレスに向けて、

  • Platform アプリケーションビルダーの資格更新が反映されていないこと
  • Webassessor ログイン ID

を記載してメールを送りました。

返事が来た

メールで問い合わせた当日に、担当者より以下の返信が届きました。

  • Webassessor ログインID にリンク済みの Trailheadアカウントでモジュール完了を確認した。
  • セールスフォースドットコム側で更新手続きを行う。完了後に連絡する。

そして、問い合わせ翌日にWebassessorから更新完了の連絡が、さらに翌日にセールスフォースドットコム担当者から更新完了の連絡が届きました。

おわりに

Webassessorでリリース試験を実施していた頃は全てWebassessor上で完結していたので更新反映の問題も少なかったのでしょうが、Trailheadとの外部連携が加わったことにより、更新が反映されない問題もそれなりに発生していそうです。 ただ、Trailheadバッジがリリース試験合格の証拠になるので、「Webassessorに更新が反映されないままリリース試験提供が終了したので、資格が無効になる」ということはおそらくないでしょう。

この投稿が同じような状況になった方の助けになれば幸いです。*1

*1:そもそも発生しないほうがいいのですがね。。