新規投稿
フォローする

別のアプリの値を取得したい

・料金テーブルアプリ

 フィールド ~ クラス、単価、個数、料金、特単価、特個数、特料金

 (通常~ 単価、個数、料金  特殊~ 特単価、特個数、特料金)

・請求アプリ

 フィールド ~ クラス、チェックボックス(通常・特殊)、単価、個数、請求額

請求アプリのクラス・チェックボックスの値から、料金テーブルのそれぞれ単価(特単価)と、通常の際は個数 > x の場合は料金、特殊の際は個数 > x の場合は特料金を表引きし請求額に値をセットしたい。

初心者なので、単にルックアップでやろうとしましたが、複数条件による表引きができません。プラグインではお金がかかるのでJSを自作するしかありません。

(function () {
  "use strict";
  kintone.events.on(['app.record.create.submit','app.record.edit.submit'], function(event){
    return kintone.api('/k/v1/record','PUT', {
      app: アプリNo, //料金テーブル
      updateKey: {field: "クラス",value: event.record.クラス.value

  },
      record: {単価: {value: field: "単価"
       }
      }
    }).then(function(){
        return event;
    });
  });
})();

こんな感じをカスタマイズすればできそうですが、、、

JSを勉強したいのでご教示いただければ幸いです。

0

27件のコメント

Avatar
mls-hashimoto

JavaScriptを使用しないのであれば、ルックアップから「単価」「特単価」の両方をフィールドにコピーするようにし、請求アプリの「請求額」フィールドにkintone標準機能の計算式適用(IF文を使い、チェックボックスの値に応じて単価か特単価)で良いと思います。

JavaScriptを使う場合、以下のようなイメージになると思います(クラスは一意の値である前提です。クラスの一致する複数のレコードから選択していく場合は、やはりkintone標準機能の計算式を使用した方が手軽だと存じます)。

(function() {
  'use strict';

  var classField = 'クラス';// 請求アプリの「クラス」フィールドコード
  var checkboxField = 'チェックボックス';// 請求アプリの「チェックボックス」フィールドコード
  var numberField = '個数';// 請求アプリの「個数」フィールドコード
  var priceAppId = ;// 料金テーブルアプリのアプリID
  var x = ;// 個数 > x の値

  var events = [];

  [classField, checkboxField, numberField].forEach(function(field) {
    events.push('app.record.create.change.' + field, 'app.record.edit.change.' + field);
  });

  kintone.events.on(events, function(event) {
    var record = event.record;

    if (!record[classField].value || !record[checkboxField].value.length) return event;

    var getRecords = {
      app: priceAppId,
      query: 'クラス = \"' + record[classField].value + '\"'
    };

  kintone.api(kintone.api.url('/k/v1/records', true), 'GET', getRecords, function(resp) {
    var recordData = kintone.app.record.get(), rec = recordData.record;
      var respRecord = resp.records[0];
      var unitPrice = rec[checkboxField].value.includes('通常') ? respRecord['料金'].value: respRecord['特料金'].value;

    if (rec[numberField].value > x) rec['請求額'].value = unitPrice;

      kintone.app.record.set(recordData);
    }, function(error) {
      alert(JSON.stringify(error));
    });

    return event;
  });
})();
mls-hashimotoにより編集されました
0
Avatar
FURUNO.T

mls-hashimoto さま

こちらでもお世話になります。

早速、ルックアップ+IF で試してみます。

ご教示ありがとうございます。

1
Avatar
FURUNO.T

mls-hashimoto さま

JSの勉強をしたいので、上記スクリプトを手直しし実行したところ、料金テーブルからの単価・特約単価は正しく表引出来てますが、ここでスクリプトが停止します。

TypeError: Cannot read properties of undefined (reading '条件') 

どうやらこれがエラーの原因のようですが対処の仕方が解りません。

(チェックボックスからラジオボタンに変更しています)

ご教示下されば幸いです。宜しくお願い致します。

 

0
Avatar
mls-hashimoto

FURUNO.T さま

(実のところ今朝スクリプトのミスに気付いて変更しました。32行目のkintone.app.record.getの後に()が必要です。申し訳ありません)

