tyoshikawa1106のブログ

- Force.com Developer Blog -

SFDC:プレミアサポートとアクセラレータを利用してみました

プレミアサポートとアクセラレータを利用してみました。

f:id:tyoshikawa1106:20191001074729p:plain

Salesforceの早期導入、定着化、ROIの実現をエキスパートが支援 - セールスフォース・ドットコム | セールスフォース・ドットコム


過去にイベントのブースでもらった資料。
f:id:tyoshikawa1106:20190726064506j:plain

f:id:tyoshikawa1106:20190726064529j:plain

定着化支援

f:id:tyoshikawa1106:20190726064608j:plain

アクセラレータ

f:id:tyoshikawa1106:20190726064613j:plain

テクニカルサポート

f:id:tyoshikawa1106:20190726064617j:plain


アクセラレータによる 1 on 1の技術支援とプレミアサポート利用者向けのWebセミナー、それとテクニカルサポートへの問い合わせ時の一時応答の時間短縮が主な利用目的になると思います。
f:id:tyoshikawa1106:20190726064741j:plain


アクセラレータについては先日のSalesforce World Tour Tokyo 2019でもミニセッションをやっていました。
f:id:tyoshikawa1106:20190925140654j:plain

f:id:tyoshikawa1106:20190925140833j:plain

プレミアサポートの契約について

プレミアサポートは契約しているライセンス数に応じて料金が決まります。
ライセンス数は組織全体ではなく製品毎に判断されます。合わせて組織全体でのプレミアサポート契約ではなく製品ごとのプレミアサポートライセンスを契約する形です。
→ SalesCloudのプレミアサポート / Pardotのプレミアサポートという形

テクニカルサポートの一次応答時間の短縮

プレミアサポートを契約するとサポート問い合わせ時の一次応答時間が8時間以内になります。通常は最大で2日間。
一次応答というのは下記工程の④の部分に辺ります。

①サポート問い合わせ
②問い合わせのカテゴリに合わせて担当部門に振り分け
③サポート担当者が問い合わせ内容を確認
④問い合わせユーザに通知メール送信 ※1時応答
→「問い合わせ内容を確認しました。質問内容応じて担当エンジニアをアサインします。」的なシステムメールが届きます
 ※エンジニアアサインまでは最大2〜5日
⑤他の問い合わせ内容と比較して対応の順序決め
⑥問い合わせの1次回答
⑦状況に応じてやりとり
⑧解決
⑨問い合わせクローズ
⑩利用者アンケート

1次応答と1次回答は別のため、問い合わせ時には意識しておくと良いと思います。1次回答までは2〜3日かかるぐらいの認識で待っていれば慌てずに済むと思います。

アクセラレータ

アクセラレータは1 on 1で製品の使い方をレクチャーしてくれるサポートです。
基本的には自由時間でのやりとりではなく予め用意されているコースを解説を受けながら進められるイメージです。
※やりとりはWebミーティングのツールを利用します。

今回受けてみたPardotのB2BMAツールのコースの場合はこんな感じ。
・[1回目:45分] 初回ヒアリング。組織の状況等の確認
・[2回目:60分] 資料を見ながらツールの基本的な使い方の解説

用意されたコースの方は上記の時間で実施されました。
2回目完了後ですが、一定期間の間メールで自由に問い合わせ対応を受けてもらえるようになっています。(受講コースの内容に関係する問い合わせ)


■アクセラレータ利用の際に意識すること
①初期設定は完了させておく
・初期設定周りはアクセラレータプログラムの範囲外となるためサポートへ問い合わせで事前に完了させておく必要があります。
②利用時のスケジュール調整
・アクセラレータは1on1で対応頂けるサポートのため事前にスケジュール調整が必要になります。混み合っている場合もありますので遅くても受けたい日の一週間前ぐらいには連絡しておくと良いと思います。
③技術的な部分はテクニカルサポートへ確認
・基本的な使用方法以外の技術的な質問の場合は内容によってはアクセラレータ側では対応できないためサポートの方へ問い合わせて調べてしてもらいます。サポートへの問い合わせの時間も考慮して進めていくと良さそうです。


とりあえずプレミアサポートで利用したのはこの2つ。アクセラレータは初めて利用したのでこういう流れだったのかという部分がいくつかありました。時間のあるときにプレミアサポート向けのWebセミナーも見てみたいと思います。

SFDC:Salesforce World Tour Tokyo 2019に参加しました

