一覧画面からのレコード登録について(100件以上)

【背景・実現したいこと】

①アプリAの一覧画面に、期間を入力するフォーム+ボタンを配置

**②①のボタン押下後、アプリB(毎日の作業時間記録)/アプリC(売上管理)から、**対象期間内のレコード取得

③②で取得した内容から、顧客コードをキーとして、作業時間合計・粗利益合計 を算出

④アプリAに算出した値をレコード登録していく。(顧客コード1つに対し、1レコード)** ※100件以上になります。**

 

【エラー情報】

・データが少ない場合は上手く処理ができた(レコード数件程度)

・データ数が多くなった場合、ボタンを押すとすぐに元の一覧画面に戻ってしまう。** (レコード登録は1件もされず。)**

・デバックしてみると上手くレコードが登録された。(100件以上の場合でも)

※非同期処理の書き方がおかしいのだと思いますが、自分ではどこを書き換えればいいかが分からず、ご教示いただけますと幸いです。

※大量データを処理するのが初めてで、どこまでkintoneでできるかがまだ分かっていない部分もあります。

※④の作業以降にアプリDやアプリEにレコード転記をしたいと思っているのですが、これ以上処理を続けることは難しいでしょうか?合わせてご確認いただけると助かります。

 

何卒宜しくお願い致します。

(async()=> {
    'use strict';
   //ソースコードは、一部省略しております・・・

    const POST_records = async(id, arr) => {
        //レコード登録数が多くなるので、100件ごとに分けてPOST
        let arrList = [];
        let idx = 0;
        while(idx < arr.length){
            arrList.push(arr.splice(idx,idx+ 100));
        }
        for(let arr of arrList) {
            let body = {
                'app': id,
                'records': arr
            };
           await kintone.api(kintone.api.url('/k/v1/records.json', true), 'POST', body, function(result) {
                console.log(result);
                
            }, function(error) {
                alert(error);
          });
        }
    }

    kintone.events.on('app.record.index.show', function(event) {
        //一覧画面にフォーム設置
        if (document.getElementById('my_form') !== null) {
            return;
        }
        const targetElement = kintone.app.getHeaderMenuSpaceElement();
        const formElement = targetElement.appendChild(createElement('form', 'my_form'));
        formElement.appendChild(createElement('input','inputDate', '','','month','required'));
        formElement.appendChild(createElement('button','analysisButton', '集計開始'));

        analysisButton.onclick = async function() {
            showSpinner(); 
            const TS = parseInt(Date.now())
            const targetMonth = document.getElementById('inputDate').value;
            if(!targetMonth) {
                hideSpinner() 
                return;
            }
            const first_date = new Date(targetMonth.slice(0,4), targetMonth.slice(-2)-1, 1).toLocaleDateString("ja-JP").replace(/\//g, '-');
            const last_date = new Date(targetMonth.slice(0,4),(targetMonth.slice(-2)), 0).toLocaleDateString("ja-JP").replace(/\//g, '-');

            //アプリBから情報取得
            let getDailyReport = new kintone.Promise(async function(resolve, reject) {
                let dailyReportArray = [];
                const params = {
                    app: DAILY_REPORT_APP_ID,
                    filterCond: `${DAILY_REPORT_APP_DATE} >= "${first_date}" and ${DAILY_REPORT_APP_DATE} <= "${last_date}"`,
                    sortConds: ['レコード番号 asc'],
                    fields: ['$id', DAILY_REPORT_APP_TABLE],
                };

                await getRecords(params).then(function(resp) {
                    console.log(resp) 
                    if(resp.records.length === 0) {
                        alert('対象の日報データがありません。');
                        reject();
                    }
                    for(let r of resp.records) {
                        r[DAILY_REPORT_APP_TABLE].value.forEach( v => {
                            dailyReportArray.push({code: v.value[DAILY_REPORT_APP_NUMBER].value , time: v.value[DAILY_REPORT_APP_TIME].value, amount: ''})
                        })
                    }
                }).catch(alert);
                resolve(dailyReportArray) 
            });
    
            //アプリCから情報取得
            let getSeles = new kintone.Promise(async function(resolve, reject) {
                let selesArray = [];
                const params = {
                    app: SALES_APP_ID,
                    filterCond: `${SALES_APP_DATE} >= "${first_date}" and ${SALES_APP_DATE} <= "${last_date}"`,
                    sortConds: ['レコード番号 asc'],
                    fields: ['$id', SALES_APP_NUMBER, SALES_APP_GROSS_MARGIN,],
                };

                await getRecords(params).then(function(resp) {
                    console.log(resp) 
                    if(resp.records.length === 0) {
                        alert('対象の売上データがありません。');
                        reject();
                    }
                    resp.records.forEach( r => {
                        selesArray.push({code: r[SALES_APP_NUMBER].value , time: '', amount: r[SALES_APP_GROSS_MARGIN].value})
                    })
                }).catch(alert);
                resolve(selesArray) 
            });
            
            //それぞれのデータ顧客コードごとに集計
            await kintone.Promise.all([getDailyReport, getSeles]).then(async function(results) {
                console.log(results)
                let createRecords = [];
                let allResults = results[0].concat(results[1])
                let totalArray = allResults.reduce((result, current) => {
                    let element = result.find(value =>  value.code === current.code);
                    if (element) {
                        element.time = Number(element.time) + Number(current.time);
                        element.amount = Number(element.amount) + Number(current.amount);
                    } else {
                        result.push({
                            code: current.code,
                            time: current.time,
                            amount: current.amount,
                        })
                    }
                    return result;
              }, []);
                await totalArray.forEach(v => {
                    createRecords.push({
                        [MY_APP_TS]: {type: 'NUMBER','value': TS},
                        [MY_APP_DATE]: {type: 'DATE','value': `${first_date}`},
                        [MY_APP_NUMBER]: {type: 'NUMBER','value': `${v.code}`},
                        [MY_APP_GROSS_MARGIN]: {type: 'NUMBER','value': `${v.amount}`},
                        [MY_APP_TIME]: {type: 'NUMBER','value': `${v.time}`},
                    })
                })

                await POST_records(kintone.app.getId(), createRecords)
                let checkSaveFlg =  window.confirm('集計が完了しました。')
                if(checkSaveFlg) {
                    hideSpinner() ;
                }
            }).catch(function(error) {
                console.log(error);
            });
        };
    });
})();

 

H.Kさん

こんにちは。

 

以下記事をご覧になっているかと思いますが

async/awaitを使うのであれば、「kintone.Promise」「kintone.Promise.all」は除外して良いと思います。

async/awaitだけで同期処理になりますので。

上から順に行いたい処理を羅列すれば分かりやすくなると思います。

 

then~catchも不要になります。

その代わり、エラー処理をする場合は、以下記事にある通りtry~catchで囲むと良いです。

目指せ!JavaScriptカスタマイズ中級者(2) 〜Promiseのかわりにasync/await編〜

 

また、レコード100件以上処理される場合は

kintone JavaScript Client (@kintone/rest-api-client)

を使われた方がコード数も少なくすっきりすると思います。

koichi様 お世話になります。

前回に引き続き、ご回答いただきありがとうございます。ご指摘いただいた点を参考に、修正してみようと思います。

また、kintone JavaScript Client (@kintone/rest-api-client)についても共有いただきありがとうございます。

これから100件以上の処理も増えてくると思いますので、こちらもぜひ試してみたいと思います。

今後とも宜しくお願いいたします。