入力しやすい画面、ワークフロー、顧客マスタアプリからの関連レコードにすることなどを考えて営業日報を以下のアプリ群で運用することを考えています。
①営業日報アプリ(テーブルに営業活動を記録していく)
②営業活動履歴アプリ(営業日アプリのテーブルを単体レコードして同期していく)
③顧客マスタアプリ(関連レコードにて②営業活動履歴アプリのレコードが参照できる)
営業日報アプリのテーブルの追加・変更・削除に営業活動アプリのレコードが追従していくかたちです。両アプリの連携keyは日報アプリのレコードID+行IDを考えています。イベントをまたぐかたちになりますが以下の処理例で問題がないのか、ご指摘いただければ幸いです。よろしくお願いいたいます。
①app.record.edit.submitイベント内でREST APIで編集前レコードを取得し、グローバル変数に格納
②app.record.create.submit.successイベント内にて編集前レコードと編集後レコード(event.record)の差分を検出。
③差分に応じて、履歴アプリに対してRESR APIで新規追加・更新・削除を行う
///////////// 実装例 //////////////
/*
* 営業日報アプリのテーブルと営業活動履歴アプリの同期処理
*/
(function () {
“use strict”;
// 営業活動履歴アプリID
varSAHappId=***;
// 編集レコードID(保存成功前イベントと保存成功後イベントで同一レコードかどうかのチェック用)
vareditRecordId;
// 活動内容テーブル差分チェック配列(変更前)
varbeforeSaTable=[];
// 活動内容テーブル差分チェック配列(変更後)
varafterSaTable=[];
// 編集前・編集後のテーブル差分格納用配列
vardiffTableArr=[];
// ------------ 営業活動履歴アプリに活動内容(日報アプリのテーブルを単体レコードとして)をコピー ------------
//レコード新規作成後の保存成功後イベントで営業活動アプリに活動内容のレコード作成(コピー)
kintone.events.on([“app.record.create.submit.success”],asyncfunction(event) {
// 日報アプリID(このアプリ)
varappId=event.appId;
// レコードID(このアプリ)
varrecordId=event.recordId;
// レコード全体
varrecord=event.record;
// 活動日
varactivityDate=record.activityDate.value;
// 営業担当者
varsalesName=record.salesName.value;
// 担当者コード
varsalesCode=record.salesCode.value;
// 活動内容(テーブル)
varsaTable=record.saTable.value;
varpostRecords=[]; // POSTするrecords
for(vari=0; i<saTable.length; i++) {
varpostRecord={
“activityDate”:{
“value”:activityDate
},
“salesName”:{
“value”:salesName
},
“salesCode”:{
“value”:salesCode
},
“activityType”:{
“value”:saTable[i].value.activityType.value
},
“kintoneCode”:{
“value”:saTable[i].value.kintoneCode.value
},
“liaison”:{
“value”:saTable[i].value.liaison.value
},
“activityInfo”:{
“value”:saTable[i].value.activityInfo.value
},
“activityNote”:{
“value”:saTable[i].value.activityNote.value
},
“activityCode”:{
“value”:recordId+“_”+saTable[i].id
}
};
postRecords.push(postRecord);
} // End for
//レコードの登録API
varpostParams=[];
postParams= {
“app”: SAHappId,
‘records’: postRecords
};
letresp1=[];
try {
resp1=awaitkintone.api(kintone.api.url(‘/k/v1/records’,true),‘POST’,postParams); // 待つ処理にawaitをつける レスポンス内容がresp1に入る。ちゃんと待ってから次の処理に移る
} catch (err) {
console.log(err);
}
returnevent;
});
// ------------ 営業活動履歴アプリの活動内容(レコード)を削除 ------------
//レコード詳細画面、一覧画面からのレコード削除イベントで営業活動アプリの活動内容レコード削除
kintone.events.on([“app.record.detail.delete.submit”,“app.record.index.delete.submit”],asyncfunction(event) {
// 日報アプリID(このアプリ)
varappId=event.appId;
// レコードID(このアプリ)
varrecordId=event.recordId;
// レコード全体
varrecord=event.record;
// 活動日
varactivityDate=record.activityDate.value;
// 営業担当者
varsalesName=record.salesName.value;
// 担当者コード
varsalesCode=record.salesCode.value;
// 活動内容(テーブル)
varsaTable=record.saTable.value;
varids=[]; // DELETE対象のレコードID
for(vari=0; i<saTable.length; i++) {
varactivityCode=recordId+“_”+saTable[i].id;
console.log(‘appId’,appId);
console.log(‘activityCode’,activityCode);
// 営業履歴アプリの削除対象レコードを取得
vargetParams=[];
getParams= {
“app”: SAHappId,
“query”: ‘activityCode = "’+activityCode+‘"’// 検索条件の指定
};
letresp1=[];
try {
resp1=awaitkintone.api(kintone.api.url(‘/k/v1/records’,true),‘GET’,getParams); // 待つ処理にawaitをつける レスポンス内容がresp1に入る。ちゃんと待ってから次の処理に移る
console.log(‘resp1 %0’,resp1);
} catch (err) {
console.log(err);
}
if(resp1.records.length>0) {
ids.push(resp1.records[0].$id.value);
}
} // End for
// 営業履歴アプリの対象レコードを削除
vardeleteParams={
“app”:SAHappId,
“ids”:ids,
};
letresp2=[];
try {
resp2=awaitkintone.api(kintone.api.url(‘/k/v1/records’,true),‘DELETE’,deleteParams);
} catch (err) {
console.log(err);
}
returnevent;
});
// ------------ 営業活動履歴アプリの活動内容(単体レコード)の新規・更新・削除 ------------
// 営業日報アプリのレコード編集で営業活動情報(テーブル)が更新された時、営業活動アプリの単体レコードも同期するようにする
// 保存実行前イベント内にて REST APIで変更前レコードをGET(取得)、グローバル変数にレコードID、開業活動テーブルを格納する
// レコード編集画面・保存実行前イベント
kintone.events.on([“app.record.edit.submit”],asyncfunction(event) {
// 日報アプリID(このアプリ)
varappId=event.appId;
// レコードID(このアプリ)
varrecordId=event.recordId;
// レコード全体
varrecord=event.record;
// 編集レコードID(保存成功前イベントと保存成功後イベントで同一レコードかどうかのチェック用)
editRecordId=Number(recordId);
// 営業日報アプリ(このアプリ)の編集前レコードを取得
vargetParams=[];
getParams= {
“app”: appId,
“id”: recordId
};
letresp1=[];
try {
resp1=awaitkintone.api(kintone.api.url(‘/k/v1/record’,true),‘GET’,getParams); // 待つ処理にawaitをつける レスポンス内容がresp1に入る。ちゃんと待ってから次の処理に移る
} catch (err) {
console.log(err);
}
// console.log(‘resp1’);
// console.log(‘%0’, resp1.record.saTable.value);
beforeSaTable=resp1.record.saTable.value; // 活動内容テーブル差分チェック配列(変更前)
returnevent;
});
// レコード編集画面・保存成功後イベント
// テーブル新規追加行の行IDを取得する為、保存実行後イベント内で REST APIで編集後レコードをGET(取得)
// グローバル変数に格納した編集前テーブルと編集後テーブルを比較し、営業活動履歴アプリのレコードに新規・更新・削除処理を行う。
kintone.events.on([“app.record.edit.submit.success”],asyncfunction(event) {
// 日報アプリID(このアプリ)
varappId=event.appId;
// レコードID(このアプリ)
varrecordId=event.recordId;
// レコード全体
varrecord=event.record;
// 活動日
varactivityDate=record.activityDate.value;
// 営業担当者
varsalesName=record.salesName.value;
// 担当者コード
varsalesCode=record.salesCode.value;
console.log(‘保存成功後イベント’);
console.log(‘editRecordId’,editRecordId);
console.log(‘recordId’,recordId);
// 保存成功前イベントと保存成功後イベントで同一レコードかどうかのチェック
if(Number(editRecordId)===Number(recordId)) {
// 営業日報アプリ(このアプリ)の編集前レコードを取得
vargetParams=[];
getParams= {
“app”: appId,
“id”: recordId
};
letresp1=[];
try {
resp1=awaitkintone.api(kintone.api.url(‘/k/v1/record’,true),‘GET’,getParams); // 待つ処理にawaitをつける レスポンス内容がresp1に入る。ちゃんと待ってから次の処理に移る
} catch (err) {
console.log(err);
}
// console.log(‘resp1’);
// console.log(‘%0’, resp1.record.saTable.value);
afterSaTable=resp1.record.saTable.value; // 活動内容テーブル差分チェック配列(変更前)
console.log(‘beforeSaTable’);
console.log(‘%0’,beforeSaTable);
console.log(‘afterSaTable’);
console.log(‘%0’,afterSaTable);
diffTableArr=diffTable(beforeSaTable,afterSaTable);
console.log(‘%0’,diffTableArr);
// ==================== 営業活動履歴アプリ更新リクエスト作成 ==========================
varpostArr=diffTableArr[1]; // 新規追加出庫
vardeleteArr=diffTableArr[2]; // 削除出庫
varputArr=diffTableArr[3]; // 変更出庫
// ====== 新規追加 ======
if(postArr.length>0) {
console.log(‘編集変更処理 — 新規追加’);
varpostRecords=[]; // POSTするrecords
for(vari=0; i<postArr.length; i++) {
varpostRecord={
“activityDate”:{
“value”:activityDate
},
“salesName”:{
“value”:salesName
},
“salesCode”:{
“value”:salesCode
},
“activityType”:{
“value”:postArr[i].value.activityType.value
},
“kintoneCode”:{
“value”:postArr[i].value.kintoneCode.value
},
“liaison”:{
“value”:postArr[i].value.liaison.value
},
“activityInfo”:{
“value”:postArr[i].value.activityInfo.value
},
“activityNote”:{
“value”:postArr[i].value.activityNote.value
},
“activityCode”:{
“value”:recordId+“_”+postArr[i].id
}
};
postRecords.push(postRecord);
} // End for
//レコードの登録API
varpostParams={
“app”:SAHappId,
‘records’:postRecords
};
letresp2=[];
try {
resp2=awaitkintone.api(kintone.api.url(‘/k/v1/records’,true),‘POST’,postParams);
} catch (err) {
console.log(err);
}
} // 新規追加 end
// ====== 削除 ======
if(deleteArr.length>0) {
console.log(‘編集変更処理 — 削除’);
varids=[]; // DELETE対象のレコードID
for(vari=0; i<deleteArr.length; i++) {
varactivityCode=recordId+“_”+deleteArr[i].id;
// 営業履歴アプリの削除対象レコードを取得
vargetParams=[];
getParams= {
“app”: SAHappId,
“query”: ‘activityCode = "’+activityCode+‘"’// 検索条件の指定
};
letresp3=[];
try {
resp3=awaitkintone.api(kintone.api.url(‘/k/v1/records’,true),‘GET’,getParams); // 待つ処理にawaitをつける レスポンス内容がresp1に入る。ちゃんと待ってから次の処理に移る
console.log(‘%0’,resp3);
} catch (err) {
console.log(err);
}
if(resp3.records.length>0) {
console.log(‘resp3.records[0].$id.value’,resp3.records[0].$id.value);
ids.push(resp3.records[0].$id.value);
}
} // End for
// 営業履歴アプリの対象レコードを削除
vardeleteParams={
“app”:SAHappId,
“ids”:ids,
};
letresp4=[];
try {
resp4=awaitkintone.api(kintone.api.url(‘/k/v1/records’,true),‘DELETE’,deleteParams);
} catch (err) {
console.log(err);
}
} // 削除 end
// ====== 更新 ======
if(putArr.length>0) {
console.log(‘編集変更処理 — 更新’);
varputRecords=[]; // POSTするrecords
for(vari=0; i<putArr.length; i++) {
varputRecord={
“updateKey”:{
“field”:“activityCode”,
“value”:recordId+“_”+putArr[i].id
},
“record”:{
“activityDate”:{
“value”:activityDate
},
“salesName”:{
“value”:salesName
},
“salesCode”:{
“value”:salesCode
},
“activityType”:{
“value”:putArr[i].value.activityType.value
},
“kintoneCode”:{
“value”:putArr[i].value.kintoneCode.value
},
“liaison”:{
“value”:putArr[i].value.liaison.value
},
“activityInfo”:{
“value”:putArr[i].value.activityInfo.value
},
“activityNote”:{
“value”:putArr[i].value.activityNote.value
}
}
};
putRecords.push(putRecord);
} // End for
//レコードの登録API
varputParams={
“app”:SAHappId,
‘records’:putRecords
};
console.log(‘putParams’,putParams);
letresp5=[];
try {
resp5=awaitkintone.api(kintone.api.url(‘/k/v1/records’,true),‘PUT’,putParams);
console.log(‘resp5’,resp5);
} catch (err) {
console.log(err);
}
} // End If
} // 更新 end
returnevent;
});
/*
* サブテーブル・stock_tableについてレコード編集前、編集後の差分をとる関数
* @param beforeArr レコード編集前のサブテーブルデータ
* @param afterArr レコード編集後のサブテーブルデータ
* @returns {Array} 変更なし、新規追加、変更あり、削除データを配列で返す
*/
functiondiffTable(beforeArr, afterArr) {
vari,ii;
varbeforeTableId,afterTableId; // 編集前テーブル行ID、編集後テーブル行ID(行IDはユニークな値)
varbeforeTableString,afterTableString; // 編集前テーブル行json文字列、編集後テーブル行json文字列、
varsameF,changeF,addF,deleteF; // 変更なしフラグ、変更フラグ、新規追加フラグ、削除フラグ
varsameArr=[]; // 変更なし行格納配列
varchangeArr=[]; // 変更あり行格納配列
varaddArr=[]; // 新規作成行格納配列
vardeleteArr=[]; // 削除行格納配列
// ------------------削除データを探索------------------------
for(i=0; i<beforeArr.length; i++) {
beforeTableId=beforeArr[i].id; // 編集前テーブル行ID
deleteF=true; // 削除フラグ
for(ii=0; ii<afterArr.length; ii++) {
afterTableId=afterArr[ii].id; // 編集後テーブル行ID
// 存在している行の削除フラグをoff
if(beforeTableId===afterTableId) {
deleteF=false;
break;
}
}
// 削除データを配列に格納
if(deleteF) { deleteArr.push(beforeArr[i]) }
}
// ------------------新規追加データを探索------------------------
for(i=0; i<afterArr.length; i++) {
afterTableId=afterArr[i].id; // 編集後テーブル行ID
addF=true; // 新規追加フラグ
for(ii=0; ii<beforeArr.length; ii++) {
beforeTableId=beforeArr[ii].id; // 編集前テーブル行ID
// 存在している行の新規追加フラグをoff
if(afterTableId===beforeTableId) {
addF=false;
break;
}
}
// 新規追加データを配列に格納
if(addF) { addArr.push(afterArr[i]) }
}
// ------------------変更データを探索------------------------
for(i=0; i<afterArr.length; i++) {
sameF=false; // 変更なしフラグ
changeF=false; // 変更ありフラグ
afterTableId=afterArr[i].id; // 編集後テーブル行ID
afterTableString=JSON.stringify(afterArr[i]); // 編集後テーブル行・Json文字列化
for(ii=0; ii<beforeArr.length; ii++) {
beforeTableId=beforeArr[ii].id; // 編集前テーブル行ID
beforeTableString=JSON.stringify(beforeArr[ii]); // 編集前テーブル行・Json文字列化
// 変更なし
if(afterTableId===beforeTableId&&afterTableString===beforeTableString) {
sameF=true;
console.log(‘変更なし’);
break;
// 変更あり
} else if (afterTableId === beforeTableId && afterTableString !== beforeTableString) {
changeF=true;
console.log(‘変更あり’);
break;
}
} // end for
// 編集テーブル変更行を配列に格納
if(changeF) { changeArr.push(afterArr[i]) }
// 編集テーブル変更なし行を配列に格納
if(sameF) { sameArr.push(afterArr[i]) }
} // end for
return [sameArr,addArr,deleteArr,changeArr];
} // End function
})();