やりたいこと
kintone の見積アプリで、
- テーブルの数量や単価を変えたら、その場で行の金額と合計を計算し直したい
- 計算結果の欄(金額・合計・消費税)は、人が書き換えられないようにしたい
計算フィールドで足りない(端数の処理が細かい、テーブルの外に合計を出したい、など)ときに、JavaScript で同じことをする書き方です。建設向けの見積書プラグインのコードで説明します。どのフィールドを使うかは、プラグインの設定(config)から読んでいます。
1. 見張るイベントを配列で並べる
kintone.events.on には、イベント名の 配列 を渡せます。作成・編集の「表示」「保存」と、決まったフィールドの「変更」をまとめて1つの関数に向けます(kintone/estimate/src/js/desktop.js)。
var watched = [config.table, config.qty, config.price, config.rateField, config.welfare, config.discount].filter(Boolean);
var editEvents = ['app.record.create.show', 'app.record.edit.show', 'app.record.create.submit', 'app.record.edit.submit'];
watched.forEach(function(code) {
editEvents.push('app.record.create.change.' + code, 'app.record.edit.change.' + code);
});
kintone.events.on(editEvents, recalc);
ポイントは4つあります。
-
change イベントは、フィールドコードごとに名前が決まる。
app.record.edit.change.数量のように、見張るフィールドの数だけ並べます。フィールドコードを設定で選ぶプラグインでは、設定を読んでから配列を組み立てます。 -
テーブル自身のコードも入れる。 テーブルのフィールドコードの change イベントは、行を足したとき・消したときに起きます。行を消したら合計を減らしたいので、
config.tableも見張ります。テーブルの中の数量や単価の change は、セルを変えたときに起きます。 -
設定で使わない(空の)ものは
filter(Boolean)で外す。 空のコードでapp.record.edit.change.という名前を登録しないためです。 - show と submit でも計算する。 開いたときに古い値が入っていても直り、保存の直前にもう一度計算するので、計算前の値で保存されません。
2. 計算して、event.record に書き戻す
イベントの関数は event.record を書き換えて、event を返します。返した event の内容が画面に反映されます。
function apply(record) {
if (!record[config.table]) return record;
var result = calc(record);
if (config.amount) {
result.lines.forEach(function(line) {
var cell = line.row.value[config.amount];
if (cell) cell.value = line.amount === null ? '' : String(line.amount);
});
}
OUTPUTS.forEach(function(key) {
var field = config[key] && record[config[key]];
if (field) field.value = String(result[OUT_KEYS[key]]);
});
lockOutputs(record);
return record;
}
function recalc(event) {
apply(event.record);
return event;
}
- テーブルの行は
record[テーブル].valueの配列で、1行はrow.value[フィールドコード]です。行の金額は、その行のセルに直接入れます。 - 数値フィールドに入れる値は 文字列 にします(
String(...))。計算できなかった行は空文字にします。 -
calcの中身(小数の誤差を出さない計算)は別の記事にまとめました。
3. 結果の欄を編集不可にする:disabled
書き戻した欄は、人が上書きできないように disabled = true にします。
// ---- 作成と編集の画面:計算結果をフィールドに入れる ----
function lockOutputs(record) {
OUTPUTS.forEach(function(key) {
if (config[key] && record[config[key]]) record[config[key]].disabled = true;
});
if (config.amount && record[config.table]) {
record[config.table].value.forEach(function(row) {
if (row.value[config.amount]) row.value[config.amount].disabled = true;
});
}
}
テーブルの中の欄は 行ごと に disabled を付けます。行を足したとき(テーブルの change)にも apply → lockOutputs が走るので、新しい行の金額の欄もすぐ編集不可になります。
4. 一覧の行内編集を忘れない
一覧の画面でも、鉛筆のボタンからその場で編集できます。ここを見落とすと、計算結果の欄を一覧から書き換えられてしまいます。
// 一覧の行内編集。テーブルが届かないときは計算しない
kintone.events.on('app.record.index.edit.show', function(event) {
lockOutputs(event.record);
return event;
});
kintone.events.on('app.record.index.edit.submit', recalc);
-
app.record.index.edit.showで、結果の欄を編集不可にします。 -
app.record.index.edit.submitで、保存の前に計算し直します。
行内編集の event.record にはテーブルが入っていないことがあります。そのため apply の頭で if (!record[config.table]) return record; として、何もせずに返しています。原価管理のプラグインでは、この場合も結果の欄を編集不可にしてから返しています(kintone/genka/src/js/desktop.js)。
function apply(record) {
// 一覧の行内編集などでテーブルが届かないときは、書き込み先を0にしないよう何もしない
if (!record[config.table] || !record[actualTable]) {
lockOutputs(record);
return record;
}
// (中略)
}
テーブルが届かないまま計算すると、合計が0になって保存されてしまいます。「届かないなら書かない」が安全側です。
5. 設定が済んでいなければ何もしない
ファイルの頭で、必要な設定がそろっていなければすぐ抜けます。
var config = kintone.plugin.app.getConfig(PLUGIN_ID) || {};
if (!config.table || !config.name || !config.qty || !config.price) return;
イベントを登録する前に抜けるので、設定前のアプリの画面には何も起きません。
まとめ
-
kintone.events.onにはイベント名の配列を渡せる。change はフィールドコードごとに並べ、テーブル自身のコードも入れる(行の追加・削除)。 -
event.recordの値は文字列で書き戻し、eventを返す。結果の欄はdisabled = true。テーブルの中は行ごと。 - 一覧の行内編集(
index.edit.show/index.edit.submit)も同じように扱う。テーブルが届かないときは書かない。
ソースと配布先
この記事のコードは、建設向けの無料の kintone プラグイン「見積書作成プラグイン」の一部です。
- ソース(MIT License):https://github.com/Genbacoe/kintone-plugins/tree/main/estimate/src
- 入れ方と設定の画面:https://genbakoe.com/kintone/estimate/
※ kintone はサイボウズ株式会社の登録商標です。このプラグインと記事は、サイボウズ株式会社の公式のものではありません。