サブテーブルを含むレコードの内容を別アプリにコピー

コードを含む長文になります。

タイトルの件ですが、見積書アプリ → 売上管理アプリとサブテーブルを含むレコードの内容をそのまま持って行きたく、下記に示すようなコードを走らせてみたのですが、レコードの内容はコピーされるもののサブテーブルの内容を持って行くことができません。

どうやらサブテーブルの内容は配列にまでは格納されているっぽいので、根本的に何かがおかしいか、足りないと思います。

もし気のついたことがあればご教示いただくことはできますでしょうか?

(function() {
‘use strict’;

//見積書アプリの詳細画面から売上管理アプリへ

var salesDao = {};

kintone.events.on(‘app.record.detail.show’, function(e) {
//「見積書」のレコード情報取得
var record = e.record;
//「売上管理」アプリのアプリの番号
salesDao.APP_ID = 40;

//レコードコピーボタン要素作成
//***** 動的にボタンを生成しているが省略 *****

//ボタンをクリックしたときのイベント
btnCopy.onclick = function() {
//売上管理のデータ登録を実行する
salesDao.insert(record);
};
//ヘッダースペースにボタン要素を付加
kintone.app.record.getHeaderMenuSpaceElement().appendChild(btnCopy);

//売上管理アプリに1行追加。
salesDao.insert = function(recordInf) {
//見積書明細の各項目を配列に取得
var productID = []; //商品コード
var productName = []; //商品名
var unitPrice = []; //単価
var quantity = []; //数量

//サブテーブル(見積書明細)オブジェクトを取得
var tableRecords = record.見積書明細.value;
//サブテーブル(見積書明細)の内容を配列に格納
for (var i = 0; i < tableRecords.length; i++) {
//alert(‘商品コード = "’ + tableRecords[i].value[‘商品コード’].value + ‘"’);
productID[i] = tableRecords[i].value[‘商品コード’].value;
productName[i] = tableRecords[i].value[‘商品名’].value;
unitPrice[i] = tableRecords[i].value[‘単価’].value;
quantity[i] = tableRecords[i].value[‘数量’].value;
alert(unitPrice[i]); //動作確認
}

var params = {
“app”: salesDao.APP_ID,
//見積書の鑑
“record”: {
“見積書番号”: {
“value”: recordInf[‘見積書番号’][‘value’]
},
“取引先コード”: {
“value”: recordInf[‘取引先コード’][‘value’]
},
“取引先名”: {
“value”: recordInf[‘取引先名’][‘value’]
},
“敬称”: {
“value”: recordInf[‘敬称’][‘value’]
}
},
//見積書明細(サブテーブル)
“見積書明細”: {
“value”: [
{
“value”: {
“商品コード”: {
“value”: productID
}
},
“value”: {
“商品名”: {
“value”: productName
}
},
“value”: {
“単価”: {
“value”: unitPrice
}
},
“value”: {
“数量”: {
“value”: quantity
}
}
}
]
}
};

//Kintone REST API リクエスト
kintone.api(kintone.api.url(‘/k/v1/record’, true), ‘POST’, params).then(function(resp) {
// 成功時、対応する「売上管理」画面を開く
if (window.confirm(‘この見積は売上管理に移行しました。該当する売上管理表を開きます。よろしいですか?’)) {
salesDao.showDetail();
}
}, function(resp) {
// 失敗時
if (resp.message !== undefined) {
alert(resp.message);
} else {
alert(‘売上管理の登録に失敗しました(2)。’);
}
});
};

//指定された売上管理アプリの詳細画面を開く
salesDao.showDetail = function() {
alert(‘この機能は現在実装されていません。売上管理には登録されています。’);
};
});

})();

 

サブテーブルのjson 指定に誤りがあります。
イメージとしては、下記のような構造です。

//見積書明細(サブテーブル)
"見積書明細": {
"value": [
{
"value": {
"商品コード": {
"value": productID[0]
}
"商品名": {
"value": productName[0]
}
"単価": {
"value": unitPrice[0]
}
"数量": {
"value": quantity[0]
}
},
},
{
"value": {
"商品コード": {
"value": productID[1]
}
"商品名": {
"value": productName[1]
}
"単価": {
"value": unitPrice[1]
}
"数量": {
"value": quantity[1]
}
},
}
...

]
}

**rex0220**様

ご回答ありがとうございます。提示いただいたコードでproductName[0], unitPrice[0]…など配列に格納された値を配列の添字の決め打ちで明細テーブルを1行だけは追加することはできました。

しかしこの部分の行数は元の見積明細によって複数行になるので、productName[1], unitPrice[1]…より大きく動的?にコードを作成するわけにも行かず、複数行の追加まで行うことができていません。

