3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

kintone のアプリのデータの集計値を、別アプリに保管する(JavaScript処理)

Last updated at Posted at 2019-04-09

処理内容

前回の kintone のアプリのデータの集計値を、別アプリに保管する(外部API連携)と同等の処理を、JavaScript で実装します。

・kintone の明細アプリにレコードが追加された直後、集計アプリの該当するコードと年月のデータを更新します。
・kintone の集計アプリに該当するコードと年月が存在しない場合は、レコードを追加します。
・集計処理を複雑にしないため、kintone の明細を更新する時には、日付とコードの入力を抑制します。

kintone は RDB のように参照制約を設定できないし、トランザクション処理がないので、データの同期などは要注意ですね。
本来は追加したレコードだけでなく、該当年月の集計を全てやり直すべきでしょうが、、、面倒なので今回は省略します。

kitone の JavaScript だけで実装してみたい方は、kintone のアプリのデータの集計値を、別アプリに保管する(JavaScript処理) を参照ください。(データの整合性を守るのが大変ですが、、、。)

kitone の設定

前回の kintone のアプリのデータの集計値を、別アプリに保管する(外部API連携) を参照ください。

kintone の JavaScriptコード

一覧表示前と、追加後、変更表示前、変更後、削除前のそれぞれイベントで処理を行います。
一覧表示は、編集、削除のボタンを非表示にします。
追加後は、集計レコードの追加か、更新を行います。
変更表示前に、日付とコードを表示項目に変えます。
変更後は、集計レコードを更新します。(集計レコードが削除される恐れは考慮せず。)
削除前に、集計レコードを更新します。

totalUpdate.js
(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;
		}
	}
	
})();

処理結果

・処理前の集計の一覧です。
kintoneTtl01.png

・集計のない明細を追加すると、集計のレコードが追加されています。
kintoneTtl02.png
kintoneTtl04.png

・明細を追加すると、集計金額が更新されます。
kintoneTtl05.png
kintoneTtl06.png

やはり kintone は RDB のように参照制約を設定できないし、トランザクション処理がないので、データの同期などは誰も操作しない夜間に、AWS の Lamda とか利用して更新するのが安全ですね。

AWS の Lamda で更新する方法については、以下参照ください。
kintone のアプリのデータの集計値を、別アプリに保管する(外部API連携)

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?