処理内容
前回の kintone のアプリのデータの集計値を、別アプリに保管する(外部API連携)と同等の処理を、JavaScript で実装します。
・kintone の明細アプリにレコードが追加された直後、集計アプリの該当するコードと年月のデータを更新します。
・kintone の集計アプリに該当するコードと年月が存在しない場合は、レコードを追加します。
・集計処理を複雑にしないため、kintone の明細を更新する時には、日付とコードの入力を抑制します。
kintone は RDB のように参照制約を設定できないし、トランザクション処理がないので、データの同期などは要注意ですね。
本来は追加したレコードだけでなく、該当年月の集計を全てやり直すべきでしょうが、、、面倒なので今回は省略します。
kitone の JavaScript だけで実装してみたい方は、kintone のアプリのデータの集計値を、別アプリに保管する(JavaScript処理) を参照ください。(データの整合性を守るのが大変ですが、、、。)
kitone の設定
前回の kintone のアプリのデータの集計値を、別アプリに保管する(外部API連携) を参照ください。
kintone の JavaScriptコード
一覧表示前と、追加後、変更表示前、変更後、削除前のそれぞれイベントで処理を行います。
一覧表示は、編集、削除のボタンを非表示にします。
追加後は、集計レコードの追加か、更新を行います。
変更表示前に、日付とコードを表示項目に変えます。
変更後は、集計レコードを更新します。(集計レコードが削除される恐れは考慮せず。)
削除前に、集計レコードを更新します。
(function() {
"use strict";
var TotalAppId = "KINTONE_TOTAL_APP_ID";
var ErrorMessage = "エラー発生。一覧画面に戻ってから再度処理を実行してください!";
// 一覧表示のイベント
var eventsIndexShow = [
'app.record.index.show',
'mobile.app.record.index.show'
];
kintone.events.on(eventsIndexShow, function(event) {
// 明細でコードや日付を変えると処理が大変なので、変更、削除を非表示にする
for (var i = 0; i < event.records.length; i++) {
document.getElementsByClassName('recordlist-remove-gaia')[i].parentNode.style.display = 'none';
}
return event;
});
// レコード編集表示イベント
var eventsCreateEditShow = [
'app.record.edit.show',
];
kintone.events.on(eventsCreateEditShow, function(event) {
var record = event.record;
// 日付とコードは変更させない
record['date']['disabled'] = true;
record['code']['disabled'] = true;
return event;
});
// 追加のSubmitイベント
var eventsCreateSubmit = [
'app.record.create.submit.success',
'mobile.app.record.create.submit.success',
];
kintone.events.on(eventsCreateSubmit, function(event)
{
var record = event.record;
// 集計アプリのレコード参照
var respons = GetTotalRecord(TotalAppId, record['date']['value'], record['code']['value']);
// 集計アプリ追加
if(respons == null){
var ym = parseInt(record['date']['value'].substring(0, 4), 10) * 100 + parseInt(record['date']['value'].substring(5, 7), 10);
var value = {
"ym" : { "value": ym.toString() },
"code" : { "value": record['code']['value'] },
"amount": { "value": record['amount']['value'] },
}
if(!PostTotalRecord(TotalAppId, value)){
event.error = ErrorMessage;
}
// 集計アプリ更新
}else{
var amount = parseInt(respons['amount']['value'], 10) + parseInt(record['amount']['value'], 10);
var value = {
"amount": { "value": amount },
}
if(!PutTotalRecord(TotalAppId, respons['レコード番号']['value'], value)){
event.error = ErrorMessage;
}
}
return event;
});
// 編集のSubmitイベント
var eventsEditSubmit = [
'app.record.index.edit.submit.success',
'app.record.edit.submit.success',
'mobile.app.record.edit.submit.success',
];
kintone.events.on(eventsEditSubmit, function(event)
{
var record = event.record;
// 集計アプリのレコード参照
var respons = GetTotalRecord(TotalAppId, record['date']['value'], record['code']['value']);
// 集計アプリ更新
if(respons == null){
event.error = ErrorMessage;
}else{
var amount = parseInt(respons['amount']['value'], 10) + parseInt(record['amount']['value'], 10);
var value = {
"amount": { "value": amount },
}
if(!PutTotalRecord(TotalAppId, respons['レコード番号']['value'], value)){
event.error = ErrorMessage;
}
}
return event;
});
// レコード削除イベント
var eventsDeleteShow = [
'app.record.detail.delete.submit',
'mobile.app.record.detail.delete.submit',
];
kintone.events.on(eventsDeleteShow, function(event) {
var record = event.record;
// 集計アプリのレコード参照
var respons = GetTotalRecord(TotalAppId, record['date']['value'], record['code']['value']);
// 集計アプリ更新
if(respons == null){
//event.error = ErrorMessage;
}else{
var amount = parseInt(respons['amount']['value'], 10) - parseInt(record['amount']['value'], 10);
var value = {
"amount": { "value": amount },
}
if(!PutTotalRecord(TotalAppId, respons['レコード番号']['value'], value)){
event.error = ErrorMessage;
}
}
return event;
});
// 集計データ取得
function GetTotalRecord(appId, date, code)
{
var ym = parseInt(date.substring(0, 4), 10) * 100 + parseInt(date.substring(5, 7), 10);
var query = ' ym = "' + ym.toString() + '"';
query += ' and code = "' + code + '"';
var appUrl = kintone.api.url('/k/v1/records', true)
+ '?app=' + appId
+ '&query=' + encodeURI(query);
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("GET", appUrl, false);
xmlHttp.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xmlHttp.send(null);
if (xmlHttp.status == 200 && window.JSON) {
var respons = JSON.parse(xmlHttp.responseText);
if(respons.records != null){
return respons.records[0];
}else{
return null;
}
}else{
console.log(xmlHttp.status);
console.log(xmlHttp.responseText);
return null;
}
}
// 集計データの追加
function PostTotalRecord(appId, value){
var appUrl = kintone.api.url('/k/v1/record', true);
var body = {
"app": appId,
"record": value,
"__REQUEST_TOKEN__": kintone.getRequestToken()
};
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("POST", appUrl, false);
xmlHttp.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xmlHttp.setRequestHeader('Content-Type', 'application/json');
xmlHttp.send(JSON.stringify(body));
if(xmlHttp.status == 200){
return true;
}else{
console.log(xmlHttp.responseText);
return false;
}
}
// 集計データの更新
function PutTotalRecord(appId, key, value){
var appUrl = kintone.api.url('/k/v1/record', true);
var body = {
"app": appId,
"id": key,
"record": value,
"__REQUEST_TOKEN__": kintone.getRequestToken()
};
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("PUT", appUrl, false);
xmlHttp.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xmlHttp.setRequestHeader('Content-Type', 'application/json');
xmlHttp.send(JSON.stringify(body));
if(xmlHttp.status == 200){
return true;
}else{
console.log(xmlHttp.responseText);
return false;
}
}
})();
処理結果
・集計のない明細を追加すると、集計のレコードが追加されています。
やはり kintone は RDB のように参照制約を設定できないし、トランザクション処理がないので、データの同期などは誰も操作しない夜間に、AWS の Lamda とか利用して更新するのが安全ですね。
AWS の Lamda で更新する方法については、以下参照ください。
kintone のアプリのデータの集計値を、別アプリに保管する(外部API連携)