ぐるなびの社内システムで活用しているSalesforceのナレッジ取得と課題解決の工夫

TOP

こんにちは、Salesforceを活用した営業支援システムを担当している松山です。
私の所属するチームでは、同システムを社内でより効果的に活用するための開発・改修をメインに行っています。
私自身は、2019年1月からぐるなびに入社して、Salesforceに関わってまだ1年ほどの新米です。現在もSalesforceについて日々勉強し、社内のユーザが使いやすいシステムを目指し、試行錯誤を繰り返しています。

今回は、どのようにぐるなびのシステムにSaleforceを活用し、Salesforceの活用技術向上に取り組んでいるかを紹介したいと思います。

Salesforceとは

Salesforceは、セールスフォース・ドットコム社が提供する、顧客管理ソリューション。

f:id:gnavi_developers:20200430110924p:plain
Salesforceとは
マーケティング、営業、コマース、サービスなどすべての部署で、顧客一人ひとりの情報を一元的に共有できる統合CRMプラットフォームです。

出典:株式会社セールスフォース・ドットコム ホームページ(2020/06/02 アクセス)

中堅・中小から大手まで、世界で15万社以上の企業が、Salesforceでビジネスを拡大しているそうです。

ぐるなびとは

株式会社ぐるなびは、飲食店の情報を集めたウェブサイト「ぐるなび」を運営する企業です。

“日本発、世界へ”を基本方針に、日本の食文化を発信することを理念としています。パソコン・スマートフォン等による飲食店等の情報提供サービス、飲食店等の経営に関わる各種業務支援サービスの提供その他関連する事業を行っています。

f:id:gnavi_developers:20200617091110j:plain
ぐるなびPC版トップページ

ぐるなびでは、営業が全国の飲食店をサポートする営業活動を行っていますが、そのデータをSalesforceに入力し、一元管理しています。そうすることにより、適切な営業活動のサポートを実現しているのです。ぐるなびではこのSalesforceを用いた営業支援システムを社内で、開発・機能追加しています。
それを実現するために行った取り組みを紹介していきたいと思います。

Salesforce開発の内製化に向けた取り組み

どんなシステムでも、会社内部で知識や経験を共有しながら、自社の目的に合わせて最大限に活用していくことが重要ですよね。 元々ぐるなびはSalesforceに特に力を入れている企業ではありませんでした。
一からエンジニアを育て、自社内でシステム開発を行うためには、大変な労力とお金がかかります。 ぐるなびでは、その点をいかにして解消してきたのかを簡単に紹介します。

Salesforce研修の有効活用

セールスフォース・ドットコム社が提供する研修があります。ぐるなびではそれを開発メンバー一人ひとりに受講させることで、新しい技術を学ぶ際の抵抗やハードルの高さ、学習意欲の維持を克服してきました。

f:id:gnavi_developers:20200422185359p:plain
Salesforce研修

Trailheadの活用

Trailheadとは、セールスフォース・ドットコム社が無料で提供しているe-learningサービスで、誰でも利用可能となっています。個人個人のペースでSalesforceについて学ぶことが出来ます。
Salesforceの知識だけではなく、ビジネスマナーに関することからIT産業の歴史など多岐にわたります。 皆さんも是非一度はアクセスして、問題にチャレンジしてみてください。

f:id:gnavi_developers:20200422185429p:plain
Trailhead

Trailhead コンテスト2019への参加

Trailheadがいかに優秀なe-learningサービスであろうとも、個人で学習を進めていくため、人によってモチベーションの違いが徐々に現れていきました。
それを改善するために参加したのがTrailhead コンテスト2019です。

Trailheadコンテスト2019とは、セールスフォース・ドットコム社が2019年に企画・実施したコンテストで、決められた期間の中で、上記Trailheadで取得したバッジ数を競うものです。ぐるなびはSalesforceに関わるメンバーが少数だったのですが、下記のような素晴らしい結果を収めることが出来ました。