こちら

https://cybozudev.zendesk.com/hc/ja/articles/204972070-%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E3%83%87%E3%83%BC%E3%82%BF%E3%82%92CSV%E3%81%A7%E3%82%A4%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%88%E3%81%97%E3%81%A6%E3%81%BF%E3%82%88%E3%81%86-

を参照してなんとかトライしていますが、csv形式と違うため試行錯誤の最中ですが上手くいっていません。

そもそもサブテーブル(見積書明細)オブジェクトを配列に格納することから間違いが生じているような気もするのですが。

この部分、複数行対応でデータを別アプリに格納するヒントはないでしょうか?

こんな感じで、配列を作ってあげればいいと思います。
なお切り貼りしただけですので、内容は検証してください。

//サブテーブル(見積書明細)の内容を配列に格納
var subtable = [];
for (var i = 0; i < tableRecords.length; i++) {
subtable.push({
value: {
"商品コード": { value: tableRecords[i].value['商品コード'].value },
"商品名": { value: tableRecords[i].value['商品名'].value },
"単価": { value: tableRecords[i].value['単価'].value },
"数量": { value: tableRecords[i].value['数量'].value },
}
});
}

var params = {
"app": salesDao.APP_ID,
//見積書の鑑
"record": {
"見積書番号": {
"value": recordInf['見積書番号']['value']
},

...

//見積書明細(サブテーブル)
"見積書明細": {
"value": subtable
}
};

余計なtype などが入りそうなので、下記の方がよさそうです。

訂正前
“商品コード”: tableRecords[i].value[‘商品コード’],

訂正後
“商品コード”: { value: tableRecords[i].value[‘商品コード’].value },

 

 

Naohiro Fukudaさん

 

サブテーブルの取扱は最初は試行錯誤と慣れが必要になるかと思います。構造に慣れと納得が出てくるのが最初の障壁かもしれません。あとは、やはり入力済みのレコードから構造を読み取るのが理解へのヒントととして欠かせませんので、event.record や kintone.app.record.get() で見てみることをおすすめします。

 

見させてもらったコードと実現されたい内容を拝見すると、いま押さえられた方が良さそうなポイントは2つくらいでしょうか。

 

ひとつ目は、苦慮されているサブテーブルの構造についてです。サブテーブルの構造は配列なので、次のような形でpushしていくことで、(for文に入れる等して)可変行数にも対応できます。今回のケースでは tableRecords のfor文の中でpushすると良さそうに思います。 

var subtable = []; // これをサブテーブルフィールドのvalueとして指定します(2つ目の項目に書いてます)
subtable.push({
// id: 1111, // 更新時にはここにサブテーブルの行のidがきます。そのため、このidと次行のvalueを区別するため、次の行のvalueが余計に見えることがあります
value: {
"商品コード": {
"value": productID
},
"商品名": {
"value": productName
},
"単価": {
"value": unitPrice
},
"数量": {
"value": quantity
}
}
});

最初に書かれていたコードはvalueと配列になりうる階層が少しごっちゃになっていましたので、よく確認してもらうと良いかと思います。

 

ふたつ目は(既にチェック済みかもしれませんが)サブテーブルも通常のフィールドと同じ並びですので、POSTのパラメータとしては、

"app": salesDao.APP_ID,
//見積書の鑑
"record": {
"見積書番号": {
"value": recordInf['見積書番号']['value']
},
"取引先コード": {
"value": recordInf['取引先コード']['value']
},
"取引先名": {
"value": recordInf['取引先名']['value']
},
"敬称": {
"value": recordInf['敬称']['value']
},
"見積書明細": {
"value": subtable // subtableはサブテーブルの配列(これの作り方を1項目で書いてます)
}
}

のようになるというところです。

 

今回はこれら2点注意してもらうと、うまくいきそうに思います。あとは、REST APIのリクエストを成功させる勘を掴むにはPOSTMAN等で試行してまず成功させてみるというのも常套手段です。こちらの記事 で紹介されているPOSTMANのkintoneコレクションにサブテーブルの例もありますので、まずはそちらを書き換えて成功させてみるというのも良いと思います。

 

rex0220さん、Ryu Yamashitaさん

まずはご提示いただいたコードを参考にして目的の動作が実現しましたので、お礼を申し上げます。今回はほとんど依存してしまったのですが、サブテーブルを扱う段階となりハードルが上がったことも事実でした。ただ、お二人のご指摘により経験を重ね、このあたりは応用もできると思います。

どうもありがとうございました。

このトピックはベストアンサーに選ばれた返信から 3 日が経過したので自動的にクローズされました。新たに返信することはできません。