
kintoneのカスタマイズでドはまりした話
聞いてください。
ちょっと申請アプリをカスタマイズしていた時のびっくりな話。
【ピンポンパンポーン📢】
以下のコードはあくまでも独学の素人が書いています。
「は?そんなんも知らんの?」という心の声はそっとしまって頂いて、素人がもがく姿を楽しんで頂ければ幸いです。
kintoneのチェックボックスの件数に応じてスペースフィールドに注意書きを出したいなぁ、と思いまして。


文字列の value(結果)を取得してif文で出すのは簡単なんですが、数値だとちゃんと数値で取得できるか不安で。。
(割愛しますが色々落とし穴あるんですよねぇ。。気になる方はこちら)
(先に)完成形




という感じ。
チェックした項目で補助額を自動計算出来たらより良いんでしょうが、
該当工事は割とえげつない量があるので(大体150項目くらい)別で配布しているパンフレットから拾ってその合計金額を入力した方が早い上に、毎年それで間違いが少なかったので良いか、という結論になりました。
というか、その約150項目をIF文で繋いで合計式書く方がやばい。絶対間違えるし毎年項目も金額も変わるからリスクしかない。
どうせ最終的に国の申請フォームで合ってるか確認できるというのもある。
*******
さて、これだけ見ると(カスタマイズの結果としては)特におかしな点は見受けられないと思いますが、該当数のカウントに大きな落とし穴がありました。
数値の計算方法
バック(カスタマイズ)だけで判断するのは(どういう計算してるのかが見えないので)ユーザー側に優しくないなぁ、と思い、今回追加したのがこの2つのフィールド。

今回のリフォーム申請の肝は
必須工事はいずれか2つ以上実施しなければならない
ということ。ちなみに前年まではいずれか1つだったのでさほど影響がなかったんですよ。(リフォームするっていって水廻りの工事(エコ設備の設置)をしない方は少ないので。)
ですが今年は2つ以上が必須となったため、社内でも事前の確認が重要になっています。
現に「2つ以上」というワードで毎回「えぇ~!(困る)」という反応。
(うるさいくらい何度も言ってるんだからいい加減覚えて欲しい。)
ということで、申請アプリの方もより目立つように随所にチェックポイントを設けていきます。
*******
さて本題。