f:id:gnavi_developers:20200422185420p:plain
Trailheadコンテスト2019

出典:株式会社セールスフォース・ドットコム Facebookページ(2020/06/02 アクセス)

個人戦で優勝・3位入賞、企業戦のミッドマーケット部門で2位に入賞しました。

Salesforce開発中に発生した課題事例

ではシステム開発を社内で行う内製化の話をしたので、Salesforceを開発していく上で発生した課題を簡単に紹介していきたいと思います。Salesforceを活用する上で同じ課題にぶつかった時は、ぜひ参考にしてください。

1.トリガー処理におけるオブジェクト間のリレーション作成
2.商談の金額と商談商品の合計金額の自動連動
3.ガバナ制限

1.トリガー処理におけるオブジェクト間のリレーション作成

Salesforceではオブジェクトがあり、そこにデータを登録する際にはBeforeトリガーとAfterトリガーが下記の図に順番で起動されます。

f:id:gnavi_developers:20200422185403p:plain
オブジェクトとはリレーショナルDBのテーブルと同義

  • 商談オブジェクトにデータを登録する際に次に起こす行動データとして、Todoオブジェクトにもデータを登録したい
  • ただし、登録するTodoは商談と紐づけておきたい

ここで、上記の仕様を実装したい場面がありました。
私もそうだったのですが、OracleやPostgreSQLに精通している方たちならこう考えるのではないでしょうか?

  • ①Beforeトリガーで、商談オブジェクトとTodoオブジェクトに関連性を持たせる
  • ②オブジェクト登録で、そのデータを登録する

f:id:gnavi_developers:20200422185412p:plain
想定する登録後のレコード状態

【発生した課題】
①Beforeトリガーに上記の処理を記述して、実行してみたところ、Todoオブジェクトの商談IDに値が設定されず、商談オブジェクトとTodoオブジェクトが関連性を持たない状態でそれぞれのデータが登録されました。

f:id:gnavi_developers:20200422185422p:plain
関連性のない状態

【原因】
ここからはSalesforceの仕様になります。
Salesforceのすべてのオブジェクトにはレコードそれぞれ識別できる一意のIDがオブジェクト登録時に振られます。そして、他オブジェクトと関連性を持たせるにはこのIDを用いる必要があるのです。

よって、①Beforeトリガーの時には、商談オブジェクトに登録するデータのIDが振られていないため、追加で登録するTodoオブジェクトに商談オブジェクトの関連性を持たすことが出来ないのです。

【解決策】
①Beforeトリガーに記載していた処理を③Afterトリガーに移行します。
そうすることにより、②オブジェクト登録が完了しているため、商談オブジェクトのIDが振られているので、Todoオブジェクトと関連性を持たせることが出来るようになります。

これは実装後に単体テストや結合試験を行えば、すぐに発見できるものですが、可能であればコーディングの段階で認識しておきたい仕様です。。。

【まとめ】
トリガーでAオブジェクトとBオブジェクトの新規データ登録時に、関連性を持たせたいときは、 処理はAfterトリガーに記述しないと、関連性を持たせることが出来ません。

2.商談の金額と商談商品の合計金額の自動連動

では続いて、商談オブジェクトと商談商品オブジェクトについての課題事例を紹介していきます。
商談オブジェクトと商談商品オブジェクトの関係性は以下の通りとなっています。

f:id:gnavi_developers:20200422185352p:plain
商談オブジェクトと商談商品オブジェクトの関係性

さらにSalesforceの標準機能として、下記の仕様があります。

  • 商談.金額には紐づいている商談商品の金額×個数の合計値が設定される

例)

商談A 商談商品B 商談商品C
金額400円 金額100円 金額200円
商談商品B×2+ 商談商品C×1 個数2個 個数1個

