見出し画像

関連レコードと合計を表示するテーブルの実装(2/5)

やりたいこと

アプリにテーブル形式で関連レコードの明細表示と金額フィールドの合計を表示します。テーブル形式の表示パーツにkintone UI Component v1の部品ReadOnlyTableを利用して、Kintoneライクな外見で表示します。

※本記事では「KUC版読取り専用テーブル」と呼びます。
※サンプルとしてKintoneアプリストアの「営業支援パック」を使用します。

今回のカスタマイズは、全体で120行を超える大きなコードになりますので、手順を分割して全部で5回のシリーズで公開しています。
今回は第2回目です(過去記事は以下のリンクから参照可能です)。

第1回:KUC版読取り専用テーブルの仕組み
第2回:他アプリのデータをKUC版読取り専用テーブルに読み込む(今回)
第3回:金額の3桁カンマ編集とユーザー選択フィールドの編集
第4回:案件名に案件レコードのリンクを貼り付ける
第5回:金額フィールドの合計を計算して表示する


第2回:他アプリのデータをKUC版読取り専用テーブルに読み込む

第2回では、他アプリのデータをKUC版読取り専用テーブルに読み込んで、関連レコードの様に表示する処理を解説します。
サンプルとして、Kintoneアプリストアの「営業支援パック」を使用します。

(1)営業支援パックの関連レコードの仕組み

まず、営業支援パックの関連レコードの仕組みを説明します。
「営業支援パック」では、顧客管理アプリのフォーム上に案件管理アプリの関連レコードが設定されており、顧客管理アプリのフォームで顧客別の案件内容や活動履歴が見れるように設定されています。

営業支援パックのアプリ関連図

「営業支援パック」の顧客管理アプリのフォーム上にある案件管理アプリの関連レコード設定の内容は以下の図の通りです。
◆案件一覧(関連レコード型フィールド)の設定
 参照するアプリ:案件管理(営業支援パック)
 表示するレコードの条件:[レコード番号]=[顧客管理レコード番号]

顧客管理アプリの案件一覧関連レコードの設定

案件管理アプリ側の顧客名(ルックアップ型フィールド)の設定で、顧客名の取得と同時に[顧客管理レコード番号(関連レコード紐付け用)]という数値型フィールドに顧客管理アプリの[レコード番号]を保存しています。
こうすることで、案件管理アプリのレコードを顧客(のレコード番号)別に検索することが可能になっています。

案件管理フォーム設定画面

アプリのレコードを関連付けるKEY項目(検索キー)となるフィールドの設定は、他のレコードと重複しないユニークな値である必要があります。
顧客管理と案件管理のレコード関連付けでは「顧客名」を検索キーにしても関連レコードの検索が出来そうですが、もし「顧客名」に同一名の顧客が存在している場合は、正しい検索結果が得られない可能性があります。

案件管理(営業支援パック)アプリが顧客管理のレコード番号をコピーして保持しているのは、他のレコードと重複しない値だからです。

個人的には、レコード番号をKEY項目に使う方法は避けた方が良いと思います。アプリの移行や統合をするとレコード番号が変わることがあるので、アプリ間のレコード関連性が破たんするリスクがあるからです。

データベース設計では、顧客番号の様なレコードの識別番号を自動採番してKEY項目にするのが定石だと思いますが、kintoneは標準で自動採番機能が無いので、レコード番号を用いているのだと思います。

自動採番機能は、Javascriptカスタマイズで実装が可能です。


(2)アプリの準備

KUC版読取り専用テーブルの動作試験をするアプリを準備します。
kintoneアプリストアの「営業支援パック」で新しいアプリを作成します。
※サンプルデータを含めるをチェックして作成して下さい。

「営業支援パック」では顧客管理、案件管理、活動履歴の3種類のアプリが自動的に作成されます。
※Kinotneの権限がある方は、練習用スペースを作成して、練習用スペースの中で「営業支援パック」のアプリを作成することをお勧めします。

「営業支援パック」の顧客管理アプリのフォーム設定画面を開いて、
案件一覧(標準の関連レコードフィールド)の上にスペースを追加して、
スペース要素IDに「Related_space」を設定して下さい。
※テーブルの表示が乱れない様にスペースは十分な幅を取ってください。
<KUC版読取り専用テーブルの動作試験用アプリ>
・スペース  :要素ID:Related_space

顧客管理アプリのフォーム設定顔面

(3)案件管理アプリのレコードを読み込む処理

それでは、今回(第2回)の本題である、顧客管理アプリのフォーム上で、案件管理アプリのレコードを読み込む処理の手順を考えます。

  1. 関連付けフィールドの初期設定

  2. テーブル先頭カラムの列設定

  3. KUC版読取り専用テーブルの表示関数の設定

  4. 検索クエリーの条件定義と実行

  5. クエリー結果をテーブルデータとして読み込む

  6. KUC版読取り専用テーブルの表示関数の呼び出し

