新規投稿
フォローする

カスタマイズ・コードで更新したフィールドの値が再描画されない問題の対策伺い

'app.record.detail.show'イベント時、lookup先と同じレコードから値を転記するようなカスタマイズJavaScriptコードを作って動作させたところ、添付の図に示したように、フオームの表示内容を示すrecord変数の中身までは更新できたのですが、フォームに表示された値は古い値のまま更新できませんでした。 

lookup先と同じレコードから値を転記する処理は、rest APIのget().then節の中に在るので、'app.record.detail.show'イベントから更に遅延して実行されるので、一旦 古い値が表示される瞬間があることまでは理解できます。

でも、console.logでrecord変数の中身が変わっていることを確認できた時点でも尚、表示内容が更新されなかったのは、解せない現象です。

どなたか、recordのフィールドを更新した後、フォーム画面の再描画を促進できる方法(recordのフィールドの値が変わったことを描画系にnotifyできるAPI)を教えていただけませんでしょうか?

 

0

15件のコメント

Avatar
岡崎 光輝

更新完了後に以下でページをリロードできますが、このような操作で大丈夫そうですか?

location.reload();

 

0
Avatar
小瀬

応答ありがというございます。

でも、location.reload()の追加では、下記のように二つの観点で、ダメでした。

'app.record.detail.show'イベントのハンドラ内にlocation.reload()を追加したら、'app.record.detail.show'イベントが再発火して、無限ループ状態になりました。 しかも、その無限ループ状態から脱するのに、escなどのボタンは効かなくて、ブラウザを閉じなければならなくなる程、割り込み困難な無限ループでした。

また、無限ループしている画面はチラついて醜かったのですが、更新を期待しているフィールドの表示内容を観ても、表示内容は変わっていませんでした。

この現象から、どうも、kintoneのフォーム画面表示は、「DB内容をfetchしたevent("record")とは別に、kintoneが制御していてlocation.reload()だけでは更新されない表示用のバッファ(キャッシュ)が在る」かのように観えました。

 

小瀬により編集されました
0
Avatar
岡崎 光輝

必ず、処理が走るプログラムであれば無限ループになりますね。。

レコード詳細で表示中のレコードの更新(自レコードの更新)はREST API経由になると思うのですが、
成功処理にlocation.reload()ということでも駄目ですかね?
これも毎回処理が走っていれば使えない手段ですが。

既知であれば失礼いたしますが、detail.showのイベントでevent.recordの値を変更してreturnしても
レコードは更新されないことはご存じですか?

0
Avatar
小瀬

>detail.showのイベントでevent.recordの値を変更してreturnしてもレコードは更新されないことはご存じですか?

はい、event("record")を更新した後のevent変数をreturnしなければ、更新が反映されないことは存じています。

さらに、非同期実行されるREST APIのpromiseを得た直後の行の「return event;」という文では、未だevent("record")が更新される前のeventのままで、'app.record.detail.show'イベントハンドラを終えざるを得えないので、該当画面を何度開き直し、REST APIでLookup先の値をgetが何度も実行されても、フォーム画面に表示される値は、古い値のままとなり続けるのも 理解できています。

また、非同期実行されるREST APIのthen節内でのevent("record")の更新が実行されうる時期は、'app.record.detail.show'イベントハンドラが一旦終わった後なので、「return event」をしていても、「誰が それを受け取っているのか?不明=無意味」なコードを使ってて、”変だ”とも認識しています。

より広く対応策を募集したいので、遅ればせながら、該当のコードを追記します。

ーーーー

kintone.events.on(['app.record.detail.show', 'app.record.edit.submit.sucess'],
function (event) {
var record = event['record'];
console.log("at 顧客管理 event=", event)

var customerRecordNo2 = record["レコード番号"].value;
// recordレコード番号
var body1 = {
"app": kintone.app.getRelatedRecordsTargetAppId("incomingCallInfo1"),
"fields": ["customerRecordNo1", "stateOfIncomingCall1", "dateOfIncomingCall1", "nextDateOfCall1", "numberOfInCharges1"],
'query': 'customerRecordNo1 = ' + customerRecordNo2 +
' and stateOfIncomingCall1 not in ("成約", "失注", "入電不可") order by dateOfIncomingCall1 asc',
"size": 500
}
// console.log(body1)
kintone.api(kintone.api.url('/k/v1/records', true), 'GET', body1, function (resp1) {
// success
// console.log(resp1);
var lastIncomingCall2Value = resp1.records.reduce(function (accVals, curVal) {
return {
dateOfIncomingCall1: accVals.dateOfIncomingCall1 > curVal.dateOfIncomingCall1.value ? accVals.dateOfIncomingCall1 : curVal.dateOfIncomingCall1.value,
nextDateOfCall1: accVals.nextDateOfCall1 < curVal.nextDateOfCall1.value ? accVals.nextDateOfCall1 : curVal.nextDateOfCall1.value,
numberOfInCharges1: accVals.numberOfInCharges1 + Number(curVal.numberOfInCharges1.value)
};
}, { dateOfIncomingCall1: "0000/01/01", nextDateOfCall1: "9999/12/31", numberOfInCharges1: 0 })
// console.log(lastIncomingCall2Value)

record.dateOfIncomingCall1.value = lastIncomingCall2Value.dateOfIncomingCall1 === "0000/01/01" ? "" : lastIncomingCall2Value.dateOfIncomingCall1;
record.nextDateOfCall1.value = lastIncomingCall2Value.nextDateOfCall1 === "9999/12/31" ? "" : lastIncomingCall2Value.nextDateOfCall1;
record.numberOfInCharges1.value = lastIncomingCall2Value.numberOfInCharges1;
if (event.type === 'app.record.edit.submit.sucess') {
var body2 = {
'app': kintone.app.getId(),
'id': record["$id"].value,
'record': (Object.entries(record)
.map(function (key1Val) {
return (
key1Val[1]["type"] === "CREATED_TIME" ||
key1Val[1]["type"] === "CREATOR" ||
key1Val[1]["type"] === "MODIFIER" ||
key1Val[1]["type"] === "RECORD_NUMBER" ||
key1Val[1]["type"] === "STATUS" ||
key1Val[1]["type"] === "STATUS_ASSIGNEE" ||
key1Val[1]["type"] === "UPDATED_TIME" ||
key1Val[1]["type"][0] === "_" ? null :
key1Val[1]["type"] === "SUBTABLE" ? ( // "(テーブルのフィールドコード)": {value: 値}
[
key1Val[0],
{
value: key1Val[1].value.map(function (rec2) {
return (Object.entries(rec2).map(function (key3Val3) {
return ([key3Val3[0], { value: key3Val3[1]["value"] }]);
})
.reduce(function (h3, kv3) {
h3[kv3[0]] = kv3[1];
return h3;
}, {})
)
;
})
}
]
) : [key1Val[0], { value: key1Val[1]["value"] }]
);
})
.filter(function (key1Val) { return key1Val; })
.reduce(function (h2, kv2) {
h2[kv2[0]] = kv2[1];
return h2;
}, {})
),
'revision': record['$revision'].value
};

console.log("at 顧客管理 非同期更新 put body2=", body2)
kintone.api(kintone.api.url('/k/v1/record', true), 'PUT', body2, function (resp2) {
// success
console.log("at 顧客管理 非同期更新後 responce=", resp2)
return event;
}, function (error) {
// error
console.log(error);
});
console.log("at 顧客管理 非同期更新後 record=", record)
}
console.log("at 顧客管理 同期更新後 event=", event);
return event;
}, function (error1) {
console.error(error1);
});

return event;
});

0
Avatar
岡崎 光輝

コードを見た限りでは、detail.showイベントの時には関連レコードの条件で'GET'しかしておらず、
更新処理をせずに終わっています。
if(event.type === 'app.record.edit.submit.success')
これが原因ではないでしょうか?
detail.showイベントでこの処理をするのであれば、
ifの条件を変えて対応できませんでしょうか?

例えば、関連レコードで一番最後の入電日と表示中のレコードの入電日が違えば更新等。

 

追記:sucessイベントでこちらを処理する場合、
apiを待たずして、successイベントを抜けている可能性があります。

 