使用していた「includes」はチェックボックス(配列)に含まれるかの判定に使用するため、ラジオボタンであればこちらに変更して下さい。

      var unitPrice = rec[checkboxField].value == '通常' ? respRecord['単価'].value: respRecord['特約単価'].value;

24行目も

    if (!record[classField].value) return event;

だけで問題ありません(ラジオボタンであれば変更しなくても問題ありません)。

また気になったことが2点あります。
①イベントにsubmitが追加されているようですが、submitイベントでAPIを使ったスクリプトを動作させるのであればPromiseまたはkintone.Promiseを使用する必要があります(スクリプトの処理完了より先にkintoneの保存完了が起きるためです。またchangeイベントではkintone.Promiseを使えず、submitイベントではkintone.app.record.get()等が使えないのでエラーになります)。
https://developer.cybozu.io/hc/ja/articles/360023047852 
https://developer.cybozu.io/hc/ja/articles/900004201403-kintone-Promise 

②8行目のxに「日数」が代入されていますが、日数というフィールドの値のことでしょうか(x = 5 の場合 個数 > 5というイメージでいました)。
その場合であれば、36行目のxを

rec[x].value

と変更する等で対応して下さい。

mls-hashimotoにより編集されました
0
Avatar
FURUNO.T

mls-hashimoto さま

素早いご対応、ありがとうございます。

確かに、submitイベントは不要で、フィールドイベントだけでした。

クラスはルックアップからのコピーフィールドです。ラジオボタンは、通常・特約の二択です。

このクラスとラジオボタンの値から請求アプリの単価は、通常選択時は料金テーブルの単価を、特約選択時は特約単価の値を表引きしたいです。更に請求アプリの日数が料金テーブルの日数を超えると通常選択時は料金テーブルのMというフィールド値を、特約選択時は特約Mというフィールド値をそれぞれ請求アプリの請求額に表引きさせたいです。

上記mls-hashimoto さまからのご指摘いただき手直しし実行したエラー結果です。ご教示宜しくお願い致します。

 

0
Avatar
mls-hashimoto

FURUNO.T さま
先のコメントの1行目にあるように27行目のkintone.app.record.getの後に()が必要です。当初の記載ミスです。申し訳ありません。

0
Avatar
FURUNO.T

mls-hashimoto さま

承知いたしました。() を付け足して、フィールドイベントを

  var events = [
               'app.record.create.change.クラス',
               'app.record.create.change.条件', //デフォルトは通常
               'app.record.create.change.日数',
               'app.record.edit.change.クラス',
               'app.record.edit.change.条件', //デフォルトは通常
               'app.record.edit.change.日数'
               ];

に変更し実行するとエラーは出ませんが、単価及び請求額に表引きされません。

クラスがルックアップからのコピー先というのが原因でしょうか?

宜しくお願い致します。

0
Avatar
FURUNO.T

また、JSEditでは、38行目このエラーです。

0
Avatar
mls-hashimoto

FURUNO.T さま

こちらも見落としていました。6行目で宣言しているnumberFieldと8行目で宣言しているxが最終的に同じフィールドを参照しているようです。個数 > x の場合に動くように作ったので、31行目のif文の括弧を削除すれば動くはずです。

JSEdit上のものはエラーというよりプログラミングの書き方の推奨のようなものです。あまり気にしなくて問題ありません(「rec['M']」と「rec.M」で同じ意味であるものの、後者の記法を推奨しているようです。詳細はブラケット記法、ドット記法等でお調べいただくと出てきますが、慣れてからで問題ありません)。

イベントは12~14行目で全く同じものを宣言しているので、追記していただかなくても問題ありません。

mls-hashimotoにより編集されました
0
Avatar
FURUNO.T

mls-hashimoto さま

イベントの書き方にも色々な方法があるのですね。初心者故勉強します。

上の宣言は、var events = []; あるいは削除で良いのでしょうか?

また、IFの()を外した ↓ ところ × になりますが良いのでしょうか?

ラジオボタンの値が特約の場合の請求額への表引きがないように見えますが・・・

ご教示宜しくお願い致します。

0
Avatar
mls-hashimoto

FURUNO.T さま

言葉足らずでした。38行目は