2019年 9月 25日(水)- 26日(木)に ザ・プリンス パークタワー東京と東京プリンスホテルで開催されたSalesforce World Tour Tokyo 2019に参加しました

Salesforce Success Anywhere World Tour | セールスフォース・ジャパン

Day 1

はじめての Salesforce [M1]@Room4 / Room5 (PPT)

8:30からのモーニングセッションです。モーニングセッションに参加する場合、受付時間が8時からになるので空いてる時間に手続きできて良いと思います。朝ごはんも頂けました。


セッション内容はセールスフォースとはという話から実際の利用をイメージしたデモンストレーションです。


B to BとB to Cの両方でサポート可能な話もありました。


デモンストレーションではリードの使い方やダッシュボードの作成例を紹介してくれました。Lightningでの詳細ページでの3列表示は想像より使いやすそうだったのが印象に残りました。


Pardotをつかったマーケティングのデモも良かったです。セミナー、展示会、資料請求フォームでリードを獲得、Pardotでメールを送付という手順は便利そうでした。(セミナーや資料請求フォームをやっている必要はありますが)


30分のセッションでしたがモーニングセッション良かったです。

基調講演:A Celebration of Trailblazers [KN]@Keynote Room (PPT)

9:00からは基調講演を見に行きました。


小出CEOと米セールスフォース・ドットコムのCTOのパーカーハリスの話が聞けました。


特定の業界向けの新製品の発表もありました。


導入事例企業の三越伊勢丹ホールディングス社とKubota社の役員の方のお話も聞けました。


どちらの話も面白かったのですが、個人的にKubota社の話で出てきた利用しているSalesforce製品の話でほとんどの製品が出てきていたのが印象に残りました。

EXPO会場

キーノートのあとです。今回はセッションとセッションの合間に時間があるのでEXPO会場を見に行きました。ミニセッションやスタンプラリーなどのイベントも行われていました。

The Future of AI [SS1]@Keynote Room (PPT)

EinsteinとAIのセッション。米セールスフォースのAIの責任者の話が聞けました。


最後にQ&Aの時間があったのですが、そこで出たEinsteinの学習データは何件必要かという質問で1,000件という話があったのが印象に残りました。ずっと数万件レベルの学習データが必要なのかと思っていました。

Activist CEO ポスト資本主義時代のリーダーの条件 [SS2]@Keynote Room (PPT)

CEOの方々の話が聞けてよかったです。

EXPO ミニセッション

Einsteinの導入の流れを見ることができました。予測ビルダーが使われるタイミングとかを見れてよかったです。

Einsteinのスコアはカスタム項目にセットするという部分も知れて良かったです。


サステナビリティ​:持続可能な成長と社会変革への挑戦 ​ [SS3]@Keynote Room (PPT)

YOSHIKIのセッション。内容は環境問題についてです。YOSHIKI見れてよかったです。


セッション終了後にクリスタル・ケイのライブも見れました。
[fid:tyoshikawa1106:20190925174641j:plain:w300]


次の日の準備があったのですぐに帰りましたが、Day1のラストで軽食が出てネットワーキングパーティーもありました。次回はゆっくり楽しみたいです。

Day 2

午後に登壇させてもらったセッションの準備(練習とか資料修正とか)があったので2日目は午後から参加。お昼ごはんは会場で頂けました。


また少し時間があったのでTrailhead zoneで限定バッチ取得も済ませました。

成長企業の必須アイテム マーケティングオートメーション Pardot [1-5]@Room1 (PPT)

2日目最初のセッションはPardotのセッション。


またPardotのセッションでは株式会社リバネス(Leave a Nest Co., Ltd. )の方がPardotを運用してみた知見をお話し頂けました。個人的に一番SWTTのセッションで一番印象に残ったセッションで実際に5年間運用してみての知見やPardotとEinsteinを組み合わせて利用してみた話など知りたかった話を聴くことができました。

セッションスライドも公開して頂けています。Pardotを利用している人にとってはすごく為になるスライドだと思います。

リバネスCIO George プレゼンアーカイブ - Google スライド


Pardotのセッションのあとはプリンスホテルの会場に移動しました。こちらは技術系セッションが中心の会場となっています。


SWTTお馴染みのTrailhead Zoneにも行きました。


同じ時間に複数セッションが開催されるのでチラッと見ては移動してと会場を回りました。2日目の最後は自分のセッションでApex周りの話をさせてもらうことができました。