コピペ非推奨
下記はコメントアウトのみでなく、kinotne.apiをreturnして同期処理に変更しています。

kintone.events.on('app.record.detail.show',
function (event) {
var record = event['record'];
console.log("at 顧客管理 event=", event)

var customerRecordNo2 = record["レコード番号"].value;
// recordレコード番号
var body1 = {
"app": kintone.app.getRelatedRecordsTargetAppId("incomingCallInfo1"),
"fields": ["customerRecordNo1", "stateOfIncomingCall1", "dateOfIncomingCall1", "nextDateOfCall1", "numberOfInCharges1"],
'query': 'customerRecordNo1 = ' + customerRecordNo2 +
' and stateOfIncomingCall1 not in ("成約", "失注", "入電不可") order by dateOfIncomingCall1 asc',
"size": 500
}
// console.log(body1)
return kintone.api(kintone.api.url('/k/v1/records', true), 'GET', body1, function (resp1) {
// success
// console.log(resp1);
var lastIncomingCall2Value = resp1.records.reduce(function (accVals, curVal) {
return {
dateOfIncomingCall1: accVals.dateOfIncomingCall1 > curVal.dateOfIncomingCall1.value ? accVals.dateOfIncomingCall1 : curVal.dateOfIncomingCall1.value,
nextDateOfCall1: accVals.nextDateOfCall1 < curVal.nextDateOfCall1.value ? accVals.nextDateOfCall1 : curVal.nextDateOfCall1.value,
numberOfInCharges1: accVals.numberOfInCharges1 + Number(curVal.numberOfInCharges1.value)
};
}, { dateOfIncomingCall1: "0000/01/01", nextDateOfCall1: "9999/12/31", numberOfInCharges1: 0 })
// console.log(lastIncomingCall2Value)

record.dateOfIncomingCall1.value = lastIncomingCall2Value.dateOfIncomingCall1 === "0000/01/01" ? "" : lastIncomingCall2Value.dateOfIncomingCall1;
record.nextDateOfCall1.value = lastIncomingCall2Value.nextDateOfCall1 === "9999/12/31" ? "" : lastIncomingCall2Value.nextDateOfCall1;
record.numberOfInCharges1.value = lastIncomingCall2Value.numberOfInCharges1;
if (event.type === 'app.record.edit.submit.sucess') { //*******このifの条件
var body2 = {
'app': kintone.app.getId(),
'id': record["$id"].value,
'record': (Object.entries(record)
.map(function (key1Val) {
return (
key1Val[1]["type"] === "CREATED_TIME" ||
key1Val[1]["type"] === "CREATOR" ||
key1Val[1]["type"] === "MODIFIER" ||
key1Val[1]["type"] === "RECORD_NUMBER" ||
key1Val[1]["type"] === "STATUS" ||
key1Val[1]["type"] === "STATUS_ASSIGNEE" ||
key1Val[1]["type"] === "UPDATED_TIME" ||
key1Val[1]["type"][0] === "_" ? null :
key1Val[1]["type"] === "SUBTABLE" ? ( // "(テーブルのフィールドコード)": {value: 値}
[
key1Val[0],
{
value: key1Val[1].value.map(function (rec2) {
return (Object.entries(rec2).map(function (key3Val3) {
return ([key3Val3[0], { value: key3Val3[1]["value"] }]);
})
.reduce(function (h3, kv3) {
h3[kv3[0]] = kv3[1];
return h3;
}, {})
)
;
})
}
]
) : [key1Val[0], { value: key1Val[1]["value"] }]
);
})
.filter(function (key1Val) { return key1Val; })
.reduce(function (h2, kv2) {
h2[kv2[0]] = kv2[1];
return h2;
}, {})
),
'revision': record['$revision'].value
};

console.log("at 顧客管理 非同期更新 put body2=", body2)
console.log("at 顧客管理 非同期更新後 record=", record)
return kintone.api(kintone.api.url('/k/v1/record', true), 'PUT', body2, function (resp2) {
// success
console.log("at 顧客管理 非同期更新後 responce=", resp2)
return event;
}, function (error) {
// error
console.log(error);
});
}
console.log("at 顧客管理 同期更新後 event=", event);
return event;
}, function (error1) {
console.error(error1);
});

});
0
Avatar
小瀬

重ね重ね、応答ありがとうございます。

例示頂いた、「ハンドル内でpromise<event>をreturnする」という使い方は、「kintoneにおけるPromiseの書き方の基本」のドキュメントも参照し、理解し、コード修正を試みました。

しかしながら、未だ 上手く動かないだけではなく、”保存”ボタンを押下した時、新たな問題現象も発生しました。

>kintone.Promiseオブジェクトをreturnすると、非同期処理の完了を待って次の処理を開始します。

 