rec['M'].value = unitPrice;

で問題ありません。

特約の場合の単価ですが、

var unitPrice = rec[checkboxField].value == '通常' ? respRecord['単価'].value: respRecord['特約単価'].value;

の部分で変数「unitPrice」に「チェックボックスが通常なら単価、そうでないなら特約単価」を代入するようにし(三項演算子等でお調べいただければ出て来るかと思います)、そのunitPriceをrecord['M'].valueに代入しています。

イベントについては

var events = [];

で問題ありません。
38行目のif文を削除したため、イベント宣言の下の12~14行目からnumberFieldは削除して

  [classField, checkboxField].forEach(function(field) {
    events.push('app.record.create.change.' + field, 'app.record.edit.change.' + field);
  });

で問題ないですね。

mls-hashimotoにより編集されました
0
Avatar
FURUNO.T

mls-hashimoto さま

ご教示の通り書き換えて実行したところです。31行目で赤×ですが、エラーなく保存はできます。が、単価等表引きしてくれません。引き続き宜しくお願い致します。

0
Avatar
mls-hashimoto

FURUNO.T さま

レコードの日数が料金アプリの日数を超えた場合、単価をMまたは特約Mにしたい旨を見落としておりました。申し訳ありません。30行目に

      if (rec['日数'].value > respRecord['日数'].value) unitPrice = rec[checkboxField].value == '通常' ? respRecord['M'].value: respRecord['特約M'].value;

こちらを追加して下さい。
また、31行目の「rec['M'].value = unitPrice」は、「現在開いているレコードのフィールド『M』に料金テーブルから取得した単価を代入する」という記述になっているので、恐らくは「rec['請求額'].value = unitPrice」が正しいのではないかと思われます。

mls-hashimotoにより編集されました
0
Avatar
FURUNO.T

mls-hashimoto さま

ありがとうございます。上記JSとrec['請求額'].value = unitPrice に手直しし正常に動作いたしました!

実は請求appの日数は、開始日・終了日から日数を計算しこの日数と料金TBLの日数と比較して、更に通常か特約かで請求app>料金TBLの場合はM(特約M)料金を、請求app<=料金TBLの場合は請求app×単価(特単価)をそれぞれ請求額に表引きという風に下記のようにアレンジしてみましたが、うまく行きません。

また、予定日数を標準搭載の式ではなく、学習のためと手入力を可能としたいのでJSでやろうと調べると、初心者故難解です。

この二つをご教示いただければ幸いです。

      var recordData = kintone.app.record.get(), rec = recordData.record;
      var respRecord = resp.records[0];
      var unitPrice = rec[checkboxField].value == '通常' ? respRecord['単価'].value: respRecord['特約単価'].value;
      var mPrice = 0;
      var tPrice = 0;
      if (rec['日数'].value > respRecord['日数'].value) mPrice = rec[checkboxField].value == '通常' ? respRecord['M'].value: respRecord['特約M'].value;
      if (rec['日数'].value <= respRecord['日数'].value) tPrice = mPrice * respRecord['日数'].value;
      rec['単価'].value = unitPrice;
      rec['利用料金'].value = mPrice;
      rec['利用料金'].value = tPrice;
0
Avatar
mls-hashimoto

FURUNO.T さま
おそらく以下のようなイメージでしょうか。

      var recordData = kintone.app.record.get(), rec = recordData.record;
      var respRecord = resp.records[0];
      var unitPrice = rec[checkboxField].value == '通常' ? respRecord['単価'].value: respRecord['特約単価'].value;

      rec['単価'].value = unitPrice;

      if (rec['日数'].value > respRecord['日数'].value) {
        rec['利用料金'].value = rec[checkboxField].value == '通常' ? respRecord['M'].value: respRecord['特約M'].value;
      } else {
        rec['利用料金'].value = unitPrice * respRecord['日数'].value;
      }

また日数を求める計算式はDay.js等のライブラリを使用すると簡単に求められます。

https://unpkg.com/dayjs 
https://unpkg.com/dayjs@1.7.7/locale/ja.js 

上2つを「JavaScript / CSSでカスタマイズ」の「URL指定で追加」で追加し、