SFDC:Salesforce World Tour Tokyo 2019のDeveloper Theatreで登壇させて頂きました - tyoshikawa1106のブログ


Day2はこんな感じ。セッション登壇も終わりネットワーキングパーティーはゆっくり楽しむことができました。


Salesforce World Tokyo 2019、二日間楽しい時間を過ごすことができました。

SFDC:Salesforce World Tour Tokyo 2019のDeveloper Theatreで登壇させて頂きました

Salesforce World Tour Tokyo 2019の2日目、Developer Theatreの17:00からのセッションで登壇させて頂きました。SalesCloudとApex開発についての内容で、セッション時のスライドはこちらです。


アレ話そうコレ話そうと付け足していったら時間ギリギリになってしまいましたが参加できて良かったです。


SFDC:日時型をSOQLクエリで条件指定するときに注意すること

日時型をSOQLクエリで条件指定するときに注意することについてです。例えば作成日を条件に取得するようなケースがあたります。

f:id:tyoshikawa1106:20190919071350p:plain


日時型はSalesforceを普通に操作するような場面では下記のように表示されます。

「2019/09/19 7:10」


ですがApexなどでシステム上の値としては次の形で保持されています。GMT表記となり日本時間から9時間ずれた値として表示されます。

「2019-09-18T22:10:49.000+0000」

f:id:tyoshikawa1106:20190919071559p:plain

日付型や日時型の値を今日や昨日というように取得したい場合は日付リテラルの仕組みで取得できます。
f:id:tyoshikawa1106:20190919072318p:plain


「 WHERE CreatedDate = TODAY」というような記述ができます。これは実行ユーザのタイムゾーンに合わせて取得してくれるようです。

SELECT Name, CreatedDate FROM Account WHERE CreatedDate = TODAY ORDER BY CreatedDate

f:id:tyoshikawa1106:20190919072517p:plain

f:id:tyoshikawa1106:20190919072728p:plain


注意が必要なのは日付リテラルではなくDAY_ONLYなどの日付関数を利用する場合になります。
f:id:tyoshikawa1106:20190919073221p:plain


日付関数は協定世界時 (UTC)の値で返します。日本時間の9時より前の時間値は9時間ずれで前日扱いとなります。

WHERE DAY_ONLY(CreatedDate) =: targeDate
本日を条件に取得した場合

f:id:tyoshikawa1106:20190919073551p:plain

f:id:tyoshikawa1106:20190919073722p:plain

前日日付で取得する方法

f:id:tyoshikawa1106:20190919073838p:plain

f:id:tyoshikawa1106:20190919073854p:plain

検証コード
// 前日日付で実行
Date targeDate = System.today().addDays(-1); 

List<Account> accounts = [SELECT Name,CreatedDate FROM Account WHERE DAY_ONLY(CreatedDate) =: targeDate ORDER BY CreatedDate];

System.debug('取得結果 = ' + accounts.size());
for (Account account : accounts) {
    System.debug(account.Name + ' : ' + String.valueOf(account.CreatedDate));
}


上記のとおり日付関数だと作成日が本日のものでも前日の日付で取得される状態となります。開発者ガイドにも表記されていますが日付関数を利用してユーザのタイムゾーンに合わせるときには「convertTimezone」関数を使用します。

f:id:tyoshikawa1106:20190919074248p:plain


これで日付関数でもユーザのタイムゾーンに合わせてデータを取得できます。
f:id:tyoshikawa1106:20190919074400p:plain

その他の対応方法

頻繁に条件指定で使用する場合などでApex側でタイムゾーンを意識して処理を実装するのが大変な場合は数式で日付型に変換した値を用意すると便利かもしれません。

f:id:tyoshikawa1106:20190919075112p:plain


次のように当日日付として取得できました。
f:id:tyoshikawa1106:20190919075247p:plain

おまけ

日時型の項目はString.valueOf処理で文字列に変換するとユーザのタイムゾーンで表示されます。
f:id:tyoshikawa1106:20190919075540p:plain

関連

SFDC:テストクラス判定できるTest.isRunningTest処理をつかったメンテナンス性の向上について

Apex開発でTest.isRunningTest処理を使ったメンテナンス性の向上についてです。
f:id:tyoshikawa1106:20190916103758p:plain

Salesforce Developers


Apex開発を行ったときにはテストクラスの作成が必要になります。テストクラスをきちんと作成することで既存処理への予期せぬ影響に気づけたり、実装した箇所の考慮漏れや実装ミスに気づくことができます。