コード修正版では、(['app.record.detail.show']用のイベンドハンドラと、['app.record.edit.submit', 'app.record.edit.submit.sucess']向けのイベントハンドラとを分け、各々のpromiseのthen節の最後にpromise<event>をreturnするように変更しました。

それでも、予め手動で入力していたフィールドの値(2020/12/01)がlookup先のレコードの値(2020/12/03)で上書きされませんでした。

でも、その時のイベントハンドラがreturnしたのはlookup先のレコードの値(2020/12/03)を含むpromise<event>です。

 

新たに発生した問題現象は、”保存”ボタンを押したときに、カスタマイズコードの制御外でフームの上部に「GAIA_UN03  レコードを再読み込みしてください」とかいうエラーメッセージが出てきたことです。

 

```

(function () {
    'use strict';
    kintone.events.on(['app.record.detail.show'],
        function (event) {
            var record = event['record'];
            console.log("at 顧客管理 event=", event)

            var customerRecordNo2 = record["レコード番号"].value;
            // recordレコード番号
            var body1 = {
                "app": kintone.app.getRelatedRecordsTargetAppId("incomingCallInfo1"),
                "fields": ["customerRecordNo1", "stateOfIncomingCall1", "dateOfIncomingCall1", "nextDateOfCall1", "numberOfInCharges1"],
                'query': 'customerRecordNo1 = ' + customerRecordNo2 +
                    ' and stateOfIncomingCall1 not in ("成約", "失注", "入電不可") order by dateOfIncomingCall1 asc',
                "size": 500
            }
            // console.log(body1)
            return kintone.api(kintone.api.url('/k/v1/records', true), 'GET', body1)
                .then(resp1 => {
                    // success
                    // console.log(resp1);
                    var lastIncomingCall2Value = resp1.records.reduce(function (accVals, curVal) {
                        // console.log("at 顧客管理 reduce curVal=", curVal)
                        return {
                            dateOfIncomingCall1: curVal.dateOfIncomingCall1.value && (curVal.dateOfIncomingCall1.value.length > 0) && (accVals.dateOfIncomingCall1 < curVal.dateOfIncomingCall1.value) ? curVal.dateOfIncomingCall1.value : accVals.dateOfIncomingCall1,
                            nextDateOfCall1: curVal.nextDateOfCall1.value && (curVal.nextDateOfCall1.value.length > 0) && (accVals.nextDateOfCall1 > curVal.nextDateOfCall1.value) ? curVal.nextDateOfCall1.value : accVals.nextDateOfCall1,
                            numberOfInCharges1: accVals.numberOfInCharges1 + Number(curVal.numberOfInCharges1.value)
                        };
                    }, { dateOfIncomingCall1: "0000/01/01", nextDateOfCall1: "9999/12/31", numberOfInCharges1: 0 })

                    record.dateOfIncomingCall1.value = lastIncomingCall2Value.dateOfIncomingCall1 === "0000/01/01" ? "" : lastIncomingCall2Value.dateOfIncomingCall1;
                    record.nextDateOfCall1.value = lastIncomingCall2Value.nextDateOfCall1 === "9999/12/31" ? "" : lastIncomingCall2Value.nextDateOfCall1;
                    record.numberOfInCharges1.value = lastIncomingCall2Value.numberOfInCharges1;
                    console.log("at 顧客管理 同期更新後 event=", event);
                    return event;
                }).catch(error1 => {
                    console.error(error1);
                });
        });
    kintone.events.on(['app.record.edit.submit', 'app.record.edit.submit.sucess'],
        function (event) {
            var record = event['record'];
            console.log("at 顧客管理 event=", event)

            var customerRecordNo2 = record["レコード番号"].value;
            // recordレコード番号
            var body1 = {
                "app": kintone.app.getRelatedRecordsTargetAppId("incomingCallInfo1"),
                "fields": ["customerRecordNo1", "stateOfIncomingCall1", "dateOfIncomingCall1", "nextDateOfCall1", "numberOfInCharges1"],
                'query': 'customerRecordNo1 = ' + customerRecordNo2 +
                    ' and stateOfIncomingCall1 not in ("成約", "失注", "入電不可") order by dateOfIncomingCall1 asc',
                "size": 500
            }
            // console.log(body1)
            try {
                return kintone.api(kintone.api.url('/k/v1/records', true), 'GET', body1)
                    .then(resp1 => {
                        // success
                        // console.log("at 顧客管理 更新前 resp1=", resp1);
                        var lastIncomingCall2Value = resp1.records.reduce(function (accVals, curVal) {
                            return {
                                dateOfIncomingCall1: curVal.dateOfIncomingCall1.value && (curVal.dateOfIncomingCall1.value.length > 0) && (accVals.dateOfIncomingCall1 < curVal.dateOfIncomingCall1.value) ? curVal.dateOfIncomingCall1.value : accVals.dateOfIncomingCall1,
                                nextDateOfCall1: curVal.nextDateOfCall1.value && (curVal.nextDateOfCall1.value.length > 0) && (accVals.nextDateOfCall1 > curVal.nextDateOfCall1.value) ? curVal.nextDateOfCall1.value : accVals.nextDateOfCall1,
                                numberOfInCharges1: accVals.numberOfInCharges1 + Number(curVal.numberOfInCharges1.value)
                            };
                        }, { dateOfIncomingCall1: "0000/01/01", nextDateOfCall1: "9999/12/31", numberOfInCharges1: 0 })
                        // console.log(lastIncomingCall2Value)

                        record.dateOfIncomingCall1.value = lastIncomingCall2Value.dateOfIncomingCall1 === "0000/01/01" ? "" : lastIncomingCall2Value.dateOfIncomingCall1;
                        record.nextDateOfCall1.value = lastIncomingCall2Value.nextDateOfCall1 === "9999/12/31" ? "" : lastIncomingCall2Value.nextDateOfCall1;
                        record.numberOfInCharges1.value = lastIncomingCall2Value.numberOfInCharges1;
                        var body2 = {
                            'app': kintone.app.getId(),
                            'id': record["$id"].value,
                            'record': (Object.entries(record)
                                .map(function (key1Val) {
                                    return (
                                        key1Val[1]["type"] === "CREATED_TIME" ||
                                            key1Val[1]["type"] === "CREATOR" ||
                                            key1Val[1]["type"] === "MODIFIER" ||
                                            key1Val[1]["type"] === "RECORD_NUMBER" ||
                                            key1Val[1]["type"] === "STATUS" ||
                                            key1Val[1]["type"] === "STATUS_ASSIGNEE" ||
                                            key1Val[1]["type"] === "UPDATED_TIME" ||
                                            key1Val[1]["type"][0] === "_" ? null :
                                            key1Val[1]["type"] === "SUBTABLE" ? ( // "(テーブルのフィールドコード)": {value: 値}
                                                [
                                                    key1Val[0],
                                                    {
                                                        value: key1Val[1].value.map(function (rec2) {
                                                            return (Object.entries(rec2).map(function (key3Val3) {
                                                                return ([key3Val3[0], { value: key3Val3[1]["value"] }]);
                                                            })
                                                                .reduce(function (h3, kv3) {
                                                                    h3[kv3[0]] = kv3[1];
                                                                    return h3;
                                                                }, {})
                                                            )
                                                                ;
                                                        })
                                                    }
                                                ]
                                            ) : [key1Val[0], { value: key1Val[1]["value"] }]
                                    );
                                })
                                .filter(function (key1Val) { return key1Val; })
                                .reduce(function (h2, kv2) {
                                    h2[kv2[0]] = kv2[1];
                                    return h2;
                                }, {})
                            ),
                            'revision': record['$revision'].value
                        };
                        console.log("at 顧客管理 非同期更新 before put body2=", body2);
                        return kintone.api(kintone.api.url('/k/v1/record', true), 'PUT', body2);
                    }).then(resp2 => {
                        // success
                        console.log("at 顧客管理 非同期更新後 responce=", resp2)
                        return event;
                    }).catch(error1 => {
                        // error
                        console.error(error1);
                        return event;
                    });
            } catch (error2) {
                console.error(error2);
            }
        });
    kintone.events.on(['app.record.detail.show'], function (event) {
        var record = event['record'];
        var telNo1 = record['representative_tel1']['value'];
        var mySpaceFieldLink1 = document.createElement('a');
        if ((typeof telNo1 === "string") && (telNo1.length > 0)) {
            telNo1 = telNo1.split("").map(function (c) { return "0" <= c && c <= "9" ? c : ""; }).join("");
            if (telNo1.length > 0) {
                mySpaceFieldLink1.id = 'repCalc_callTo1_ref';
                mySpaceFieldLink1.innerText = telNo1;
                mySpaceFieldLink1.href = "callto:" + telNo1;
            }
        }
        kintone.app.record.getSpaceElement('repCalc_callTo1').appendChild(mySpaceFieldLink1);

        var telNo2 = record['representative_tel2']['value'];
        var mySpaceFieldLink2 = document.createElement('a');
        if ((typeof telNo2 === "string") && (telNo2.length > 0)) {
            telNo2 = telNo2.split("").map(function (c) { return "0" <= c && c <= "9" ? c : ""; }).join("");
            if (telNo2.length > 0) {
                mySpaceFieldLink2.id = 'repCalc_callTo2_ref';
                mySpaceFieldLink2.innerText = telNo2;
                mySpaceFieldLink2.href = "callTo:" + telNo2;
            }
        }
        kintone.app.record.getSpaceElement('repCalc_callTo2').appendChild(mySpaceFieldLink2);

        return event;
    });
})();

```

0
Avatar
岡崎 光輝

すみません、イベントを分ける意図が読み取れませんが、
動きとしては、いつ、どのような条件でどのような操作を行いたいのですか?

推測ですがレコードを閲覧中に入電日に差があれば更新して、閲覧中のレコードを更新する。
という動きかと思いますが、detail.showイベント内だけで完結するのではないでしょうか?

各イベントの発火タイミングのドキュメントを再度ご確認されてはいかがでしょうか。
app.record.edit.submitとedit.submit.successで同じ処理をするということは、
保存ボタンが押されて実行→保存が成功するタイミングで実行と二度実行されていませんか?
加えて、detail.showでは単に、日付のチェックのみ実行されているだけかと。

イベント一覧

関数のスコープ

0
Avatar
小瀬

アプリの仕様に遡上った対策検討ですか、、、

>いつ、どのような条件でどのような操作を行いたいのですか?

A:{ルックアップ先の未完了案件の入電日の最大値または ルックアップ先に記録しなくて当該フォームに手動入力した入電日の}大きいほうを入電日として蓄積。

B:次回発信時は、{ルックアップ先の未完了案件の次回発信時のの最小値、または当該フォームに手動入力した次回発信日}の小さいほうを次回発信日として蓄積。

>detail.showイベント内だけで完結するのではないでしょうか?

当該フォームのdetail.showだけだと、当該フォームでeditモードに入り手動入力で更新した直後に、min/maxのチェック結果を反映できません。

また、ルックアップ先の更新時に当該フォーム側に書き込む方式だと、「案件完了時に幻となる次回発信日をmin対象から外して 次に小さな値を探す」というルックアップ先アプリ内の関連レコード検索が面倒(検索期間中にダーディな値を読み取ってしまうのを避けるのが困難)なので、当該フォーム側の更新時に、「人間が目視確認して更新する」というアプリの仕様にしようとしています。

>保存が成功するタイミングで実行と二度実行されていませんか?

イイエ、直前コメントの添付の図のconsole.logの出力部を観て確認できるように、当該の自作ハンドラは1度だけapp.record.edit.submitイベントで発火していました。 

当初期待していたedit.submit.successというイベントでは 当該ハンドラが発火しなかったので、不思議だとは思いながらapp.record.edit.submitで発火するようにしました。

とはいえ、自作イベントハンドラが起動されないだけで、実は、edit.submit.successイベントで$revisionがインクリメントされていたとすると、自作イベントハンドラでの更新と合わせて2度 $revisionがインクリメントされて、今般の「レコードを読み直してください」というエラーメッセージが出たのだと解釈できます。

ーーーーーー

issueが発散して 解決策無となるのは嫌なので、まずは、タイトルに示した現象で、'app.record.detail.show'側のイベント発火時に、フィールドの更新が出来なかった現象を解決したく、よろしくお願いします。

 

0
Avatar
岡崎 光輝

submit.successでrevisionはインクリメントされているようでした。
なので、仰る通りに
submitでイベント発火で処理をすべきかと思います。

submitで表示中のレコードの値を変更して反映するのであれば、eventをreturnしてあげるとシンプルになるかと。

code

kintone.events.on(['app.record.detail.show','app.record.edit.submit'],

    function (event) {

        var record = event['record'];

        console.log("at 顧客管理 event=", event)

        var customerRecordNo2 = record["レコード番号"].value;

        // recordレコード番号

        var body1 = {

            "app": kintone.app.getRelatedRecordsTargetAppId("incomingCallInfo1"),

            "fields": ["customerRecordNo1", "stateOfIncomingCall1", "dateOfIncomingCall1", "nextDateOfCall1", "numberOfInCharges1"],

            'query': 'customerRecordNo1 = ' + customerRecordNo2 +

                ' and stateOfIncomingCall1 not in ("成約", "失注", "入電不可") order by dateOfIncomingCall1 asc',

            "size": 500

        }

        // console.log(body1)

        return kintone.api(kintone.api.url('/k/v1/records', true), 'GET', body1, function (resp1) {

            // success

            // console.log(resp1);

            var lastIncomingCall2Value = resp1.records.reduce(function (accVals, curVal) {

                return {

                    dateOfIncomingCall1: accVals.dateOfIncomingCall1 > curVal.dateOfIncomingCall1.value ? accVals.dateOfIncomingCall1 : curVal.dateOfIncomingCall1.value,

                    nextDateOfCall1: accVals.nextDateOfCall1 < curVal.nextDateOfCall1.value ? accVals.nextDateOfCall1 : curVal.nextDateOfCall1.value,

                    numberOfInCharges1: accVals.numberOfInCharges1 + Number(curVal.numberOfInCharges1.value)

                };

            }, { dateOfIncomingCall1: "0000/01/01", nextDateOfCall1: "9999/12/31", numberOfInCharges1: 0 })

            // console.log(lastIncomingCall2Value)

            record.dateOfIncomingCall1.value = lastIncomingCall2Value.dateOfIncomingCall1 === "0000/01/01" ? "" : lastIncomingCall2Value.dateOfIncomingCall1;

            record.nextDateOfCall1.value = lastIncomingCall2Value.nextDateOfCall1 === "9999/12/31" ? "" : lastIncomingCall2Value.nextDateOfCall1;

            record.numberOfInCharges1.value = lastIncomingCall2Value.numberOfInCharges1;

            

            //app.record.detal.showであればAPIで更新をかける。

            /*

                しかし、このままだとdetail.showのイベント発火時には二度も通信を行うことになるので、

                下記のifに更新が必要ない条件を追記して更新の通信を行わないようにすることがおすすめ。

            */

            if (event.type = 'app.record.detail.show') {

                var body2 = {

                    'app': kintone.app.getId(),

                    'id': record["$id"].value,

                    'record': (Object.entries(record)

                        .map(function (key1Val) {

                            return (

                                key1Val[1]["type"] === "CREATED_TIME" ||

                                    key1Val[1]["type"] === "CREATOR" ||

                                    key1Val[1]["type"] === "MODIFIER" ||

                                    key1Val[1]["type"] === "RECORD_NUMBER" ||

                                    key1Val[1]["type"] === "STATUS" ||

                                    key1Val[1]["type"] === "STATUS_ASSIGNEE" ||

                                    key1Val[1]["type"] === "UPDATED_TIME" ||

                                    key1Val[1]["type"][0] === "_" ? null :

                                    key1Val[1]["type"] === "SUBTABLE" ? ( // "(テーブルのフィールドコード)": {value: 値}

                                        [

                                            key1Val[0],

                                            {

                                                value: key1Val[1].value.map(function (rec2) {

                                                    return (Object.entries(rec2).map(function (key3Val3) {

                                                        return ([key3Val3[0], { value: key3Val3[1]["value"] }]);

                                                    })

                                                        .reduce(function (h3, kv3) {

                                                            h3[kv3[0]] = kv3[1];

                                                            return h3;

                                                        }, {})

                                                    )

                                                        ;

                                                })

                                            }

                                        ]

                                    ) : [key1Val[0], { value: key1Val[1]["value"] }]

                            );

                        })

                        .filter(function (key1Val) { return key1Val; })

                        .reduce(function (h2, kv2) {

                            h2[kv2[0]] = kv2[1];

                            return h2;

                        }, {})

                    ),

                    'revision': record['$revision'].value

                };

                console.log("at 顧客管理 非同期更新 put body2=", body2)

                return kintone.api(kintone.api.url('/k/v1/record', true), 'PUT', body2, function (resp2) {

                    // success

                    console.log("at 顧客管理 非同期更新後 responce=", resp2)

                    console.log("at 顧客管理 非同期更新後 record=", record)

                }, function (error) {

                    // error

                    console.log(error);

                });

            }

            console.log("at 顧客管理 同期更新後 event=", event);

            return event; //submitイベントであればここで自レコの値が更新される

        }, function (error1) {

            console.error(error1);

        });

    });
0
Avatar
小瀬

応答ありがとうございます。

しかしながら、例示されたコードは、kintone.api rest-APIのPUTの非同期実行結果であるresp2を握りつぶしているだけで、「$revisionが最新ではない」という内部エラーの発生を回避できるものではありませんでした。 エラー扱いとなるので、当然、DB内容も更新できませんでした。

処理を複雑化していると指摘されたif文は、下記の場合分け目的のものでしたが、イベントハンドラ毎にreturn時に有効なプロパティが異なる(event.recordが参照されなかったり、event.urlに遷移したり)ので、別々のイベントハンドラに分割せざるをえないと考えて、一つ前のコメント以降で 分割版にしています。

・'app.record.detail.show':「一覧表示画面から詳細表示画面に入った場合は、フォーム表示内容のみを更新して、表示を期待]