ではここで実現したい追加機能を紹介します。

  • 商談商品の個数が1個よりも多い商品は個数をすべて1個に
  • 数量分だけ商談商品のレコードを複製するボタン(以下一括複製ボタン)を実装する


※こちらは他システムに連携するデータなのですが、他システム側の制約として、『商談商品はすべて1個で登録されていること』があるため、このような機能の実装が求められました。


上記の例において、一括複製ボタンを押下すると下記のようになる想定です。

商談A
(変更なし)
商談商品B 商談商品B-1
(追加レコード)
商談商品C
金額400円 金額100円 金額100円 金額200円
商談商品B    × 1 + 商談商品B-1 × 1 + 商談商品C    × 1 個数1個 個数1個 個数1個

では、これを実現するために下記の処理を実装しました。

  • ①商談商品B-1のレコードを新規追加する
  • ②商談商品Bの個数を1個に更新する


【発生した課題】
商談レコードの金額履歴に、下記のレコードが作られてしまいました。

  • 400円⇒500円の商談金額に変更
  • 500円⇒400円の商談金額に変更

【原因】
①の処理で商談金額が一時的に500円に変更されます。
その後②の処理で商談金額が400円に戻るため、意図せぬ変更履歴が作成されてしまいました。

※Salesforceの仕様として、データの新規作成と更新は同時には行えないようになっています。
なので、①と②の処理を同時には行えないようになっています。

【解決策】
処理の実行を下記のように変更します。

  • ①個数0個、金額100円の商談商品B-1のレコードを新規追加する
  • ②商談商品BとB-1の個数を一括で1個に更新する

こうすることによって、商談金額は400円のままなので、商談金額の履歴は作成されないように制御することが出来ました。

【まとめ】
商談商品オブジェクトのデータを修正する追加機能を実装する際には、商談オブジェクトの金額にも自動的に影響を与えるため、処理の順番には注意を払う必要があります。

3. ガバナ制限

Salesforceで開発を行う場合、ApexというSalesforce独自のプログラミング言語を使用して機能を実装し、それをSalesforceのプラットフォーム上で実行させることになります。

ガバナ制限とは、その実行時にプラットフォーム上にあるDBやメモリなどのリソースを、大きく占有するような処理が行われないように設けられている制限のことで、この制限に引っかかる処理を実行してしまうとエラーが発生してしまいます。

なぜこのような制限があるのかというと、Salesforceは複数の顧客ユーザがリソースを共有して利用する、マルチテナント環境で実行されているため、1つのテナントでリソースを独占させないためにあります。

ここではガバナ制限に引っかかった簡単な事例を紹介します。

【発生した課題】
トリガーの処理の中で、LimitExceptonが発生しました。
※これは1つの処理の中でSQL実行処理が100回を超えると発生する例外です。

【原因】
APEXクラスの処理のfor文の中で、繰り返しSQL実行処理をしていました。
そのために、一度のトランザクション処理の中で呼び出せる限界回数を超えてしまいました。

【解決策】
for文の中で記載していたSQL処理を、for文の外に移行し、一回にまとめることで例外が発生しなくなりました。

【まとめ】
一度の処理の中で、呼び出せるSQL回数には限界値があるため、SQL実行処理などは、for文の中ではなく、for文の外に記載する必要があります。

最後に

ここまで、ぐるなびがいかにしてSalesforceを活用してきたか説明しました。しかし、私たちぐるなびもSalesforceを100%活用しきれているとは思っていません。

さらなる活用のためには、Salesforceを活用している他の皆さんとの、知識・交流が必要不可欠であると思っています。このブログを読むことがきっかけで、Salesforceを知り、勉強会や研修など触れ合う機会が生まれていったら幸いと思います。

最後まで読んでくださり、ありがとうございました。

※6/17追記 :商談商品の金額と個数の表現を一部修正しました

松山
2019年1月に入社。使用言語はJava、APEX、PHP、C+など。
いつかは自分のゲームを開発してみたいです。