・・・ですが処理の内容によってはテストクラスが作成しずらい場面がでてきます。


たとえば下記のような処理です。

// 次回スケジュールバッチ実行時間取得
Datetime nextBatchTime = Datetime.now().addMinutes(5);
// 次回スケジュールバッチ実行時間登録
OpportunityChatterPostBatchSchedule cls = new OpportunityChatterPostBatchSchedule();
String jobName = 'OpportunityChatterPostBatchScheduleJob_' + nextBatchTime.format('yyyyMMddHHmm');
String sch = nextBatchTime.format('0 m H d M ? yyyy');
// スケジュールバッチ登録
System.schedule(jobName, sch, cls);


上記の処理をそのままテスト実行すると下記のエラーが発生します。

System.AsyncException: "OpportunityChatterPostBatchScheduleJob_201909161032" という Apex ジョブはすでに実行がスケジュールされています。 3483
Class.OpportunityChatterPostBatch.finish: line 54, column 1

f:id:tyoshikawa1106:20190916104136p:plain


スケジュールバッチ処理実行時にジョブ名をユニークにするために日時を付与していますが、テストクラスで同じタイミングで複数呼び出しされることでユニークにならなくなってしまいました。こうした処理がある場合の対処方法として、テストクラスの実装を諦めるという手段もありますが、Test.isRunningTest処理を利用することできれいに解決できます。


Test.isRunningTest処理は「現在実行中のコードが、テストメソッドに含まれているコード」かを判別するための処理です。
f:id:tyoshikawa1106:20190916104550p:plain


これで下記のような書き方が可能となります。(if処理では「!」をつけてテストではない場合にという判定にできる)

if (!Test.isRunningTest()) {
    // テストでない場合にスケジュール登録処理を実行
    System.schedule(jobName, sch, cls); 
}


スケジュール登録処理のみスキップできるようになりテストクラスを開発できるようになります。ですが上記の判定方法だとif判定内の処理は絶対に実行できないためカバー率低下が発生します。この問題を回避するために下記の記述にした方が良いと思います。

// スケジュールバッチ登録
String nextBatchJobId = (!Test.isRunningTest()) ? System.schedule(jobName, sch, cls) : '';

f:id:tyoshikawa1106:20190916105754p:plain


テストクラスの実行判定は行単位で識別されるのでこの書き方ならカバー率低下を回避することができます。また必要に応じてテスト処理の場合のみ任意も戻り値を指定することも可能になります。


このようにTest.isRunningTest()をうまく利用することでテスト実装ができない問題を回避しつつ正しくテストを行い品質とメンテナンス性を向上することができると思います。

関連

SFDC:Apexバッチの数分おきに繰り返し実行を試してみました

Apexバッチを指定の時間や定期的に実行したい場合は、スケジュールバッチの仕組みを使って対応します。スケジュールバッチは「implements Schedulable 」を宣言したクラスを用意することで作成できます。

Scheduleクラス

f:id:tyoshikawa1106:20190916082622p:plain

Connectクラス

f:id:tyoshikawa1106:20190916082421p:plain


上記のようなクラスを用意するとApexクラスの設定で「Apex をスケジュール」の仕組みが利用できるようになります。
f:id:tyoshikawa1106:20190916082810p:plain


こちらがApexスケジュールの設定画面です。
f:id:tyoshikawa1106:20190916082918p:plain


開始日と終了日を設定でき、実行対象の曜日と時間を指定できます。一日一回のスケジュール実行という要件の場合はこちらの設定画面のみで対応できます。注意が必要なのは数分単位で実行したい場合です。Apex をスケジュールの設定では1時間単位でのみ実行時間を指定できます。そのため5分間隔や15分間隔での実行はサポートされていません。今回は設定ページのみでは実現できない数分間隔での実行方法を紹介します。


Apexバッチの処理は「コンストラクタ」「start」「execute」「finish」のメソッドで構成されます。「start」のメソッドで対象となるデータを取得します。「execute」のメソッドでメインの処理が実行されます。バッチサイズの件数分に分割して繰り返し処理を実行します。(バッチサイズ200件で1000件対象データがある場合は200×5回繰り返し実行されます。)「finish」のメソッドが最後に一回呼び出されて処理を実行します。

Apexバッチクラス

f:id:tyoshikawa1106:20190916083634p:plain


最後に実行される「finish」メソッドで次のスケジュールバッチを登録することが可能です。
f:id:tyoshikawa1106:20190916084102p:plain