・'app.record.edit.submit.success':「詳細表示画面の中で、保存ボタンが押された場合は、DB内容が更新されているので、自前のカスタムコードで値を変更したフィールドの値をDBに追いつき書き込みする」

ここで、「$revisionが最新ではない」というエラーの対処としては、公式ドキュメントに記載の無い内部的な挙動である「submit.successイベント発火時は、$revision.valueがインクリメントされた状態となる)」という事から、下記のように「$revision.value +1」という値を用いるコードを変更したら、保存後の表示状態も、DB格納内容も、期待通りの値に更新されました。

しかしながら、アンドキュメントな挙動にそった このコードを改善できるようなAPIの使い方は無いものでしょうか?

また、保存ボタンを押す前の「一覧画面から詳細画面に入った時のフィールドの値を 自動変更できる」というAPIの使い方は、無いものでしょうか?

```code

kintone.events.on(['app.record.detail.show'],
function (event) {
var record = event['record'];
console.log("at 顧客管理 event=", event)

var customerRecordNo2 = record["レコード番号"].value;
// recordレコード番号
var body1 = {
"app": kintone.app.getRelatedRecordsTargetAppId("incomingCallInfo1"),
"fields": ["customerRecordNo1", "stateOfIncomingCall1", "dateOfIncomingCall1", "nextDateOfCall1", "numberOfInCharges1"],
'query': 'customerRecordNo1 = ' + customerRecordNo2 +
' and stateOfIncomingCall1 not in ("成約", "失注", "入電不可") order by dateOfIncomingCall1 asc',
"size": 500
}
// console.log(body1)
return kintone.api(kintone.api.url('/k/v1/records', true), 'GET', body1)
.then(resp1 => {
// success
// console.log(resp1);
var lastIncomingCall2Value = resp1.records.reduce(function (accVals, curVal) {
// console.log("at 顧客管理 reduce curVal=", curVal)
return {
dateOfIncomingCall1: curVal.dateOfIncomingCall1.value && (curVal.dateOfIncomingCall1.value.length > 0) && (accVals.dateOfIncomingCall1 < curVal.dateOfIncomingCall1.value) ? curVal.dateOfIncomingCall1.value : accVals.dateOfIncomingCall1,
nextDateOfCall1: curVal.nextDateOfCall1.value && (curVal.nextDateOfCall1.value.length > 0) && (accVals.nextDateOfCall1 > curVal.nextDateOfCall1.value) ? curVal.nextDateOfCall1.value : accVals.nextDateOfCall1,
numberOfInCharges1: accVals.numberOfInCharges1 + Number(curVal.numberOfInCharges1.value)
};
}, { dateOfIncomingCall1: "0000/01/01", nextDateOfCall1: "9999/12/31", numberOfInCharges1: 0 })

record.dateOfIncomingCall1.value = lastIncomingCall2Value.dateOfIncomingCall1 === "0000/01/01" ? "" : lastIncomingCall2Value.dateOfIncomingCall1;
record.nextDateOfCall1.value = lastIncomingCall2Value.nextDateOfCall1 === "9999/12/31" ? "" : lastIncomingCall2Value.nextDateOfCall1;
record.numberOfInCharges1.value = lastIncomingCall2Value.numberOfInCharges1;
console.log("at 顧客管理 同期更新後 event=", event);
return event;
}).catch(error1 => {
console.error(error1);
event.error = JSON.stringify(error1)
return event;
});
});
kintone.events.on([/*'app.record.edit.submit',*/ 'app.record.edit.submit.success'],
function (event) {
var record = event['record'];
console.log("at 顧客管理 edit event=", event)

var customerRecordNo2 = record["レコード番号"].value;
// recordレコード番号
var body1 = {
"app": kintone.app.getRelatedRecordsTargetAppId("incomingCallInfo1"),
"fields": ["customerRecordNo1", "stateOfIncomingCall1", "dateOfIncomingCall1", "nextDateOfCall1", "numberOfInCharges1"],
'query': 'customerRecordNo1 = ' + customerRecordNo2 +
' and stateOfIncomingCall1 not in ("成約", "失注", "入電不可") order by dateOfIncomingCall1 asc',
"size": 500
}
// console.log(body1)
try {
return kintone.api(kintone.api.url('/k/v1/records', true), 'GET', body1)
.then(resp1 => {
// success
// console.log("at 顧客管理 更新前 resp1=", resp1);
var lastIncomingCall2Value = resp1.records.reduce(function (accVals, curVal) {
return {
dateOfIncomingCall1: curVal.dateOfIncomingCall1.value && (curVal.dateOfIncomingCall1.value.length > 0) && (accVals.dateOfIncomingCall1 < curVal.dateOfIncomingCall1.value) ? curVal.dateOfIncomingCall1.value : accVals.dateOfIncomingCall1,
nextDateOfCall1: curVal.nextDateOfCall1.value && (curVal.nextDateOfCall1.value.length > 0) && (accVals.nextDateOfCall1 > curVal.nextDateOfCall1.value) ? curVal.nextDateOfCall1.value : accVals.nextDateOfCall1,
numberOfInCharges1: accVals.numberOfInCharges1 + Number(curVal.numberOfInCharges1.value)
};
}, { dateOfIncomingCall1: "0000/01/01", nextDateOfCall1: "9999/12/31", numberOfInCharges1: 0 })
// console.log(lastIncomingCall2Value)

record.dateOfIncomingCall1.value = lastIncomingCall2Value.dateOfIncomingCall1 === "0000/01/01" ? "" : lastIncomingCall2Value.dateOfIncomingCall1;
record.nextDateOfCall1.value = lastIncomingCall2Value.nextDateOfCall1 === "9999/12/31" ? "" : lastIncomingCall2Value.nextDateOfCall1;
record.numberOfInCharges1.value = lastIncomingCall2Value.numberOfInCharges1;
var body2 = {
'app': kintone.app.getId(),
'id': record["$id"].value,
'record': (Object.entries(record)
.map(function (key1Val) {
return (
key1Val[1]["type"] === "CREATED_TIME" ||
key1Val[1]["type"] === "CREATOR" ||
key1Val[1]["type"] === "MODIFIER" ||
key1Val[1]["type"] === "RECORD_NUMBER" ||
key1Val[1]["type"] === "STATUS" ||
key1Val[1]["type"] === "STATUS_ASSIGNEE" ||
key1Val[1]["type"] === "UPDATED_TIME" ||
key1Val[1]["type"][0] === "_" ? null :
key1Val[1]["type"] === "SUBTABLE" ? ( // "(テーブルのフィールドコード)": {value: 値}
[
key1Val[0],
{
value: key1Val[1].value.map(function (rec2) {
return (Object.entries(rec2).map(function (key3Val3) {
return ([key3Val3[0], { value: key3Val3[1]["value"] }]);
})
.reduce(function (h3, kv3) {
h3[kv3[0]] = kv3[1];
return h3;
}, {})
)
;
})
}
]
) : [key1Val[0], { value: key1Val[1]["value"] }]
);
})
.filter(function (key1Val) { return key1Val; })
.reduce(function (h2, kv2) {
h2[kv2[0]] = kv2[1];
return h2;
}, {})
),
'revision': {type: "__REVISION__", value: record['$revision'].value + 1}
};
console.log("at 顧客管理 非同期更新 before put body2=", body2);
return kintone.api(kintone.api.url('/k/v1/record', true), 'PUT', body2);
}).then(resp2 => {
// success
console.log("at 顧客管理 非同期更新後 responce=", resp2, event)
return event;
}).catch(error1 => {
// error
console.error(error1);
event.error = JSON.stringify(error1)
return event;
});
} catch (error2) {
console.error(error2);
event.error = JSON.stringify(error2)
return event;
}
});

```