(function() {
  'use strict';

  kintone.events.on([
    'app.record.create.change.開始日', 'app.record.edit.change.開始日',
    'app.record.create.change.終了日', 'app.record.edit.change.終了日',
  ], function(event) {
    var record = event.record;

    if (!record['開始日'].value || !record['終了日'].value) {
      record['日数'].value = '';
    } else {
      record['日数'].value = dayjs(record['終了日'].value).diff(record['開始日'].value, 'day');
    }

    return event;
  });
})();

を追加すれば日数を求められます…が、個人的にはおすすめしません(今後更にカスタマイズをしていく時に弊害になる可能性があります。特にREST APIでレコードの操作をしていくとなると、何かと不便になります。kintoneの標準機能計算で簡単に実装できることはそちらで済ませた方が個人的には良いと思います)。

0
Avatar
FURUNO.T

mls-hashimoto さま

いつもありがとうございます。

日付計算は入力の手間を考えると、開始日 + 請求appの(日数は紛らわしいので)予定日数で終了日を求めたいと思い、ご教示くださったJSを手直しし

https://unpkg.com/dayjs 
https://unpkg.com/dayjs@1.7.7/locale/ja.js 

を組み込みましたが、以下でエラーでした(基本がなってない?)。

また、checkboxFieldが特約の際は、請求appの日数と料金TBLの特約日数を比較、大きければ料金TBLの特約Mを利用料金(請求額)に表引きしたいので色々と勉強しましたが、ギブでした。

 kintone.api(kintone.api.url('/k/v1/records', true), 'GET', getRecords, function(resp) {
      var recordData = kintone.app.record.get(), rec = recordData.record;
      var respRecord = resp.records[0];
      var unitPrice = rec[checkboxField].value == '通常' ? respRecord['単価'].value: respRecord['特約単価'].value;

      if (!record['開始日'].value || !record['予定日数'].value) {
          record['終了日'].value = '';
      } else {
          record['終了日'].value = plus({month: numberField});           ←エラー
      }
   record['終了時刻'].value = plus({hours: 24}); //終了時刻=開始時刻      ←エラー
   rec['単価'].value = unitPrice;

      if (rec['予定日数'].value > respRecord['日数'].value) {
        rec['利用料金'].value = rec[checkboxField].value == '通常' ? respRecord['M'].value: respRecord['特約M'].value;
      } else {
        rec['利用料金'].value = unitPrice * rec['予定日数'].value;
      }

VBA風だと IF checkboxField  > '予定日数' and checkboxField ='特約' then  '特約M' ?

また、JSについていったい何から勉強すればよいか、初心者故チュートリアルにある「はじめよう JavaScript」を勉強しましたが、Kintoneは文法・作法が違うとか、APIとか色々ありますがどんな時にどれでコーティングしたら良いか、何を組み込みだら良いか等々、サンプルスクリプトが豊富で参考になる良いサイトをご教授いただければ幸いです(自分のレベルはVBAが中級、HTML・CSSは10数年ほど前に少しかじった程度です)。

宜しくお願い致します。

0
Avatar
mls-hashimoto

FURUNO.T さま

以下のような形でいかがでしょうか(変数を多用していたため、直観的になるよう書き換えました)

      // 終了日を求める計算
      if (!rec['開始日'].value) {
        rec['終了日'].value = '';
      } else {
        rec['終了日'].value = dayjs(rec['開始日'].value).add(rec['日数'].value, 'day').format('YYYY-MM-DD');
        /*
         * 日を加算ではなく月を加算であれば'day'を'month'に
         * 年の加算であれば'day'を'year'に
         * 減算であれば.addを.subtractに
         */
      }

      // 予定日数に応じて利用料金を決定
      if (rec['予定日数'].value > respRecord['日数'].value) {
        if (rec['条件'].value == '通常') {
          rec['利用料金'].value = respRecord['M'].value;
        } else if (rec['条件'].value == '特約') {
          rec['利用料金'].value = respRecord['特約M'].value;
        }
      } else {
        rec['利用料金'].value = unitPrice * rec['予定日数'].value;
      }

      // 終了時刻を求める計算
      rec['終了時刻'].value = rec['開始時刻'].value;
      /*
       * 終了時刻を開始時刻の数時間後に設定する場合
       *
        if (!rec['開始時刻'].value) {
          rec['終了時刻'].value = '';
        } else {
          var splitTime rec['開始時刻'].value.split(':');

          rec['終了時刻'].value = dayjs().hour(splitTime[0]).minute(splitTime[1]).add(*足す時間の数字*, 'hour').format('HH:mm');
        }
       *
       */

 

JavaScriptの勉強についてですが、あまり参考になるか分かりませんが私はほとんどこのコミュニティで習得しました。
(自分の勉強よりとにかく機能の実装が必要だったので)実装したいことを検索すると大抵誰かが答えを記述しているので、それをコピペして見様見真似しながら今に至っています(理解しないまま開発して、一通り実装した後にようやく理解できるようになっていました)。
個人的に一般的なJavaScriptの解説サイトはkintoneの開発をする上では不要な(使わない)情報が多いと感じているので、kintoneの開発のためのJavaScript習得であればこの場所かチュートリアルページがおすすめではあります。その上で詰まったところをその都度検索する等が一番近道ではないかと考えております。

0
Avatar
FURUNO.T

mls-hashimoto さま

いつもの神対応に感謝申し上げます。

早速動作確認いたしましたところ、一見正常に見えますが

①条件=通常も特約も、予定日数が 3~9 までが M 料金になり、単価 × 予定日数 になりません。この数以外は②以外で正常です。

②条件=特約のとき ① に加え、予定日数 > 日数 が一日少ない数で表引きします(本来は23で特約Mのところ22で表引きしてきます。

JS勉強の件、確かにkintoneのみでの構築ですので、おっしゃる通りですね。

>自分の勉強よりとにかく機能の実装が必要だったので・・・

自分もそうです。業務改善に向けてより良いインターフェース、エラー処理等充実させたく今後とも宜しくお願い致します。

0
Avatar
FURUNO.T

追伸です。

以下の部分がエラーと出てます。

https://unpkg.com/dayjs 
https://unpkg.com/dayjs@1.7.7/locale/ja.js 

を組み込んでますが、関係ありますか?

開始→出発に変更、終了→帰着に変更(時刻も)しております。

0
Avatar
FURUNO.T

 

mls-hashimoto さま

お世話になってます。色々調べたらライブラリがおかしいかもと思い、

https://unpkg.com/dayjs 
https://unpkg.com/dayjs@1.7.7/locale/ja.js 

の代わりに

https://cdn.jsdelivr.net/npm/dayjs@1.10.8/dayjs.min.js

こちらを組み込んだらエラーは出ませんが、計算がおかしいので引き続き検証してみます。

0
Avatar
mls-hashimoto

FURUNO.T さま

画面に出すかコンソールに出すかで解決するかもしれません。一度こちらを試してみてください。

      // 予定日数に応じて利用料金を決定
      alert('予定日数は' + rec['予定日数'].value + 'で、料金テーブルから取得したレコードの日数は' + respRecord['日数'].value + 'です');

      if (rec['予定日数'].value > respRecord['日数'].value) {
        if (rec['条件'].value == '通常') {
          rec['利用料金'].value = respRecord['M'].value;
        } else if (rec['条件'].value == '特約') {
          rec['利用料金'].value = respRecord['特約M'].value;
        }
      } else {
        rec['利用料金'].value = unitPrice * rec['予定日数'].value;
      }
0
Avatar
FURUNO.T

mls-hashimoto さま

お世話になってます。

上記アラートに

'で、特約日数は、'  + respRecord['特約日数'].value

と組み込んで実行したところ、

前述質問の① 症状はそのままで(3~9の際の予定日数、料金テーブルの日数とも正常に引いてます)、

②特約時は、料金テーブルの特約日数ではなく日数を参照しています。

また、

https://cdn.jsdelivr.net/npm/dayjs@1.10.8/dayjs.min.js

こちらのライブラリと差し替えて、出発日を入力すると、

”カスタマイズ用のJavaScriptの実行時にエラーが発生しました”

調べてますが、ギブします。

宜しくお願い致します。

0
Avatar
mls-hashimoto

FURUNO.T さま

アラートには何が表示されていますか?最初の書き込み時から仕様が変わっているようなので、私の現在の認識と相違ないかの確認のつもりでアラートを組み込みました。一度本当に実現したいことを整理したいと考えています

「カスタマイズ用のJavaScriptの実行時に…」は、JavaScriptの処理自体は成功しているものの、kintoneのフィールドに代入できない値を入れようとした時に出ることが多いエラーという認識です(例として日付フィールドに文字を代入したり、サブテーブルの存在しない行に代入したり等)

代入しようとしている値をconsole.log等で確認することで問題が分かるかと存じます。

 

また、エラーの確認方法ですが、コンソールサイドバー(FURUNO.T さまが添付している画像だと右上にある矢印のマーク)から見るとエラーの原因や場所がより分かりやすくなるかと存じます。

mls-hashimotoにより編集されました
0
Avatar
FURUNO.T

mls-hashimoto さま

お世話になってます。(どうすればコンソールを日本語に出来るのでしょうか?(当方Chromeです))

このようにコンソールにはエラーがありません。このまま入力を続け保存もできます。

また、おっしゃるとおり実現したいことのおさらいを致します(因みにこのスクリプトでもコンソールにはエラーがありません)。

①請求appの出発日と予定日数から帰着日を求めます。時刻はイコールです。

②請求appのクラス=料金TELのクラス(ユニークキー)が同じの場合、

  a. 請求appの条件が通常の場合は料金TBLの単価を、 特約の場合は料金TBLの特約単価を請求appの単価に表引き

  b. 請求appの利用料金は、

    ・請求appの条件が通常 and 予定日数 >料金TBLの日数が

     falseの場合、 単価 × 予定日数 // aで求めた単価

     trueの場合、料金TBLのM

    ・請求appの条件が特約 and 予定日数 >料金TBLの日数が   

     falseの場合、 単価 × 予定日数 // aで求めた単価

     trueの場合、料金TBLの特約M

    をそれぞれ請求appの利用料金にセット

以上になります。解りにくい場合は再度ご連絡下されば幸いです。

宜しくお願い致します。

0
Avatar
juridon

こんばんは!
すごく横槍で申し訳ないのですが、

Day.js がうまく動かないようですが、Day.jsについて調べたり検証をするよりは
Cybozu CDN で準備されている Luxon.js を使うのをおすすめしたいです。

Luxon を使って kintone の日付や日時フィールドのフォーマットをカスタマイズする



また、kintoneカスタマイズのJavaScriptを勉強したいということでしたら

チュートリアルを一通りやってみたり
https://developer.cybozu.io/hc/ja/articles/360024370392

kintone dev campに参加されてみたり
https://page.cybozu.co.jp/-/kintone-devcamp-stepup

するのをおすすめしたいです^^


それと、
Chromeのコンソールの日本語化は、実はグーグル検索すればやり方がヒットしますので
ぜひ検索してみてください^^

chrome コンソール 日本語化 で検索

 

やりたいことが整理されたら、プログラミングを少しずつ実行して動作確認しての繰り返しで組み立てていくと上達すると思いますので、ファイトです💪

横槍失礼しました👀💦応援しております~!

1
Avatar
FURUNO.T

juridon さま

レス遅くなりすみません。

日付計算は非常にめんどくさいのですね。どのやり方が最適なのか、Luxon が最適なのかすら理解できてない超初心者です。Luxon のサンプルコードを漁って検証してみます。

コンソールの日本語化、簡単にできました。kintone dev campは、平日午後の2時間くらいとのことでしたので、参加したのはやまやまですが、勤務時間帯なので難しいかもです。

色々とありがとうございます。

1
Avatar
FURUNO.T

juridon さま

Luxon の件、以下のように一行ですっきり収まるので、Luxon は良いですね。

日付計算はこれでOKです。次は表引き計算が未だ解決できず困ってます。

    var yoDay = record['予定日数'].value;

  if (event.record['予定日数'].value) {
       record['帰着日'].value = luxon.DateTime.fromISO(strDate).plus({days: yoDay}).toFormat('yyyy-MM-dd')};

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