Salesforce OCI の API 利用してみる

※ これから記載する事項は、私が所属する会社とは一切関係のない事柄です。

今回は Salesforce の[オムニチャネル在庫](https://trailhead.salesforce.com/ja/content/learn/modules/omnichannel-inventory)（OCI）の API の使い方を紹介したいと思います。基本的には Salessforce Platform の REST API を利用するのと変わらないのですが、一部の API は少しわかりずらいところがあるのでその点を紹介したいと思います。


## Salesforce OCI の API について

Salesforce OCI API は [REST](https://developer.salesforce.com/docs/atlas.en-us.chatterapi.meta/chatterapi/connect_resources_omnichannel_inventory_resources.htm) と [Apex の関数](https://developer.salesforce.com/docs/atlas.en-us.apexref.meta/apexref/apex_ConnectAPI_OmnichannelInventoryService_static_methods.htm)として提供されています。REST を使用する際の認証などについては「[Connect REST API Quick Start](https://developer.salesforce.com/docs/atlas.en-us.chatterapi.meta/chatterapi/quickstart.htm)」をご覧ください。
今回は「[OAuth 2.0 クライアントログイン情報フローの接続アプリケーションの設定](https://help.salesforce.com/s/articleView?id=sf.connected_app_client_credentials_setup.htm&type=5)」で接続アプリケーションを設定し、「[Connect to Connect REST API Using OAuth](https://developer.salesforce.com/docs/atlas.en-us.chatterapi.meta/chatterapi/quickstart_connecting.htm)」でトークンを取得しました。

:::note warn
今回は Salesforce Connect API のみ取り上げますが、B2C Commerce から OCI を利用する場合は[独自の API](https://developer.salesforce.com/docs/commerce/commerce-api/references/inventory-availability?meta=Summary) がありますのでご注意ください。
:::



## OCI の API でできること

ざっくりとした説明ですが、下記の様なことができます。

* 在庫情報の更新・取得
* 予約の作成・開放・履行・移動



## 在庫のアップロード

基本的には普通の REST API と仕様は変わらないですが在庫の更新の部分は少し特殊なので、コードと共に紹介します。
在庫更新 API に関してはヘルプの「[Availability Records, Upload](https://developer.salesforce.com/docs/atlas.en-us.chatterapi.meta/chatterapi/connect_resources_oci_availability_records_upload.htm#UploadResource)」をご確認ください。


### 更新ファイルの準備

在庫の更新には JSON を１行づつ並べたファイルをアップロードする必要があります。その際には下記のようにフォーマットされた状態ではなく、一行にまとまった状態にする必要があります。ファイルの拡張子は `.json` でも `.jsonl` でもどっちでも良さそうです。

これはダメ❌
```json:sample.jsonl
{
  "location": "inventory_m_sample_tokyo",
  "mode": "UPDATE"
}
{
  "recordId": "0a87539d-f3dd-47bc-91c7-9c75abc123de",
  "onHand": 10,
  "sku": "C-300",
  "effectiveDate": "2020-12-08T14:05:22.790896-07:00",
  "futures": [
    {
      "quantity": 1,
      "expectedDate": "2021-04-18T14:05:22.781-07:00"
    }
  ],
  "safetyStockCount": 0
}
```

これは良い⭕️
```json:sample.jsonl
{"location":"inventory_m_sample_tokyo","mode":"UPDATE"}
{"recordId":"0a87539d-f3dd-47bc-91c7-9c75abc123de","onHand":10,"sku":"C-300","effectiveDate":"2020-12-08T14:05:22.790896-07:00","futures":[{"quantity":1,"expectedDate":"2021-04-18T14:05:22.781-07:00"}],"safetyStockCount":0}
```




### アップロード

ファイルのアップロードは `/commerce/oci/availability-records/uploads` に対して POST します。


##### Node.js のサンプル

https://github.com/SalesforceDevelopersJapan/jp-cc-se/blob/main/tools/jpccsfdx/src/lib/service/oci/lightning-availability.ts#L43


##### Apex のサンプル

https://github.com/SalesforceDevelopersJapan/jp-cc-se/blob/main/packages/OCIInventoryRegistration/force-app/main/default/classes/OciInvRegController.cls#L41


##### Postman のサンプル

Postman の場合はフォームデータのファイルに設定してアップロードします。
![スクリーンショット 2023-12-06 15.45.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2110894/cc983d86-3aa2-dd85-3139-6cccd2b3e6db.png)




### アップロードの状態

ファイルのアップロードは `/commerce/oci/availability-records/uploads/{uploadId}` に対して GET します。
レスポンスに「COMPLETED」と入っていれば完了です。

![スクリーンショット 2023-12-06 15.56.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2110894/b92b8769-a9be-8bc5-ad9b-5fe289f85994.png)