複数アプリからまとめの表を作成したい

背景・実現したいこと

 受注データを元に作業日報、材料使用日報、外注利用日報データから利益集計表を作成したい。

このような表を作成するのにアプリの作り方しだいでJavaScriptを使わなくても作成できるのかも合わせて確認したい。

エラー情報 (開発者ツールのコンソール)

  一度受注データで表を作成後、alert文で表示をSTOPして作業日報、材料使用日報、外注利用日報データを表に反映。
その後、もう一度alert文で表示をSTOPし、作った表を利用して原価計、利益を算出し表を完成するPG。
この途中の「alert」のSTOP文を入れると正しい表が得られるが、「alert」でSTOPする箇所をコメントアウトすると表示に抜けがでて正しい表にならない。

[受注データ]

[作業日報データ]

[材料使用日報データ]

[外注利用日報データ]

受注データを元に2021年度として作業日報データ、材料使用日報データ、外注利用日報データより集計。

(alertがあり正しい表)

(alertがない。間違っている表)

(F5で更新)

利用したソースコード

 (function() {
  ‘use strict’;

  kintone.events.on(‘app.record.detail.show’, function(event) {

    var record = event.record;
    // 「利益集計表」を表示する表を作成
    var tableHtml = ‘<thead><tr>’ +
        ‘<th>’ + ‘受注番号’ + ‘</th>’ +
        ‘<th>’ + ‘受注名称’ + ‘</th>’ +
        ‘<th>’ + ‘受注額’ + ‘</th>’ +
        ‘<th>’ + ‘作業費’ + ‘</th>’ +
        ‘<th>’ + ‘材料費’ + ‘</th>’ +
        ‘<th>’ + ‘外注費’ + ‘</th>’ +
        ‘<th>’ + ‘原価計’ + ‘</th>’ +
        ‘<th>’ + ‘利益’ + ‘</th>’ +
        ‘</tr>’ +
        ‘</thead>’ +
        ‘</tbody>’;

    // スペースフィールドに表を作成
    var tableEl = document.createElement(‘table’);
    tableEl.id = ‘table_test’;
    tableEl.border = ‘1’;
    tableEl.style.textAlign = ‘center’;
    tableEl.style.padding = ‘10px’;
    tableEl.insertAdjacentHTML(‘afterbegin’, tableHtml);
    kintone.app.record.getSpaceElement(‘tablespace’).appendChild(tableEl);

    var makeday = record.作成日.value;
    var mDate = new Date(makeday);
    var mYear = mDate.getFullYear();
    var mMonth = mDate.getMonth();
    // 0起点のため
    if (mMonth < 3) {
      mYear -= 1;
    }
    // 「受注データID」
    var params_jcyu = {‘app’: 40, ‘query’: ‘レコード番号 > 0’};
    // 「作業日報データID」
    var params_npou = {‘app’: 41, ‘query’: ‘レコード番号 > 0’};
    // 「材料費使用データID」
    var params_zair = {‘app’: 42, ‘query’: ‘レコード番号 > 0’};
    // 「外注費データID」
    var params_gaic = {‘app’: 43, ‘query’: ‘レコード番号 > 0’};
    // 「外注費データID」
    var params_matome = {‘app’: kintone.app.getId(),‘query’: kintone.app.getQuery()};

    // 受注データ読み込み
    getSgData(mYear, params_jcyu, 0);
    window.alert(‘少し待って下さい。(’ + mYear + ‘)’);  // ←**このalertを削除したい**
    // 作業日報データ読み込み
    getSgData(mYear, params_npou, 3);
    // 材料費データ読み込み
    getSgData(mYear, params_zair, 4);
    // 外注費データ読み込み
    getSgData(mYear, params_gaic, 5);
    window.alert(‘少しまって下さい。’);  // ←**このalertを削除したい**
    // まとめ
    getSgData(mYear, params_matome, 0);
  });

  // データ読み込み
  function getSgData(mYear, params, iSetNo) {
    kintone.api(kintone.api.url(‘/k/v1/records’, true), ‘GET’, params).then(function(resp) {
      // エラーを表示
      if (resp.records.length === 0) {
        if (params.app == 40) {
          window.alert(‘受注データのレコードがないため、データを表示できません。’);
        }
        return;
      }
      if (params.app == 40) {
        // 取得処理
        myDisplayCustomizedViewJcyu(resp.records, mYear);
      } else if (params.app == 41 || params.app == 42 || params.app == 43) {
        // 作業日報、材料費、外注費データの取得処理
        myDisplayCustomizedView(resp.records, mYear, iSetNo);
      } else {
        // まとめ
        myDisplayCustomizedViewMatome();
      }
      return;
    }).catch(function(error) {
      // エラー表示をする
      window.alert(‘エラーが起こりました。エラーメッセージ:’ + error.message);
      return;
    });
    return;
  }

  // 受注データ表示
  function myDisplayCustomizedViewJcyu(records, mYear) {
    // 取得した「受注データ」のテーブルデータを利益集計表に格納
    var tableRef = document.getElementById(‘table_test’);
    for (var i = 0, l = records.length; i < l; i++) {
      var row = records[i];
      if (row[‘年度’].value == mYear) {
        var tableRow = tableRef.insertRow();
        var cell1 = tableRow.insertCell();
        var cell2 = tableRow.insertCell();
        var cell3 = tableRow.insertCell();
        var cell4 = tableRow.insertCell();
        var cell5 = tableRow.insertCell();
        var cell6 = tableRow.insertCell();
        var cell7 = tableRow.insertCell();
        var cell8 = tableRow.insertCell();

        cell1.appendChild(document.createTextNode(row[‘受注番号’].value));
        cell2.appendChild(document.createTextNode(row[‘受注名称’].value));
        // カンマ編集
        cell3.appendChild(document.createTextNode(Number(row[‘受注額’].value).toLocaleString()));
        cell4.appendChild(document.createTextNode(’ ‘));
        cell5.appendChild(document.createTextNode(’ ‘));
        cell6.appendChild(document.createTextNode(’ ‘));
        cell7.appendChild(document.createTextNode(’ ‘));
        cell8.appendChild(document.createTextNode(’ '));
      }
    }
  }
  // データ表示
  function myDisplayCustomizedView(records, mYear, iSetNo) {
    // 利益集計表を取得
    var tableRef = document.getElementById(‘table_test’);
    var ikei = 0;

    for (var i = 1, l = tableRef.rows.length; i < l; i++) {
      var hrow = tableRef.rows[i];
      ikei = 0;

      for (var j = 0, ll = records.length; j < ll; j++) {
        var row = records[j];
        var sday = new Date(row[‘作業日’].value);
        var syear = sday.getFullYear();
        if (sday.getMonth() < 3) {
          syear -= 1;
        }
        if (hrow.cells[0].innerHTML == row[‘受注番号’].value) {
          // 年度が同じ場合
          if (syear == mYear) {
              if (iSetNo == 3) {
                // 作業費
                ikei += row[‘作業時間’].value * row[‘単価’].value;
              } else if (iSetNo == 4) {
                // 材料費
                ikei += Number(row[‘金額’].value);
              } else if (iSetNo == 5) {
                // 外注費
                ikei += Number(row[‘金額’].value);
              }
          }
        }
      }
      if (ikei > 0) {
        // カンマ編集して設定
        hrow.cells[iSetNo].innerHTML = ikei.toLocaleString();
      }
    }
  }
  // まとめ表示
  function myDisplayCustomizedViewMatome() {
    // 利益集計表を取得
    var tableRef = document.getElementById(‘table_test’);
    for (var i = 1, l = tableRef.rows.length; i < l; i++) {
      var hrow = tableRef.rows[i];
      // 受注額
      var work = hrow.cells[2].innerHTML;
      var jcyu = ((work).replace(/’ ‘/g,’‘)).replace(/,/g,’‘);
      // 作業費
      work = hrow.cells[3].innerHTML;
      var sag = ((work).replace(/’ ‘/g,’‘)).replace(/,/g,’‘);
      // 材料費
      work = hrow.cells[4].innerHTML;
      var zai = ((work).replace(/’ ‘/g,’‘)).replace(/,/g,’‘);
      // 外注費
      work = hrow.cells[5].innerHTML;
      var gai = ((work).replace(/’ ‘/g,’‘)).replace(/,/g,’');

      if (sag == ‘’) {
        sag = 0;
      } else {
        sag = Number(sag);
      }
      if (zai == ‘’) {
        zai = 0;
      } else {
        zai = Number(zai);
      }
      if (gai == ‘’) {
        gai = 0;
      } else {
        gai = Number(gai);
      }
      var kei = sag + zai + gai;
      var rieki = jcyu - kei;
      if (kei > 0) {
          // カンマ編集して設定「原価計」に設定
          hrow.cells[6].innerHTML = kei.toLocaleString();
      }
      // カンマ編集して設定「利益」に設定
      hrow.cells[7].innerHTML = rieki.toLocaleString();
    }
  }
})();

細かくはみてないんですが、パット見たところ

getSgData内でkintone.api()を行っており、その完了をまててないからですね。(AlertでうまくいってるのはAlertを出してるうちに待ててるから)

この場合、Promiseを活用することで、kintone.api()の処理を待つことができます。

下記の記事を参考にしてみてください。
特に、IEや特段古いバージョンのブラウザを使ってないのであれば、Async/Awaitでやるのが直感的になるかと思います。

https://developer.cybozu.io/hc/ja/articles/360023047852-kintone%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8BPromise%E3%81%AE%E6%9B%B8%E3%81%8D%E6%96%B9%E3%81%AE%E5%9F%BA%E6%9C%AC

ありがとうございます。

お教え頂いたURLのPromiseの内容を確認してやっているのですが、途中で「入力内容が正しくありません。」のエラーとなりまだ確認できていません。少々難しいですね。(- -;;

上のgetSgData関数部分を展開し、

  return kintone.api(kintone.api.url(‘/k/v1/record’, true), ‘GET’, params_npou);

}).then(function(resp1) {

のように修正したのですが… params_npouの内容がいけないのかな?と思いつつ、悩み中です。努力してみます。

 

学習としては、まずは簡単なPromiseを組んで試すのがいいかもですね。
IEさえ使わないのであればAsync/Awaitが直感的ですよ。(どうしても使えないなら仕方ないですが)

 

  // データ読み込み
  async function getSgData(mYear, params, iSetNo) {
    const resp = await kintone.api(kintone.api.url(‘/k/v1/records’, true), ‘GET’, params);
    // 以下respを利用できる

ご教授本当にありがとうございました。

Async/Await を使わないで下のようにしましたらうまく行きました。今度はAsync/Awaitを使ってやってみたいと思います。m(_ _)m

    // 受注データ読み込み
    return kintone.api(kintone.api.url(‘/k/v1/records’, true), ‘GET’, params_jcyu).then(function(resp) {
      // エラーを表示
      if (resp.records.length === 0) {
        window.alert(‘受注データのレコードがないため、データを表示できません。’);
        return;
      }
      // 取得処理
      myDisplayCustomizedViewJcyu(resp.records, mYear);
      return kintone.api(kintone.api.url(‘/k/v1/records’, true), ‘GET’, params_npou);

    }).then(function(resp1) {
      if (resp1.records.length !== 0) {
        // 作業日報データの取得処理
        myDisplayCustomizedView(resp1.records, mYear, 3);
      }
      return kintone.api(kintone.api.url(‘/k/v1/records’, true), ‘GET’, params_zair);

    }).then(function(resp2) {
      if (resp2.records.length !== 0) {
        // 材料費データの取得処理
        myDisplayCustomizedView(resp2.records, mYear, 4);
      }
      return kintone.api(kintone.api.url(‘/k/v1/records’, true), ‘GET’, params_gaic);

    }).then(function(resp3) {
      if (resp3.records.length !== 0) {
        // 外注費データの取得処理
        myDisplayCustomizedView(resp3.records, mYear, 5);
      }
      return kintone.api(kintone.api.url(‘/k/v1/records’, true), ‘GET’, params_matome);

    }).then(function(resp4) {
      if (resp4.records.length !== 0) {
        // まとめ
        myDisplayCustomizedViewMatome();
      }
      return;
    }).catch(function(error) {
      // エラー表示をする
      window.alert(‘エラーが起こりました。エラーメッセージ:’ + error.message);
      return;
    });