上記の手順1~3のコードは以下の通りです。
ここまでの手順は、初期設定などの準備段階です。

    // 関連付けフィールドの初期設定
    const relatedKeycode = '顧客管理レコード番号_関連レコード紐付け用';
    const relatedItem01  = '案件名';
    const relatedItem02  = '確度';
    const relatedItem03  = '受注予定日';
    const relatedItem04  = '合計費用';
    const relatedItem05  = '商談担当者';
    const resultSpaceId = 'Related_space'; // KUC版テーブル表示スペース
// <---  初期設定ここまで --->

    // テーブル先頭カラムの列設定
    let tblColumns = [
        {title: relatedItem01, field: 'field01'}, // 案件名
        {title: relatedItem02, field: 'field02'}, // 確度
        {title: relatedItem03, field: 'field03'}, // 受注予定日
        {title: relatedItem04, field: 'field04'}, // 合計費用
        {title: relatedItem05, field: 'field05'}  // 商談担当者
    ];

    // KUC版ReadOnlyテーブルの表示
    function createKUCReadOnlyTable(columns, data, spaceElement) {
        const readOnlyTable = new Kuc.ReadOnlyTable({
            className: 'sample-class',
            id: 'sample-id',
            label: 'KUC版読み取り専用テーブル',
            columns: columns,
            data: data,
            rowsPerPage: 5,
            pagination: false
        });
        spaceElement.appendChild(readOnlyTable);
    }

手順4~6のメイン処理で、kintoneイベントのレコード詳細画面、編集画面で実際にKUC版読取り専用テーブルが表示される様に設定します。

手順4:検索クエリーの条件定義と実行

変数appIDに、レコード検索するアプリのIDをセット
変数queryに、レコード検索の条件を記述します
<クエリー条件の書式>
query = '{検索条件}order by [ソートKey] asc/desc][limit 100]'

const appID = 123; //案件管理アプリのID番号
const query = `${relatedKeycode} = "${relatedKey}"
       order by ${relatedItem04} desc limit 100` ; // 検索条件
