Lwcでその日訪問予定の取引先をマップに表示する


営業支援ツールに関しては、標準オブジェクトでほとんど事足りるsalesforce。
さらに、その日訪問予定の顧客取得し、地図上にマッピングして...
あれ、ホントにこの機能って必要なのかな。
営業したことないから分かりかねますが、
これができれば「LWCで任意の関連レコードとってきて表示させる」
という汎用的な機能のベースになると思って頑張ります。

コードについては株式会社テラスカイ様の
「TerraSkyBase ~テラスカイを支える人とテクノロジーの情報を発信する基地局~」
を参考に(ほぼ拝借して)そこに付け加える形で作成していきます。

アジェンダ

  • 概要
  • ApexClassでレコードを取得
  • HTML
  • JavaScript
  • js-meta.xml
  • 今後の課題

概要

やりたいことととしては冒頭でも触れている通り、
「今日訪問予定の顧客情報を地図へマッピングしたい」です。

ユーザ目線では、
カレンダーに予定を作成すると

マップに表示されるようになります。

より具体的に説明すると、「行動(Event)オブジェクトの開始日(startDateTime)項目が“今日の日付と一致する”レコードの
関連先(What)項目に紐づいている取引先(Account)レコードの情報を取得し、地図コンポーネントを使用して
googleMap上に取得した顧客の住所にピンを打つこと」が今回の目的です。

ApexClassでレコード取得

はじめにApexClassのなかでSOQLを使用し、必要なレコードを取得します。
関連レコードの取得方法を調べるといろいろ出てきますが、下記のコードを参考にしてください。

pubulic with sharing class getTodayAcc
 @auraEnabled(cacheable=true)
 public static List<Event> getAcc(){
   return[
     SELECT AccountId, Account.Name, Account.BillingCountry, Account.BillingState, 
            Account.BillingCity, Account.BillingStreet, Account.Description

            //カスタム項目の場合は、下記のように項目名__cと記述してください。
            //Account.Prefecture__c,Account.City__c

     FROM Event
     WHERE StartDateTime = Today and What.Type IN ('Account')
     ORDER BY StartDateTime 
   ];
 }
}

HTML

次にHTMLを記述します。
テラスカイ様のコードに加えて「zoom-level={zoomLevel}」を記述します。

タグの属性と仕様についてはこちら

<template>
    <lightning-map
        map-markers={mapMarkers}
        selected-marker-value={selectedMarkerValue}
        markers-title="Today's account list"
        onmarkerselect={handleMarkerSelect}
        zoom-level={zoomLevel}
        list-view="auto">
    </lightning-map>
</template>

Javascript

こちらもベースのコードはテラスカイ様より拝借。
加えてHTMLに記述したzoom-levelを指定します。

今日の訪問予定が一件の場合、zoom-levelが未指定だと、マッピング時に自動的に最大ズームされてしまいます。
なので、訪問予定一件(=Eventから取得したレコードが一件)のとき、Zoom-levelを任意の値にセットします。

import { LightningElement, track, wire } from 'lwc';

// getAccounts メソッドのインポート
import getAccounts from '@salesforce/apex/LightningMapExampleController.getAccounts';

export default class LightningMapExample extends LightningElement {
    // 表示するマーカーのリスト
    @track
    mapMarkers=[];

    // 選択しているマーカーの値
    @track
    selectedMarkerValue;

    // 取引先を取得して表示するマーカーを作成
    @wire(getAccounts, {})
    wiredAccounts({ data }) {
        if (data) {
            var markers = [];
            for(var i = 0; i < data.length; i++){
                var acc = data[i];
                markers.push({
                    location: {
                        Country : acc.Account.BillingCountry,
                        State : acc.Account.BillingState,
                        City: acc.Account.BillingCity,
                        Street: acc.Account.BillingStreet
                    },
                    icon : "standard:account",

                    //selectedMarkerValueへ設定される
                    value: acc.AccountId,

                    //マーカークリック時に表示される情報
                    title: acc.Account.Name,
                    description: acc.Description 
                });
            }

            //取得した顧客情報レコードが一つのとき、zoom-Levelを指定します。
            if(data.length == 1){
               this.zoomLevel = 13;
            }
            this.mapMarkers = markers;
        }    
    }  ![Something went wrong]()


    // マーカー選択時のアクション
    handleMarkerSelect(event) {
        console.log(event.target.selectedMarkerValue);
    }
}

js-meta.xml

最後にメタデータを設定します。
isExposedはデフォルトではFalseですが、Trueにしないとカスタムコンポーネントとして使用できません。(編集画面に表示されません)
Tragetで、使用するアプリケーションページを指定します。

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>51.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
    </targets>
</LightningComponentBundle>

今後の課題

① レンダリング
 皆様お気づきかと思いますが、カレンダーへ予定を作成後、タブを切り替えただけでは
 その予定に紐づく顧客が表示されません。毎回ページの再読み込みを手動で行うのは
 イケていませんね!
 
② 条件をいろいろ選べるようにしたい
 といいますのも、きっと一週間以上訪問していない顧客や、売上が高い顧客など、
 何かしら目的をもって訪問すると思いますので、そういった条件でも絞り込めると
 より使いこなしてくれるのではないでしょうか。知らんけど。

③ 自分の現在位置 
 これは言わずもがなですね。すぐに実装できるよう引き続き勉強します。

次回は上記の課題に対する記事を書く予定です!