POST時(サブテーブル)エラーについて

いつもお世話になっております。

下記、Aアプリ(通常フィールド+サブテーブル)→Bアプリ(通常フィールド+サブテーブル)にPOSTする際に400エラーが出ています。

色々試してみましたが、わからず、お力を貸してください。

サブテーブルを除外するとPOSTできたので、サブテーブルの記載が悪いのだと思いますが…

アドバイスよろしくお願いします。

…

for (var i = 0; i < mainTable.length; i++) {
  …
    table = {"value": []};
    for (var j = 0; j < meisaiTbl.length; j++) {
          if(meisaiTbl[j].value['明細番号1'].value == hyoshiNo){
               //同じ集計番号の明細を取得
               var row = {};
               var tblNo = meisaiTbl[j].value;
               row['分類'] = {value: tblNo['明細分類'].value};
               row['番号'] = {value: Number(tblNo['明細番号'].value)};
              row['品名'] = {value: tblNo['明細品名'].value};
               row['数'] = {value: Number(tblNo['明細数'].value)};
               row['単位'] = {value: tblNo['明細単位'].value};
               row['単価'] = {value: Number(tblNo['明細単価'].value)};
               row['金額'] = {value: Number(tblNo['明細金額'].value)};
               row['定価'] = {value: Number(tblNo['明細定価'].value)};
               row['原価'] = {value: Number(tblNo['明細原価'].value)};
               row['原価率'] = {value: Number(tblNo['明細原価率'].value)};
               row['備考'] = {value: tblNo['明細備考'].value};
               table.value.push({value: row});
           }
     }
                  
     //新規登録
     var iBody={
          app:meisaiAppId,
          record:{
          ['見積表紙レコード番号']:{value:insertRecNo},
          ['見積集計番号']:{value:hyoshiNo},
          ['名称']:{value:daiBunrui},
          ['明細合計']:{value:Number(daiSyoukei)},
          ['明細テーブル']:table
      }
      };
      kintone.api(kintone.api.url('/k/v1/record', true), 'POST', iBody).then(function(resp5) {
      }, function (resp5){
           console.log("見積明細登録エラー");
      });

matsu さん

下記コードで試した限りデータ構造的には問題がないので、エラーの可能性があるとすればコピー元のデータの不備、またはフィールドの値が不一致(変換不可)、が考えられます。APIの失敗処理でエラーを出力してみてはいかがでしょうか。

var table = { value: [] };
for (var j = 0; j < 1; j++) {
  var row = {};
  row['分類'] = { value: 'A' };
  row['番号'] = { value: 1 };
  table.value.push({ value: row });
}
var iBody = {
  app: kintone.app.getId(),
  record: {
    ['明細テーブル']: table,
  },
};
kintone.api(kintone.api.url('/k/v1/record', true), 'POST', iBody).then(
  function (resp5) {},
  function (resp5) {
  console.error('見積明細登録エラー', iBody, resp5);
  }
);

以上になります。参考になれば幸いです。

matsu 様
横槍になってしまうかもしれませんが、ChromeやEdgeのデベロッパツールでステータス400が出たときにペイロードを確認できますので、確認してみてはいかがでしょうか?
ペイロードの確認をするとデータ構造が視覚的に見えやすいのかなと感じました。

Chromeでのペイロードの確認の仕方:
https://www.tsukimi.net/chrome-developer-tools_post.html 

川村様

お世話になります。

とても参考になりました!今後エラー出力重宝します!

エラー出力で確認すると、どうやらこの記述の前の処理が問題でした。

Promise処理で同じレコードがある場合DELETEしてからPOSTする、という流れにしているのですが、

Promiseがどうやらうまくいってなく、DELETEする前にPOSTして重複エラーになっていました。

…
.then((resp3) =\>{
   //①アプリBにデータがあるか検索、ある場合は削除データ作成
    var param3 = {
      app: meisaiAppId,
      query:'見積表紙レコード番号 = "'+ recordNo +'"',
    };
  kintone.api('/k/v1/records','GET', param3, function (resp3) {
      var record3 = kintone.app.record.get();
     if(resp3.records.length >0) {
       //全件削除
       for(var i =0; i < resp3.records.length; i++) {
          delList.push(resp3.records[i]['レコード番号'].value);
        }
    }
    });
  })
  .then((resp4) =\>{
   //②削除データがある場合、アプリB削除
   if(delList.length >0) {
      const dbody = {
        app: meisaiAppId,
        ids: delList,
      };
    kintone.api(kintone.api.url('/k/v1/records',true),'DELETE', dbody)
        .then(
          function (resp4) {
           console.log('削除完了');
          },
         (error) =\>{
           console.log(error);
          }
        );
  }
  })
  .then((resp5) =\>{
   //③今回の処理 アプリAの情報をアプリBに登録
  }));

Yuki Minamitani

お世話になります。

ペイロード確認、初めて知りました。

今後活用させていただきます!

ありがとうございました!

matsu さん

お役に立てて嬉しいです。

Promise で処理の完了を待つ場合、コールバックの関数内で Promise を return する必要があります。

元のコードに少し手を加え、「※」付きでコメントさせていただきました。

  .then((resp3) => {
    //①アプリBにデータがあるか検索、ある場合は削除データ作成
    var param3 = {
      app: meisaiAppId,
      query: '見積表紙レコード番号 = "' + recordNo + '"',
    };
    // ※ kintone.api は Promise を返すのでここの処理が終わったら次の then が実行
    return kintone.api('/k/v1/records', 'GET', param3, function (resp3) {
      var record3 = kintone.app.record.get();

      if (resp3.records.length > 0) {
        //全件削除
        for (var i = 0; i < resp3.records.length; i++) {
          delList.push(resp3.records[i]['レコード番号'].value);
        }
      }
      // ※ ここで return した値は次の then の関数の引数 resp4 に渡せる
    });
  })
  .then((resp4) => {
    //②削除データがある場合、アプリB削除
    if (delList.length > 0) {
      const dbody = {
        app: meisaiAppId,
        ids: delList,
      };
      // ※ kintone.api は Promise を返すのでここの処理が終わったら次の then が実行
      return kintone
        .api(kintone.api.url('/k/v1/records', true), 'DELETE', dbody)
        .then(
          function (resp4) {
            console.log('削除完了');
            // ※ ここで return した値は次の then の関数の引数 resp5 に渡せる
          },
          (error) => {
            console.log(error);
          }
        );
    }

    // ※ return しなければ resp5 = undefined が設定されて次の then が実行
  })
  .then((resp5) => {
    //③今回の処理 アプリAの情報をアプリBに登録
  }));

参考:プロミスの使用 - MDN

以上になります。何か不明な点がありましたら、気兼ねなくご質問ください。

 

川村様

お世話になります。

詳しい説明、ありがとうございます!

returnが全部抜けていたせいなんですね!追加したらちゃんと動作してくれました。

やっと次に進めます~(泣)ありがとうございました★