try {
    const resp = await kintone.api(kintone.api.url('/k/v1/records', true), 'GET', {
     app: appID,
     query: query
});

上記のクエリ条件は、案件管理アプリの[顧客管理レコード番号_関連レコード紐付け用]フィールドの値(relatedKeycode)と、顧客管理アプリで操作中のレコード番号(relatedKey)が等しいレコードを検索します。
order byはソート条件で、検索結果を、費用合計(relatedItem04)の降順(desc)に並び替えるという意味になります。金額の小さい順に並び替えたい場合は昇順(asc)を指定します。
limit は取得するレコード数(初期値は100)で、上限は500です。
省略してもクエリー検索の結果を100件まで取得します。

検索クエリーについて詳しく知りたい方は以下のサイトを参照して下さい

手順5:クエリー結果をテーブルデータとして読み込む

手順5で、テーブルの明細行に他アプリのデータをセットします。
詳しい処理内容は、下記の通りです。

検索結果のレコード数で下記の処理をforEach命令で繰り返します。
これでレコード数と同じ行プロパティのデータが作成されます
<繰り返す処理>
テーブルのindex値と列設定名(fieldレコードの値(Value)5種類の組み合わせを明細1行分のオブジェクトにまとめて、テーブル行プロパティの配列・オブジェクト型変数(tblData)に追加(Push)します。
-------------------------------------------------------
let tblData = []; // テーブルデータ行の初期化
resp.records.forEach( (record, index) => {
tblData.push( {
     index: index,  // 行の番号
     field01: record[relatedItem01].value, // 案件名
     field02: record[relatedItem02].value, // 確度
     field03: record[relatedItem03].value, // 受注予定日
     field04: record[relatedItem04].value, // 合計費用
     field05: record[relatedItem05].value, // 商談担当者
} );

手順6:KUC版読取り専用テーブルの表示関数の呼び出し

手順3で作成したKUC版読取り専用テーブルの表示関数を呼び出します。
関数の引数として、tblColumns(列データ), tblData(行データ), spaceElement(表示スペース)を渡します。

//KUC版読取り専用テーブル表示
createKUCReadOnlyTable(tblColumns, tblData, spaceElement);

非同期処理について

Kintoneのクエリー検索処理は「非同期」に行われますので、クエリー検索の結果を得てから次の処理に進む様に工夫する必要があります。
そうしないと、検索が未完了=テーブルの行プロパティ(data)が空の状態で次の処理に進んでしまい、予期しないエラーが発生するからです。

「注文が来ないレストラン」を例にして「非同期」を説明します。
調理プロセスが「非同期」で接客係と連携できていないと、オーダーしたのに注文が来ない?という状態になります
本来は調理プロセスの完了を待ってから次のステップ「料理を提供」に進むべきですが、「非同期」なので調理プロセスの完了を待たずに次のステップ「料理を提供」を実行してしまうという問題があります。

非同期処理のイメージ「注文が来ないレストラン」

非同期処理のエラー対策として、非同期処理の完了を待ってから次の命令を実行するようにします。
具体的にはレコードの取得と表示の処理の関数の頭でasyncを宣言し、完了するのを待ちたい非同期処理の前にawaitを付ます。

async 関数名()  {
             await  kintone.api….  //非同期処理
}

レコードの取得と表示を非同期対応したコードの構造図を示します
(Noteでは文字色を付けられないので画像にしています)

async/await処理のイメージ

非同期処理のasync/awaitの詳しい使い方は下記リンクを参照して下さい。

手順4~6のJavascriptコード

手順4~6の処理を実行するサンプルコードを下記に掲載します。

    // レコードの取得と表示
    async function fetchAndDisplayRecords(relatedKey, spaceElement) {
        const appID = 123; //案件管理アプリのID番号
        const query = `${relatedKeycode} = "${relatedKey}" order by ${relatedItem04} desc limit 100`; // 検索条件

        try {
            const resp = await kintone.api(kintone.api.url('/k/v1/records', true), 'GET', {
                app: appID,
                query: query
            });

            // クエリー検索結果をテーブルデータとして読み込む
            if (resp.records.length > 0) {
                let tblData = []; // テーブルデータ行の初期化
                resp.records.forEach((record, index) => { 
                    tblData.push({
                       index: index,
                       field01: record[relatedItem01].value, // 案件名
                       field02: record[relatedItem02].value, // 確度
                       field03: record[relatedItem03].value, // 受注予定日
                       field04: record[relatedItem04].value, // 合計費用
                       field05: record[relatedItem05].value, // 商談担当者
                    });
                });
                //KUC版読取り専用テーブル表示
                createKUCReadOnlyTable(tblColumns, tblData, spaceElement); 
            } else {
                spaceElement.innerHTML = '<b style="color: blue;">関連データがありません</b>';
            }
        } catch (error) {
            console.error(error);
            spaceElement.textContent = `データの取得中にエラーが発生しました: ${error.message}`;
        }
    }

    // 動作イベントの設定
    kintone.events.on(['app.record.edit.show', 'app.record.detail.show'], function (event) {
        const spaceElement = kintone.app.record.getSpaceElement(resultSpaceId);
        if (!spaceElement) {
            console.error('Space element ' + spaceElement + ' not found.');
            return event;
        }
        spaceElement.innerHTML = ''; // 結果表示スペースの初期化
        const relatedKey = kintone.app.record.getId();    // 検索キー(レコード番号)の取得
        fetchAndDisplayRecords(relatedKey, spaceElement); // 関連レコード検索とテーブル表示
        return event;
    });

表ヘッダーの背景色を変更する

標準の関連レコードと区別できる様に表ヘッダー背景色を緑にします。
kintone UI Componentの各コンポーネントは、専用のCSSプロパティを持っています。
以下にKUC版読取り専用テーブルのテーブルヘッダーの背景色を緑色にする
CSSコードの例を掲載しておきます。
アプリの設定>JavaScript / CSSでカスタマイズの画面のCSSファイルの所にアップロードして追加して下さい。

/* KUC版読み取り専用テーブル
   CSSプロパティの指定サンプル */
#sample-id {
  /* テーブルヘッダーの背景色 */
  --kuc-readonly-table-header-background-color: green;

}

実行結果

サンプルコードでKUC版読取り専用テーブルを作成した実行結果のイメージは以下の通り(赤枠で囲んだ部分がサンプルコードの実行結果)です。
標準の関連レコードと同じレコードを取得出来ました。

第2回の実行結果

第2回の目標「他アプリのデータをKUC版読取り専用テーブルに読み込む」が実現出来ましたね。
しかし、合計費用列の数字が3桁カンマ区切りで表示されてない、商談担当者の列(ユーザー選択フィールド)が配列データのため正しい値が表示されていない、などの問題が残ってます。
この問題は、次回(第3回)で対応方法を説明する予定です。


次回の予告

今回の「他アプリのデータをKUC版読取り専用テーブルに読み込む」で実用的なコードになってきましたが、合計費用や商談担当者の列表示がまだ完全ではありません。

「第3回:金額の3桁カンマ編集とユーザー選択フィールドの編集」では、金額の3桁カンマ編集と、ユーザー選択フィールド(配列型)から値を取り出して表示する仕組みを解説します。

今回も、最後まで読んで頂いてありがとうございました。

もし、本記事の内容に興味があり「続きを読みたい」という方がいらっしゃいましたら「スキ」や「フォロー」を頂けると励みになります。
どうぞよろしくお願いします。


よろしければサポートお願いします! いただいたサポートは、note記事制作の活動費に使わせていただきます!