★一覧画面から詳細画面に入った時は、event.recordを更新したにも関わらず、表示内容が変更されなかった。

 

★submit.sucessイベントハンドラでは、所望の更新が出来たが、ここまでの操作ソノモノが煩わしい。

小瀬により編集されました
0
Avatar
岡崎 光輝

>>★一覧画面から詳細画面に入った時は、event.recordを更新したにも関わらず、表示内容が変更されなかった。

一番初めにお伝えしたときに伝わっていなかったと思います。
detail.showでのevent.recordを変更してreturnしても変更はそもそもDBに行きません。
detail.showでの自レコ更新はAPIになります。

 

>>また、保存ボタンを押す前の「一覧画面から詳細画面に入った時のフィールドの値を 自動変更できる」というAPIの使い方は、無いものでしょうか?

detail.showイベント
event.recordと関連レコードのクエリでGETしたrecordsの日付値チェック
→期待通り(日付のチェックで処理の必要なし)の場合終了(GETして確認処理のみ)
→処理の必要ありの場合、APIで自レコの日付フィールドを更新という流れで処理ができると思います。
前回の返信では上記の分岐のことを指しておりました。

 

submitイベント
event.recordと関連レコードのクエリでGETしたrecordsの日付値チェック
→期待通り(日付のチェックで処理の必要なし)の場合終了(GETして確認処理のみ)
→処理の必要ありの場合、return event;で自レコの日付フィールドを変更して従来の保存処理へという流れ

今一度、各イベントの特性をドキュメントでご確認をした方がよろしいかと思いました。

以上より、最新の小瀬さんのコードを少し変更しました。
イベントを逆にしています。