スケジュールバッチは「System.schedule(jobName, sch, cls);」の処理で登録できます。ジョブ名、スケジュール実行時間、対象のスケジュールバッチクラスが引数として必要です。

/**
 * Finish
 */
public void finish(Database.BatchableContext BC) {
    // 次回スケジュールバッチ登録判定
    if (this.isNextBatch) {
        // 次回スケジュールバッチ実行時間取得
        Datetime nextBatchTime = Datetime.now().addMinutes(5);
        // 次回スケジュールバッチ実行時間登録
        OpportunityChatterPostBatchSchedule cls = new OpportunityChatterPostBatchSchedule();
        String jobName = 'OpportunityChatterPostBatchScheduleJob_' + nextBatchTime.format('yyyyMMddHHmm');
        String sch = nextBatchTime.format('0 m H d M ? yyyy');
        System.schedule(jobName, sch, cls);
    }
}

ジョブ名はユニークにする必要があります。Apex処理で自動登録する場合は実行日時などを追加するのが良さそうです。
スケジュール実行時間は文字列で宣言します。引数の渡し方はいくつか用意されていますが任意の時間に一回実行したい場合は下記の引数を渡します。

(秒 分 時 日 月 ? 年)

時間は24時間表記です。DateTime型の.formatでは「hh:mm:ss」と宣言できますが「hh」を「HH」と大文字で宣言することで24時間表記になります。また「H」とのみ宣言することで0埋めがされなくなります。


この方法で実行した結果がこちらです。約5分おきに実行されています。
f:id:tyoshikawa1106:20190916084729p:plain


検証時ですが20:00など切りの良い時間から開始しましたが一晩立つ頃には1分ズレが発生しました。こればバッチ実行は宣言してすぐに実行されない(一度キューに貯まる)ことと、Finsh時点での日時を基準に5分後で登録したので処理に時間がかかることで1分間のズレが発生したためと思います。


5分おきに実行する場合はこうしたズレも考慮した方が良いみたいです。またバッチのキューは一度に登録できる件数に上限があります。夜間バッチなど処理が多く実行される場合は登録をスキップするなどの考慮も必要になると思います。

補足

上記サンプルのバッチクラスでは下記の「Helper」クラスと「Dao」クラスを宣言しています。目的に合わせてクラスを分けるとメンテがしやすいと思います。

Helperクラス

f:id:tyoshikawa1106:20190916085723p:plain

Daoクラス

f:id:tyoshikawa1106:20190916085745p:plain

利用例

今回の数分単位でのバッチ実行ですが、例として新規商談を登録した際にChatterに投稿すると行った場面で利用できます。社内ユーザが新規商談を登録した際には何も気にせずプロセスビルダーでそのまま対応できますが、Force.comサイトで作成したフォーム経由で登録された場合など社外ユーザの作成時には通常Chatter投稿ができません。Apexのスケジュールバッチの場合は管理者権限で実行できるので、社外ユーザ権限で商談作成できる仕組みを構築したいときなどに利用できると思います。

関連・参考

SFDC:Apexで日付の曜日部分を取得する方法

Apexで日付の曜日部分を取得したいときは、一度日時型に変換して「.format('E')」の処理で取得できます。

f:id:tyoshikawa1106:20190907164758p:plain

// 月曜日
Datetime day1 = Datetime.newInstance(2019, 9, 9);
System.debug(day1.format('E'));

// 火曜日
Datetime day2 = Datetime.newInstance(2019, 9, 10);
System.debug(day2.format('E'));

// 水曜日
Datetime day3 = Datetime.newInstance(2019, 9, 11);
System.debug(day3.format('E'));

// 木曜日
Datetime day4 = Datetime.newInstance(2019, 9, 12);
System.debug(day4.format('E'));

// 金曜日
Datetime day5 = Datetime.newInstance(2019, 9, 13);
System.debug(day5.format('E'));

// 土曜日
Datetime day6 = Datetime.newInstance(2019, 9, 14);
System.debug(day6.format('E'));

// 日曜日
Datetime day7 = Datetime.newInstance(2019, 9, 15);
System.debug(day7.format('E'));

'月'、'火'ではなく'Mon'や'Thu'という形で取得できるのでそこから日本語表記には別途変換処理が必要になります。
f:id:tyoshikawa1106:20190907164929p:plain


変換用の共通クラスを用意しておくと使い回せると思います。