この2つの計算式は以下の通り。
必須工事 :requiredProject
必須該当数 :requiredCount
必須工事判定:requiredJudge
必須該当数の式
SUM(IF( CONTAINS(requiredProject,"開口部の断熱改修/窓リノベ"),1,0),
IF( CONTAINS(requiredProject,"躯体の断熱改修"),1,0),
IF( CONTAINS(requiredProject,"エコ設備の設置"),1,0))
CONTAINS関数でチェック(真)されたら「1」。なし(偽)なら「0」で合計してるだけ。
必須工事判定の式
IF(requiredCount >= 2,"OK","NG")
該当数のカウントが2以上なら「OK」、2未満なら「NG」です。
割とシンプルですね。
で、これを元にバック(カスタマイズ)でスペースへの表記の条件分岐を書いていきます。
JavaScript(発火しないコード)
まず最初に書いたコードです。どこかが間違っています。
(function() {
'use strict';
kintone.events.on([
//新規作成時
"app.record.create.change.project", //リフォーム申請事業
"app.record.create.change.requiredProject", //リフォーム必須工事
"app.record.create.change.construct", //工事種別
//編集時
"app.record.edit.change.over",
"app.record.edit.change.project",
"app.record.edit.change.requiredProject",
"app.record.edit.change.construct",
"app.record.detail.show",
"app.record.create.show",
"app.record.edit.show",
"app.record.print.show"
],
function(event) {
const statusRequiredJudge = event.record["requiredJudge"].value; //子育てグリーン必須判定
const statusRequiredCount = Number(event.record["requiredCount"].value); //子育てグリーン必須該当数
const statusConstruct = event.record["construct"].value; //工事種別
const statusProject = event.record["project"].value; //リフォーム申請事業
const uamessage = kintone.app.record.getSpaceElement('upperAttention'); //補助額横スペース
const uamEvent = () => {
uamessage.style.fontSize = '20pt';
uamessage.style.color = 'red';
uamessage.style.textAlign = "left";
uamessage.style.fontWeight = "bold";
uamessage.style.marginTop = '36px';
uamessage.style.marginLeft = '5px';
}
switch(statusProject) {
case "子育てグリーン":
if(statusConstruct == "リフォーム" && statusProject == "子育てグリーン" && statusRequiredJudge == "NG") {
uamessage.innerText = "必須工事の該当数を満たしていないため申請不可";
uamEvent();
} else if (statusConstruct == "リフォーム" && statusProject == "子育てグリーン" && statusRequiredCount === 2) {
uamessage.innerText = "上限:40万円まで";
uamEvent();
} else if (statusConstruct == "リフォーム" && statusProject == "子育てグリーン" && statusRequiredCount === 3) {
uamessage.innerText = "上限:60万円まで";
uamEvent();
} else {
uamessage.innerText = "";
}
break;
}
これだとずっと「必須工事の該当数を満たしていないため申請不可」になっちゃいました。
仕方がないので「console.log」を入れて原因を探していきます。
問題箇所
case "子育てグリーン":
if(statusConstruct == "リフォーム" && statusProject == "子育てグリーン" && statusRequiredJudge == "NG") {
console.log("子育てグリーン必須判定:",statusRequiredJudge);
console.log("子育てグリーン必須該当数:",statusRequiredCount);
uamessage.innerText = "必須工事の該当数を満たしていないため申請不可";
uamEvent();
} else if (statusConstruct == "リフォーム" && statusProject == "子育てグリーン" && statusRequiredCount === 2) {
console.log("子育てグリーン必須該当数:",statusRequiredCount);
uamessage.innerText = "上限:40万円まで";
uamEvent();
} else if (statusConstruct == "リフォーム" && statusProject == "子育てグリーン" && statusRequiredCount === 3) {
console.log("子育てグリーン必須該当数:",statusRequiredCount);
uamessage.innerText = "上限:60万円まで";
uamEvent();
} else {
console.log("子育てグリーン必須該当数:",statusRequiredCount);
uamessage.innerText = "";
}
break;
すると驚く結果が。
<リフォームにチェック打っただけ、必須工事は0>
子育てグリーン必須判定: NG
子育てグリーン必須該当数: 0
<リフォームにチェック、必須工事は1>
子育てグリーン必須判定: NG
子育てグリーン必須該当数: 0
<リフォームにチェック、必須工事は2>
子育てグリーン必須判定: NG
子育てグリーン必須該当数: 1
そう、「配列」だったんです…!!
<JavaScriptにおける配列とは>
通常の数字の数え方は
1,2,3,4,5・・・
ですが、プログラミングにおける数え方は
0,1,2,3,4・・・
つまり「0」が一つ目になるのです。
いやぁ、盲点でした。
まさか配列でカウントされているとは。
計算フィールドの数値を取得しているのに、バックのカウントは異なるようでした。(解せぬw)
ちなみに、
const statusRequiredCount = event.record["requiredCount"].value;
でも試してみたんですが、やはり数値として認識してもらえず、
const statusRequiredCount = Number(event.record["requiredCount"].value);
でないとダメでした。
ここで「わーい!完成ぃぃ!!」と喜んだのも束の間。
二つ目の落とし穴がありました。
チェックを打った回数が認識される?
デバック作業、大事ですね。
ちゃんと動くか、想定とは異なる動作をしたらどうなるのか、もちろんしつこく確認していきます。すると、、
<必須工事:3つに☑>
子育てグリーン必須該当数: 2
<必須工事:3つ☑の状態 → 1つチェックを外す>
子育てグリーン必須該当数: 3 (<-!!?)
つまり、



え?なんで?☑外しても外したことがカウントされる。
正確に書くと、
① 初期値(☑0)| 0
➁ ☑1 | 0
③ ☑2 | 1
④ ☑3 | 2
⑤ ☑2 | 3(④から一つ外す)
⑥ ☑1 | 2(⑤から一つ外す)
⑦ ☑0 | 1(⑥から一つ外す)
⑧ ☑1 | 0(⑦から一つ追加)
⑨ ☑2 | 1(⑧から一つ追加)
という動き。⑤~⑦を対応しなければいけない事態に。。
(ちなみにどこに打つかは特に関係ない模様)
どういうことだよー!!
*******
色々考えましたが、自分一人では解決できず…(巡り巡って全部出来ねぇとなったので割愛。悔しい。)
AI(perplexity)の力を借りることにしました。
結果としては、チェックボックスを直接lengthで取りに行く、が正解でした。
(最終)ちゃんと思い通り動いたコード
(function() {
'use strict';
kintone.events.on([
//新規作成時
"app.record.create.change.over", //補助額上限アップ
"app.record.create.change.project", //リフォーム申請事業
"app.record.create.change.requiredProject", //リフォーム必須工事
"app.record.create.change.construct", //工事種別
//編集時
"app.record.edit.change.over",
"app.record.edit.change.project",
"app.record.edit.change.requiredProject",
"app.record.edit.change.construct",
//表示時
"app.record.detail.show",
"app.record.create.show",
"app.record.edit.show",
"app.record.print.show"
], function(event) {
// requiredProjectフィールドの値を取得
const requiredProject = event.record.requiredProject.value;
// チェックされた項目の数をカウント
let currentCheckedCount = requiredProject.length;
console.log("requiredProject:",requiredProject.length);
// カウント結果をrequiredCountフィールドに反映
event.record.requiredCount.value = String(currentCheckedCount);
//リフォーム補助額上限アップ時のエラーメッセージ
const statusRequiredJudge = event.record["requiredJudge"].value; //子育てグリーン必須判定
const statusOver = event.record["over"].value; //補助額上限アップ
const statusConstruct = event.record["construct"].value; //工事種別
const statusProject = event.record["project"].value; //リフォーム申請事業
const uamessage = kintone.app.record.getSpaceElement('upperAttention'); //補助額横スペース
const uamEvent = () => {
uamessage.style.fontSize = '20pt';
uamessage.style.color = 'red';
uamessage.style.textAlign = "left";
uamessage.style.fontWeight = "bold";
uamessage.style.marginTop = '36px';
uamessage.style.marginLeft = '5px';
}
switch(statusProject) {
case "子育てグリーン":
if(statusConstruct == "リフォーム" && statusProject == "子育てグリーン" && currentCheckedCount === 0 || currentCheckedCount === 1) {
console.log("子育てグリーン必須該当数:", currentCheckedCount);
uamessage.innerText = "必須工事の該当数を満たしていないため申請不可";
uamEvent();
} else if (statusConstruct == "リフォーム" && statusProject == "子育てグリーン" && currentCheckedCount === 2) {
console.log("子育てグリーン必須該当数:", currentCheckedCount);
uamessage.innerText = "上限:40万円まで";
uamEvent();
} else if (statusConstruct == "リフォーム" && statusProject == "子育てグリーン" && currentCheckedCount === 3) {
console.log("子育てグリーン必須該当数:", currentCheckedCount);
uamessage.innerText = "上限:60万円まで";
uamEvent();
} else {
console.log("子育てグリーン必須該当数:", currentCheckedCount);
uamessage.innerText = "";
}
break;
case "窓リノベ":
if(statusConstruct == "リフォーム" && statusOver == "いいえ" && statusProject == "窓リノベ") {
uamessage.innerText = "上限:30万円まで";
uamEvent();
} else if(statusConstruct == "リフォーム" && statusOver == "はい" && statusOver_check == "未" && statusProject == "窓リノベ"){
uamessage.innerText = "補助額が30万円を超えています。補助額上限UPをご確認ください。";
uamEvent();
} else {
uamessage.innerText = "";
uamEvent();
}
break;
}
return event;
});
})();
ちなみにlengthで直接取得しに行くと配列じゃなくて、合計値だったので
0か1つならNG、2つなら40万円、3つなら60万円がそのまま行けました。
しかも直接取りに行ってるからカスタマイズ的には追加した2つのフィールドはマジで使ってないww
本当にフロントユーザー(見やすさ)のためだけのフィールドになっちゃった💧w
また一つ賢くなりましたw(何とか解決できて良かったです💧)