//************変更点****************/とコメントアウトしていますので、ご確認を。
kintone.events.on(['app.record.edit.submit'],//************変更点****************/

    function (event) {

        var record = event['record'];

        console.log("at 顧客管理 event=", event)

        var customerRecordNo2 = record["レコード番号"].value;

        // recordレコード番号

        var body1 = {

            "app": kintone.app.getRelatedRecordsTargetAppId("incomingCallInfo1"),

            "fields": ["customerRecordNo1", "stateOfIncomingCall1", "dateOfIncomingCall1", "nextDateOfCall1", "numberOfInCharges1"],

            'query': 'customerRecordNo1 = ' + customerRecordNo2 +

                ' and stateOfIncomingCall1 not in ("成約", "失注", "入電不可") order by dateOfIncomingCall1 asc',

            "size": 500

        }

        // console.log(body1)

        return kintone.api(kintone.api.url('/k/v1/records', true), 'GET', body1)

            .then(resp1 => {

                // success

                // console.log(resp1);

                var lastIncomingCall2Value = resp1.records.reduce(function (accVals, curVal) {

                    // console.log("at 顧客管理 reduce curVal=", curVal)

                    return {

                        dateOfIncomingCall1: curVal.dateOfIncomingCall1.value && (curVal.dateOfIncomingCall1.value.length > 0) && (accVals.dateOfIncomingCall1 < curVal.dateOfIncomingCall1.value) ? curVal.dateOfIncomingCall1.value : accVals.dateOfIncomingCall1,

                        nextDateOfCall1: curVal.nextDateOfCall1.value && (curVal.nextDateOfCall1.value.length > 0) && (accVals.nextDateOfCall1 > curVal.nextDateOfCall1.value) ? curVal.nextDateOfCall1.value : accVals.nextDateOfCall1,

                        numberOfInCharges1: accVals.numberOfInCharges1 + Number(curVal.numberOfInCharges1.value)

                    };

                }, { dateOfIncomingCall1: "0000/01/01", nextDateOfCall1: "9999/12/31", numberOfInCharges1: 0 })

                record.dateOfIncomingCall1.value = lastIncomingCall2Value.dateOfIncomingCall1 === "0000/01/01" ? "" : lastIncomingCall2Value.dateOfIncomingCall1;

                record.nextDateOfCall1.value = lastIncomingCall2Value.nextDateOfCall1 === "9999/12/31" ? "" : lastIncomingCall2Value.nextDateOfCall1;

                record.numberOfInCharges1.value = lastIncomingCall2Value.numberOfInCharges1;

                console.log("at 顧客管理 同期更新後 event=", event);

                return event;

            }).catch(error1 => {

                console.error(error1);

                event.error = JSON.stringify(error1)

                return event;

            });

    });

kintone.events.on(['app.record.detail.show'],//************変更点****************/

    function (event) {

        var record = event['record'];

        console.log("at 顧客管理 edit event=", event)

        var customerRecordNo2 = record["レコード番号"].value;

        // recordレコード番号

        var body1 = {

            "app": kintone.app.getRelatedRecordsTargetAppId("incomingCallInfo1"),

            "fields": ["customerRecordNo1", "stateOfIncomingCall1", "dateOfIncomingCall1", "nextDateOfCall1", "numberOfInCharges1"],

            'query': 'customerRecordNo1 = ' + customerRecordNo2 +

                ' and stateOfIncomingCall1 not in ("成約", "失注", "入電不可") order by dateOfIncomingCall1 asc',

            "size": 500

        }

        // console.log(body1)

        try {

            return kintone.api(kintone.api.url('/k/v1/records', true), 'GET', body1)

                .then(resp1 => {

                    // success

                    // console.log("at 顧客管理 更新前 resp1=", resp1);

                    var lastIncomingCall2Value = resp1.records.reduce(function (accVals, curVal) {

                        return {

                            dateOfIncomingCall1: curVal.dateOfIncomingCall1.value && (curVal.dateOfIncomingCall1.value.length > 0) && (accVals.dateOfIncomingCall1 < curVal.dateOfIncomingCall1.value) ? curVal.dateOfIncomingCall1.value : accVals.dateOfIncomingCall1,

                            nextDateOfCall1: curVal.nextDateOfCall1.value && (curVal.nextDateOfCall1.value.length > 0) && (accVals.nextDateOfCall1 > curVal.nextDateOfCall1.value) ? curVal.nextDateOfCall1.value : accVals.nextDateOfCall1,

                            numberOfInCharges1: accVals.numberOfInCharges1 + Number(curVal.numberOfInCharges1.value)

                        };

                    }, { dateOfIncomingCall1: "0000/01/01", nextDateOfCall1: "9999/12/31", numberOfInCharges1: 0 })

                    // console.log(lastIncomingCall2Value)

                    record.dateOfIncomingCall1.value = lastIncomingCall2Value.dateOfIncomingCall1 === "0000/01/01" ? "" : lastIncomingCall2Value.dateOfIncomingCall1;

                    record.nextDateOfCall1.value = lastIncomingCall2Value.nextDateOfCall1 === "9999/12/31" ? "" : lastIncomingCall2Value.nextDateOfCall1;

                    record.numberOfInCharges1.value = lastIncomingCall2Value.numberOfInCharges1;

/*ここで更新が必要なければreturnというifで無駄な自レコ更新を防止できます。*/

                    var body2 = {

                        'app': kintone.app.getId(),

                        'id': record["$id"].value,

                        'record': (Object.entries(record)

                            .map(function (key1Val) {

                                return (

                                    key1Val[1]["type"] === "CREATED_TIME" ||

                                        key1Val[1]["type"] === "CREATOR" ||

                                        key1Val[1]["type"] === "MODIFIER" ||

                                        key1Val[1]["type"] === "RECORD_NUMBER" ||

                                        key1Val[1]["type"] === "STATUS" ||

                                        key1Val[1]["type"] === "STATUS_ASSIGNEE" ||

                                        key1Val[1]["type"] === "UPDATED_TIME" ||

                                        key1Val[1]["type"][0] === "_" ? null :

                                        key1Val[1]["type"] === "SUBTABLE" ? ( // "(テーブルのフィールドコード)": {value: 値}

                                            [

                                                key1Val[0],

                                                {

                                                    value: key1Val[1].value.map(function (rec2) {

                                                        return (Object.entries(rec2).map(function (key3Val3) {

                                                            return ([key3Val3[0], { value: key3Val3[1]["value"] }]);

                                                        })

                                                            .reduce(function (h3, kv3) {

                                                                h3[kv3[0]] = kv3[1];

                                                                return h3;

                                                            }, {})

                                                        )

                                                            ;

                                                    })

                                                }

                                            ]

                                        ) : [key1Val[0], { value: key1Val[1]["value"] }]

                                );

                            })

                            .filter(function (key1Val) { return key1Val; })

                            .reduce(function (h2, kv2) {

                                h2[kv2[0]] = kv2[1];

                                return h2;

                            }, {})

                        ),

                        'revision': { type: "__REVISION__", value: record['$revision'].value }//************変更点****************/

                    };

                    console.log("at 顧客管理 非同期更新 before put body2=", body2);

                    return kintone.api(kintone.api.url('/k/v1/record', true), 'PUT', body2)//************変更点****************/

                    .then(resp2 => {

                        // success

                        console.log("at 顧客管理 非同期更新後 responce=", resp2, event)

                        location.reload();//************変更点****************/

                    }).catch(error1 => {

                        // error

                        console.error(error1);

                        event.error = JSON.stringify(error1)

                        return event;

                    });

                })

        } catch (error2) {

            console.error(error2);

            event.error = JSON.stringify(error2)

            return event;

        }

    });
岡崎 光輝により編集されました
0
Avatar
小瀬

応答ありがとうございます。

例示されたコードでは、 「 location.reload();」が無条件で発行されていて、無限ループになりましたが、

そこを「値に変更があったことを判定するisChangedフラグを追加し、

return eventし、kintoneによって再描画が終わるであろう頃合いの30ミリ秒の後に、isChangedの場合のみ遅延して location.reload()を実行する」

と、いう風に変更して、ようやく 所望の結果を得ることができました。

 

