[Kintone]関連するレコードの合算値を表示する方法[コピペOK]

やりたいこと

複数のレコード間で項目の値を共有する方法 [コピペOK]の記事とロジック的には同じ。
kintoneで各レコードの合計数値を集計するには集計機能を利用しなければいけない。しかし、いちいち集計をさせるのは面倒なため、詳細画面に表示したい。

ソースコード

/**
 * 【機能】
 *   関連レコード間で対象フィールドの合計値を共有する
 * 
 * 【処理】
 *   ・フィールド「CONDITIONAL_FIELD_ID」の値が一致する関連レコードを一括取得する
 *   関連レコードのフィールド「SOURCE_FIELD_IDS[i]」の合算値をフィールド[TOTAL_FIELD_IDS[i]]に設定する
 *   関連レコードを一括更新する
 *   関連レコードの一括取得、一括更新は REST APIを利用する
 * 
 * 【トリガー】
 *   レコード詳細画面で編集の保存ボタンを押下した時
 * 
 * 【カスタマイズが必要な定数】
 *   ・RECORD_ID_FIELD_ID
 *   ・CONDITIONAL_FIELD_ID
 *   ・SOURCE_FIELD_IDS
 *   ・TOTAL_FIELD_IDS
 * 
 * 【制約】
 *   SOURCE_FIELD_IDSの要素数とTOTAL_FIELD_IDSの要素数は同じでなければいけない
 * 
 */
(() => {
    'use strict';

	/**
	 * 
	 * 
	 * 
	 * ★★★ カスタマイズが必要な定数群 ★★★
	 * 
	 * 
	 * 
	 */
	// レコード番号のフィールドコード
	const RECORD_ID_FIELD_ID = 'レコード番号';
	// 関連レコード
	const CONDITIONAL_FIELD_ID = 'PROJECT_ID';
	// 計算対象となるフィールドコード
	const SOURCE_FIELD_IDS = ['WORKER_COUNT', 'BUDGET', 'ACTUAL'];
	// 計算結果表示対象となるフィールドコード
	const TOTAL_FIELD_IDS = ['WORKER_COUNT_TOTAL', 'BUDGET_TOTAL', 'ACTUAL_TOTAL'];

	/**
	 * Kintone イベント:編集画面を表示した時
	 */
	kintone.events.on('app.record.edit.show', async (e) => {
		// 合計表示項目の編集を不可にする
		TOTAL_FIELD_IDS.forEach((id) => {
			e.record[id].disabled  = true;
		});
		return e;
	});

	/**
	 * Kintone イベント:編集画面で保存が完了した時
	 */
	kintone.events.on('app.record.edit.submit.success', async (e) => {
		await updateTotalValue(e);
	});

	/**
	 * 合計項目を更新する
	 * @param {*} e 当該画面におけるレコードの情報
	 */
	async function updateTotalValue(e) {
		// レコードを取得する
		let records = await getRecords(e);
		if (records.length == 0) {
			return;
		}
		// レコードを加工する
		records = setTotalValue(records);
		// レコードを更新する
		await updateRecords(records, e);
	}

	/**
	 * REST APIを用いて、レコードの一括取得を行う
	 * @param {*} e 当該画面におけるレコードの情報
	 * @returns レコードのリスト
	 */
	async function getRecords(e) {
		// 取得条件:部署が一致していること
		const query = CONDITIONAL_FIELD_ID + ' = ' + e.record[CONDITIONAL_FIELD_ID].value;
		
		// 取得項目:レコードNO、合算対象レコード群、合算表示レコード群
		let fields = [];
		fields = fields.concat(RECORD_ID_FIELD_ID);
		fields = fields.concat(SOURCE_FIELD_IDS);
		fields = fields.concat(TOTAL_FIELD_IDS); 
		const body = {
			app: e.appId
			, query: query
			, fields: fields
		};
		const response = await kintone.api(kintone.api.url('/k/v1/records.json', true), 'GET', body);
		return response.records;
	} 

	/**
	 * 各レコードに合計値を計算する
	 * @param {*} records 変更前のレコードのリスト
	 * @returns 変更後のレコードのリスト
	 */
	function setTotalValue(records) {
		// 合算対象のフィールド数
		const field_count = SOURCE_FIELD_IDS.length;
		for (let i = 0; i < field_count; i++) { 
        const source_field_id = SOURCE_FIELD_IDS[i]; 
        const total_field_id = TOTAL_FIELD_IDS[i]; 
        // 合計値を取得する 
        let total = 0; records.forEach((record) => {
            total += parseInt(record[source_field_id].value);
        });
     // 合計値を設定する
        records.forEach((record) => {
				record[total_field_id].value = total;
			});
		}
		return records;
	}

	/**
	 * REST APIを用いて、レコードの一括更新を行う
	 * @param {*} records レコードのリスト
	 * @param {*} e 当該画面におけるレコードの情報
	 * @returns -
	 */
	async function updateRecords(records, e) {
		// レコードをリクエスト用に加工する
		records = records.map((record) => {
			const id = record[RECORD_ID_FIELD_ID].value;
			delete record[RECORD_ID_FIELD_ID];
			return {
				id : id
				, record : record
			};
		});
		const body = {
			app: e.appId
			, records: records
		}
		await kintone.api(kintone.api.url('/k/v1/records.json', true), 'PUT', body);
	}
})();

解説

ソースコードの上にコメントをいっぱいのせたのでそれで良しとしてください。

実行結果

  • 作業者人数の合計値を作業者(総人数)に設定する
  • 予算の合計値を予算(総額)に設定する
  • 実績の総数を実績(総数)に設定する

レコード一覧(更新前)

詳細画面(編集)

レコード一覧(更新後)