開発者向け機能:スクリプト:$p.apiUpsert
## 概要
AjaxのPOSTリクエストにより、レコードおよびWikiを作成・更新します。
・ 指定したキー項目に一致するレコードがある場合:該当レコードを更新
・ 指定したキー項目の値がNULLの場合:レコードを新規作成
・ 一致するレコードがない場合:レコードを新規作成
## 使い方
##### JavaScript
```
$p.apiUpsert({
id: <サイトID>,
data: {
<データ>
},
done: <任意の処理>,
fail: <任意の処理>,
always: <任意の処理>
});
```
## 各パラメータの説明
|パラメータ名|説明|
|:--|:--|
|サイトID|任意のサイトID|
|データ|POSTするjsonデータ|
|任意の処理|API通信成功(done:必須)、失敗時(fail:任意)、完了時(always:任意)の処理|
## 記述方法
##### JavaScript
```
$p.apiUpsert({
id: 123,
data: {
ApiVersion: 1.1,
Keys: [
'ClassA',
'ClassB'
],
ClassHash: {
ClassA: 'テストデータ',
ClassB: 'テストデータ詳細です'
}
},
done: function (data) {
console.log(data);
},
fail: function (data) {
console.log(data);
},
always: function (data) {
console.log(data);
}
});
```
## サンプルコード
##### コード内の【 ... 】 は適宜修正してください。
<details>
<summary>1. 2テーブル間でデータを同期管理する。</summary>
レコード更新後に、外部キー(ClassB)をもとに指定したテーブルへ内容を同期します。
画面で「入力テーブル」のレコードを保存すると、そのレコードIDを外部キーとして「反映先テーブル」で検索します。
一致するレコードがあれば更新、なければ新規作成し、以降も同じレコードからの更新は同じ反映先レコードに上書きされます。
**実務での使いどころ**
・受注確定時に案件情報を契約管理テーブルへ自動反映
・問い合わせ内容を社内ダッシュボードへミラーリング
・現場入力用テーブルと報告用テーブルを分けつつ入力を一本化
・複数店舗の日報テーブルを本部集計用テーブルへ集約
##### JavaScript
```
// 反映先サイトID
const destinationId = 【サイトID】;
const syncToDestination = () => {
// 入力テーブルのレコードIDを外部キーとして使用
const sourceId = $p.id();
const data = {
ApiVersion: 1.1,
Keys: ['ClassB'], // 外部キー項目(この値で更新/新規を判定)
Title: $p.getValue('Title'),
Status: $p.getValue('Status'),
ClassHash: {
ClassA: $p.getValue('ClassA'),
ClassB: sourceId, // 外部キー(入力レコードID)
},
};
$p.apiUpsert({
id: destinationId,
data: data,
done: function (res) {
// res.Message に「作成しました」「更新しました」がサーバーから返る
console.log(`Upsert成功(外部キー=${sourceId}): ${res.Message}`);
},
fail: function (res) {
console.log(`Upsert失敗(外部キー=${sourceId})`, res);
},
});
};
// レコード新規作成後・更新後の両方で反映を実行
$p.events.after_set_Create = function () {
syncToDestination();
};
$p.events.after_set_Update = function () {
syncToDestination();
};
```
##### 実行結果
```
Upsert成功(外部キー=998): タイトルAを作成しました。
Upsert成功(外部キー=999): タイトルBを更新しました。
```
</details>
<details>
<summary>2. 祝日データを定期的に取り込む。</summary>
祝日APIは、すべての祝日データを毎回返す仕様のため、単純に登録すると同じ日付の祝日が重複して作成されてしまいます。
祝日の日付を一意なキーとして扱い、Upsertの Keys に日付項目(DateA)を指定することで、同じ日付のレコードが存在する場合は更新、存在しない場合は新規作成を自動で判定できます。これにより、祝日APIを何度実行しても差分のみを安全に反映できます。
**実務での使いどころ**
・祝日APIなど外部マスタデータを社内テーブルへ定期的に同期
・為替レートや郵便番号など外部提供の一覧データを定期反映
・取引先マスタなど外部システムの出力をUpsertで重複なく取り込む
**サンプルコード内の処理について**
コード中のupsertHolidayRecord(1件分のUpsert処理)と$.ajax以降(API取得とループ制御)はあえて分けています。
$p.apiUpsertは非同期処理のため全件を一度に呼び出すと通信が集中してエラーになりやすく、1件ずつ完了を待って次を呼ぶ「直列実行」にするため、1件処理とループ制御の責務を分離しています。
##### JavaScript
```
// 反映先サイトID
const destinationId = 【サイトID】;
// 祝日レコードをUpsertする
const upsertHolidayRecord = (date, name) => {
return $p.apiUpsert({
id: destinationId,
data: {
ApiVersion: 1.1,
Keys: ['DateA'], // 祝日の日付を一意キーとして Upsert 判定
ClassHash: { ClassA: name },
DateHash: { DateA: date },
},
done: function (res) {
console.log(`(Info):祝日レコード作成/更新成功: ${date} ${name}`);
},
fail: function (res) {
console.log(`(Info):祝日レコード作成/更新失敗: ${date} ${name}`);
},
});
};
// 祝日APIから祝日データを取得し、順番にUpsertする
$.ajax({
url: 'https://holidays-jp.github.io/api/v1/date.json',
type: 'GET',
dataType: 'json',
})
.done(function (nationalHolidays) {
if (!nationalHolidays) {
console.log('祝日データ取得失敗');
return;
}
// 祝日データをもとにレコードを作成/更新(直列に実行)
const dates = Object.keys(nationalHolidays);
const runSequential = (index) => {
if (index >= dates.length) {
console.log('全ての祝日レコードの処理が完了しました');
return;
}
const date = dates[index];
const name = nationalHolidays[date];
upsertHolidayRecord(date, name).always(function () {
runSequential(index + 1);
});
};
runSequential(0);
})
.fail(function (jqXHR, textStatus) {
console.log(`祝日API取得エラー: ${textStatus}`);
});
```
##### 実行結果
```
(Info):祝日レコード作成/更新成功: 2025-01-01 元日
(Info):祝日レコード作成/更新成功: 2025-01-13 成人の日
(Info):祝日レコード作成/更新成功: 2025-02-11 建国記念の日
(Info):祝日レコード作成/更新成功: 2025-02-23 天皇誕生日
(Info):祝日レコード作成/更新成功: 2025-02-24 天皇誕生日 振替休日
・・・・・
全ての祝日レコードの処理が完了しました
```
</details>