でも、項目数が10個程度で多いのか?通通信環境が低速通信なのか?、location.reload()による再描画で、画面がマバタクのを感じるのが、チョット気になりました。

また、promiseのthen()メソッドの連鎖やsettimeout等の非同期処理を条件付きでスキップできるテクニックが思い浮かばなかったので、元々は一つの関数だった所が、イベントの種類ごとに分かれたハンドリング関数になってしまって、ビジネス・ロジック上デリケートなコードを複製しているのも、美しくないと感じています。

 

ここまでの改善を適用したコードを記載しますので、「画面がマバタク]等、改善の余地があれば、ご指摘願います。

 

```

kintone.events.on(['app.record.edit.submit'],
function (event) {
var record = event['record'];
console.log("at 顧客管理 event=", event)

var customerRecordNo2 = record["レコード番号"].value;
// recordレコード番号
var body1 = {
"app": kintone.app.getRelatedRecordsTargetAppId("incomingCallInfo1"),
"fields": ["customerRecordNo1", "stateOfIncomingCall1", "dateOfIncomingCall1", "nextDateOfCall1", "numberOfInCharges1"],
'query': 'customerRecordNo1 = ' + customerRecordNo2 +
' and stateOfIncomingCall1 not in ("成約", "失注", "入電不可") order by dateOfIncomingCall1 asc',
"size": 500
}
// console.log(body1)
return kintone.api(kintone.api.url('/k/v1/records', true), 'GET', body1)
.then(resp1 => {
// success
// console.log(resp1);
var lastIncomingCall2Value = resp1.records.reduce(function (accVals, curVal) {
// console.log("at 顧客管理 reduce curVal=", curVal)
return {
dateOfIncomingCall1: curVal.dateOfIncomingCall1.value && (curVal.dateOfIncomingCall1.value.length > 0) && (accVals.dateOfIncomingCall1 < curVal.dateOfIncomingCall1.value) ? curVal.dateOfIncomingCall1.value : accVals.dateOfIncomingCall1,
nextDateOfCall1: curVal.nextDateOfCall1.value && (curVal.nextDateOfCall1.value.length > 0) && (accVals.nextDateOfCall1 > curVal.nextDateOfCall1.value) ? curVal.nextDateOfCall1.value : accVals.nextDateOfCall1,
numberOfInCharges1: accVals.numberOfInCharges1 + Number(curVal.numberOfInCharges1.value)
};
}, { dateOfIncomingCall1: "0000/01/01", nextDateOfCall1: "9999/12/31", numberOfInCharges1: 0 })

if (lastIncomingCall2Value.dateOfIncomingCall1 === "0000/01/01") {
lastIncomingCall2Value.dateOfIncomingCall1 = "";
}
if (lastIncomingCall2Value.nextDateOfCall1 === "9999/12/31") {
lastIncomingCall2Value.nextDateOfCall1 = "";
}
// var isChanged = (record.dateOfIncomingCall1.value !== lastIncomingCall2Value.dateOfIncomingCall1) ||
// (record.nextDateOfCall1.value !== lastIncomingCall2Value.nextDateOfCall1) ||
// (record.numberOfInCharges1.value !== lastIncomingCall2Value.numberOfInCharges1);

record.dateOfIncomingCall1.value = lastIncomingCall2Value.dateOfIncomingCall1;
record.nextDateOfCall1.value = lastIncomingCall2Value.nextDateOfCall1;
record.numberOfInCharges1.value = lastIncomingCall2Value.numberOfInCharges1;
console.log("at 顧客管理 同期更新後 event=", event);
return event;
}).catch(error1 => {
console.error(error1);
event.error = JSON.stringify(error1)
return event;
});
});
kintone.events.on(['app.record.detail.show'],
function (event) {
var record = event['record'];
console.log("at 顧客管理 edit event=", event)

var customerRecordNo2 = record["レコード番号"].value;
// recordレコード番号
var body1 = {
"app": kintone.app.getRelatedRecordsTargetAppId("incomingCallInfo1"),
"fields": ["customerRecordNo1", "stateOfIncomingCall1", "dateOfIncomingCall1", "nextDateOfCall1", "numberOfInCharges1"],
'query': 'customerRecordNo1 = ' + customerRecordNo2 +
' and stateOfIncomingCall1 not in ("成約", "失注", "入電不可") order by dateOfIncomingCall1 asc',
"size": 500
}
// console.log(body1)
try {
return kintone.api(kintone.api.url('/k/v1/records', true), 'GET', body1)
.then(resp1 => {
// success
// console.log("at 顧客管理 更新前 resp1=", resp1);
var lastIncomingCall2Value = resp1.records.reduce(function (accVals, curVal) {
return {
dateOfIncomingCall1: curVal.dateOfIncomingCall1.value &&
(curVal.dateOfIncomingCall1.value.length > 0) &&
(accVals.dateOfIncomingCall1 < curVal.dateOfIncomingCall1.value) ? curVal.dateOfIncomingCall1.value : accVals.dateOfIncomingCall1,
nextDateOfCall1: curVal.nextDateOfCall1.value &&
(curVal.nextDateOfCall1.value.length > 0) &&
(accVals.nextDateOfCall1 > curVal.nextDateOfCall1.value) ? curVal.nextDateOfCall1.value : accVals.nextDateOfCall1,
numberOfInCharges1: accVals.numberOfInCharges1 + Number(curVal.numberOfInCharges1.value)
};
}, { dateOfIncomingCall1: "0000/01/01", nextDateOfCall1: "9999/12/31", numberOfInCharges1: 0 })
// console.log(lastIncomingCall2Value)
if (lastIncomingCall2Value.dateOfIncomingCall1 === "0000/01/01") {
lastIncomingCall2Value.dateOfIncomingCall1 = "";
}
if (lastIncomingCall2Value.nextDateOfCall1 === "9999/12/31") {
lastIncomingCall2Value.nextDateOfCall1 = "";
}
var isChanged = (record.dateOfIncomingCall1.value != lastIncomingCall2Value.dateOfIncomingCall1) ||
(record.nextDateOfCall1.value != lastIncomingCall2Value.nextDateOfCall1) ||
(record.numberOfInCharges1.value != lastIncomingCall2Value.numberOfInCharges1);

record.dateOfIncomingCall1.value = lastIncomingCall2Value.dateOfIncomingCall1;
record.nextDateOfCall1.value = lastIncomingCall2Value.nextDateOfCall1;
record.numberOfInCharges1.value = lastIncomingCall2Value.numberOfInCharges1;
if (isChanged) {
var body2 = {
'app': kintone.app.getId(),
'id': record["$id"].value,
'record': (Object.entries(record)
.map(function (key1Val) {
return (
key1Val[1]["type"] === "CREATED_TIME" ||
key1Val[1]["type"] === "CREATOR" ||
key1Val[1]["type"] === "MODIFIER" ||
key1Val[1]["type"] === "RECORD_NUMBER" ||
key1Val[1]["type"] === "STATUS" ||
key1Val[1]["type"] === "STATUS_ASSIGNEE" ||
key1Val[1]["type"] === "UPDATED_TIME" ||
key1Val[1]["type"][0] === "_" ? null :
key1Val[1]["type"] === "SUBTABLE" ? ( // "(テーブルのフィールドコード)": {value: 値}
[
key1Val[0],
{
value: key1Val[1].value.map(function (rec2) {
return (Object.entries(rec2).map(function (key3Val3) {
return ([key3Val3[0], { value: key3Val3[1]["value"] }]);
})
.reduce(function (h3, kv3) {
h3[kv3[0]] = kv3[1];
return h3;
}, {})
)
;
})
}
]
) : [key1Val[0], { value: key1Val[1]["value"] }]
);
})
.filter(function (key1Val) { return key1Val; })
.reduce(function (h2, kv2) {
h2[kv2[0]] = kv2[1];
return h2;
}, {})
),
'revision': { type: "__REVISION__", value: record['$revision'].value + 1 }
};
console.log("at 顧客管理 非同期更新 before put body2=", body2);
return kintone.api(kintone.api.url('/k/v1/record', true), 'PUT', body2);
} else {
return null;
}
}).then(resp2 => {
if (resp2) { // success
console.log("at 顧客管理 非同期更新後 responce=", resp2, event)
setTimeout(() => {
location.reload(); // 無限ループ抑止の為、更新時のみ遅延実行
}, 30)
} else {
console.log("at 顧客管理 非同期更新セズ")
}
return event;
}).catch(error1 => {
// error
console.error(error1);
event.error = JSON.stringify(error1)
return event;
});
} catch (error2) {
console.error(error2);
event.error = JSON.stringify(error2)
return event;
}
});

```

 

0
Avatar
岡崎 光輝

カスタマイズ完成されたようで、よかったです。
isChangedの条件を加えられて無限ループ防止(無駄な更新を防止)、
こちらも加えられ、お伝えしたかったことはすべて伝わりました。

ここで、イベントで分けてコーディングしているものを合わせることができそうなので、
私の所見を以下に残します。

submitイベントとdetailイベントでは自レコの更新方法が違うだけで
eventオブジェクトをリターンするのか、APIで更新をかけるかなので、
event.typeで条件分岐すると余計なコーディングを行わずに済むのではないかと思います。

変更前


if(isChanged){
  /*更新*/
}else{
  return null;
}

変更後

if(isChanged && event.type == 'app.record.detail.show'){
  /*更新*/
}else{
  return event;
}

 

location.reload()はCtrl + Rや、画面の再読み込みなので、ちらつきは免れないかもしれません。

常に最新の情報を表示したいのであればこの方法が今私の思いつく範囲でした。

以下まとめてみました。

kintone.events.on(['app.record.detail.show','app.record.edit.submit'],

    function (event) {

        var record = event['record'];

        console.log("at 顧客管理 edit event=", event)

        var customerRecordNo2 = record["レコード番号"].value;

        // recordレコード番号

        var body1 = {

            "app": kintone.app.getRelatedRecordsTargetAppId("incomingCallInfo1"),

            "fields": ["customerRecordNo1", "stateOfIncomingCall1", "dateOfIncomingCall1", "nextDateOfCall1", "numberOfInCharges1"],

            'query': 'customerRecordNo1 = ' + customerRecordNo2 +

                ' and stateOfIncomingCall1 not in ("成約", "失注", "入電不可") order by dateOfIncomingCall1 asc',

            "size": 500

        }

        // console.log(body1)

        try {

            return kintone.api(kintone.api.url('/k/v1/records', true), 'GET', body1)

                .then(resp1 => {

                    // success

                    // console.log("at 顧客管理 更新前 resp1=", resp1);

                    var lastIncomingCall2Value = resp1.records.reduce(function (accVals, curVal) {

                        return {

                            dateOfIncomingCall1: curVal.dateOfIncomingCall1.value &&

                                (curVal.dateOfIncomingCall1.value.length > 0) &&

                                (accVals.dateOfIncomingCall1 < curVal.dateOfIncomingCall1.value) ? curVal.dateOfIncomingCall1.value : accVals.dateOfIncomingCall1,

                            nextDateOfCall1: curVal.nextDateOfCall1.value &&

                                (curVal.nextDateOfCall1.value.length > 0) &&

                                (accVals.nextDateOfCall1 > curVal.nextDateOfCall1.value) ? curVal.nextDateOfCall1.value : accVals.nextDateOfCall1,

                            numberOfInCharges1: accVals.numberOfInCharges1 + Number(curVal.numberOfInCharges1.value)

                        };

                    }, { dateOfIncomingCall1: "0000/01/01", nextDateOfCall1: "9999/12/31", numberOfInCharges1: 0 })

                    // console.log(lastIncomingCall2Value)

                    if (lastIncomingCall2Value.dateOfIncomingCall1 === "0000/01/01") {

                        lastIncomingCall2Value.dateOfIncomingCall1 = "";

                    }

                    if (lastIncomingCall2Value.nextDateOfCall1 === "9999/12/31") {

                        lastIncomingCall2Value.nextDateOfCall1 = "";

                    }

                    var isChanged = (record.dateOfIncomingCall1.value != lastIncomingCall2Value.dateOfIncomingCall1) ||

                        (record.nextDateOfCall1.value != lastIncomingCall2Value.nextDateOfCall1) ||

                        (record.numberOfInCharges1.value != lastIncomingCall2Value.numberOfInCharges1);

                    record.dateOfIncomingCall1.value = lastIncomingCall2Value.dateOfIncomingCall1;

                    record.nextDateOfCall1.value = lastIncomingCall2Value.nextDateOfCall1;

                    record.numberOfInCharges1.value = lastIncomingCall2Value.numberOfInCharges1;

                    if (isChanged && event.type == 'app.record.detail.show') {

                        var body2 = {

                            'app': kintone.app.getId(),

                            'id': record["$id"].value,

                            'record': (Object.entries(record)

                                .map(function (key1Val) {

                                    return (

                                        key1Val[1]["type"] === "CREATED_TIME" ||

                                            key1Val[1]["type"] === "CREATOR" ||

                                            key1Val[1]["type"] === "MODIFIER" ||

                                            key1Val[1]["type"] === "RECORD_NUMBER" ||

                                            key1Val[1]["type"] === "STATUS" ||

                                            key1Val[1]["type"] === "STATUS_ASSIGNEE" ||

                                            key1Val[1]["type"] === "UPDATED_TIME" ||

                                            key1Val[1]["type"][0] === "_" ? null :

                                            key1Val[1]["type"] === "SUBTABLE" ? ( // "(テーブルのフィールドコード)": {value: 値}

                                                [

                                                    key1Val[0],

                                                    {

                                                        value: key1Val[1].value.map(function (rec2) {

                                                            return (Object.entries(rec2).map(function (key3Val3) {

                                                                return ([key3Val3[0], { value: key3Val3[1]["value"] }]);

                                                            })

                                                                .reduce(function (h3, kv3) {

                                                                    h3[kv3[0]] = kv3[1];

                                                                    return h3;

                                                                }, {})

                                                            )

                                                                ;

                                                        })

                                                    }

                                                ]

                                            ) : [key1Val[0], { value: key1Val[1]["value"] }]

                                    );

                                })

                                .filter(function (key1Val) { return key1Val; })

                                .reduce(function (h2, kv2) {

                                    h2[kv2[0]] = kv2[1];

                                    return h2;

                                }, {})

                            ),

                            'revision': { type: "__REVISION__", value: record['$revision'].value + 1 }

                        };

                        console.log("at 顧客管理 非同期更新 before put body2=", body2);

                        return kintone.api(kintone.api.url('/k/v1/record', true), 'PUT', body2);

                        

                    } else {

                        return event;

                    }

                }).then(resp2 => {

                    if (resp2) { // success

                        console.log("at 顧客管理 非同期更新後 responce=", resp2, event)

                        setTimeout(() => {

                            location.reload(); // 無限ループ抑止の為、更新時のみ遅延実行

                        }, 30)

                    } else {

                        console.log("at 顧客管理 非同期更新セズ")

                    }

                    return event;

                }).catch(error1 => {

                    // error

                    console.error(error1);

                    event.error = JSON.stringify(error1)

                    return event;

                });

        } catch (error2) {

            console.error(error2);

            event.error = JSON.stringify(error2)

            return event;

        }

    });
岡崎 光輝により編集されました
1
Avatar
小瀬

重ね重ね、応答ありがとうございました。

例示していただいたコードも参考にして変更しましたコードは、その後 テストを重ね、問題は解消できました。

 

ただ、悔しいのは、angular等のユーザインタフェース系のライブラリであれば、一部のフィールドの内容を更新した時に、notifyイベントの様なイベントを発火し バブリングして、画面の一部のみを再描画させる手段が在って、画面のチラツキを避けることが出来るのに、kintoneでは出来なかったことです。

>location.reload()はCtrl + Rや、画面の再読み込みなので、ちらつきは免れないかもしれません。

 

なにわともあれ、本件closeということにします。

1
Avatar
岡崎 光輝

私も勉強になりました。
ありがとうございました。

0
サインインしてコメントを残してください。