> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fluz.app/llms.txt
> Use this file to discover all available pages before exploring further.

# 新增費用詳細資訊

你可以為任何交易新增**備註**、**類別**，以及/或**附件**（例如收據、發票、採購單）。註記可在原始交易時加入，或之後使用 `updateTransactionMetadata` mutation 進行更新。

支援註記的類型：

* 存款（`depositCashBalance1`）
* 禮品卡購買（`purchaseGiftCard`）
* 錢包轉帳（`createTransfer`, `transferInternalBalance`）
* 虛擬卡建立（`createVirtualCard`）
  * 不支援 `attachment`

***

## 運作方式

1. 選用：若你想附加檔案，先透過 REST 上傳端點上傳。你會收到一個 `attachmentId`。
2. 在 mutation 的 input 中傳入 `memo`、`transactionCategory`，以及/或 `attachmentId`——可以在交易發生時傳入，或之後透過 `updateTransactionMetadata` 更新。
3. 在 `getTransactions`、`getUserPurchases`，或 mutation 回應中讀取註記。`attachmentUrl` 欄位會回傳短效的簽名 URL 以供存取檔案。

***

## 第 1 步：上傳附件（選用）

> 這是 REST 端點，而非 GraphQL mutation

### 端點

`POST /api/v1/file-upload/transaction-memo-attachment`

### 認證

`Authorization: Bearer <YOUR_USER_ACCESS_TOKEN>`

### 請求

以 `multipart/form-data` 方式傳送檔案，欄位名稱為 `file`。

**可接受的類型：** `application/pdf`, `image/png`

> ⚠️ 交易附件不接受 JPEG。

### 範例請求

```bash theme={null}
curl -X POST https://transactional-graph.staging.fluzapp.com/api/v1/file-upload/transaction-memo-attachment \
  -H "Authorization: Bearer <YOUR_ACCESS_TOKEN>" \
  -F "file=@receipt.pdf"
```

### 回應

```json theme={null}
{
  "attachmentId": "3f2a1b4c-e5d6-7890-abcd-ef1234567890"
}
```

複製這個 `attachmentId`——你會在下一步的 mutation input 中使用它。

> `attachmentId` 會限制在你的帳戶範圍內。當你提交 mutation 時，系統會驗證該檔案是否存在於你的帳戶儲存空間中。來自其他帳戶的 ID 會被拒絕。

### 上傳錯誤

| 原因               | 狀態  | 詳細資訊                |
| ---------------- | --- | ------------------- |
| 請求中未包含檔案         | 400 | Missing file        |
| 檔案類型不允許（例如 JPEG） | 400 | `INVALID_ARGUMENTS` |

***

## 第 2 步：為交易加上註記

你可以在原始交易發生時提供註記，**或是**之後再更新。

### 選項 A — 在交易發生時

以下 mutations 的 input 接受 `memo`、`transactionCategory`，以及 `attachmentId` 作為選填欄位：

* `depositCashBalance` → `DepositCashBalanceInput`
* `purchaseGiftCard` → `PurchaseGiftCardInput`
* `createTransfer` → `CreateTransferInput`
* `transferInternalBalance` → `TransferInternalBalanceInput`

#### 註記欄位

| 欄位                    | 類型     | 說明                                       |
| --------------------- | ------ | ---------------------------------------- |
| `memo`                | String | 自由文字備註。最多 255 個字元。                       |
| `transactionCategory` | String | 類別標籤。自由填寫——第一次使用時會自動建立該類別，之後傳入相同名稱會重複使用。 |
| `attachmentId`        | String | 上傳端點回傳的 ID。必須於提交 mutation 前先完成檔案上傳。      |

#### 範例 — 購買禮品卡並加上註記

```graphql theme={null}
mutation purchaseGiftCard($input: PurchaseGiftCardInput!) {
  purchaseGiftCard(input: $input) {
    purchaseDisplayId
    purchaseAmount
    memo
    transactionCategory
    attachmentUrl
    giftCard {
      giftCardId
      status
    }
  }
}
```

```json theme={null}
{
  "idempotencyKey": "0284be6f-1a69-44f7-9da0-5b5edaf45d19",
  "offerId": "0284be6f-1a69-44f7-9da0-5b5edaf45d19",
  "amount": 50.00,
  "balanceAmount": 50.00,
  "memo": "Team lunch — Q2",
  "transactionCategory": "Meals & Entertainment",
  "attachmentId": "3f2a1b4c-e5d6-7890-abcd-ef1234567890"
}
```

***

### 選項 B — 交易後（`updateTransactionMetadata`）

使用此 mutation 為任何現有交易新增或更新註記。

> 部分更新語意：只有你包含的欄位會被更新。省略的欄位維持不變。傳入 `null` 可清除欄位值。

#### Mutation

```graphql theme={null}
mutation updateTransactionMetadata($input: UpdateTransactionMetadataInput!) {
  updateTransactionMetadata(input: $input) {
    record_id
    memo
    transactionCategory
    attachmentUrl
  }
}
```

#### UpdateTransactionMetadataInput

| 欄位                    | 類型     | 必填 | 說明                                     |
| --------------------- | ------ | -- | -------------------------------------- |
| `recordId`            | UUID!  | 是  | 要更新之交易的 `record_id`。                   |
| `memo`                | String | 否  | 自由文字備註。最多 255 個字元。省略則不變；傳入 `null` 以清除。 |
| `transactionCategory` | String | 否  | 類別標籤。省略則不變；傳入 `null` 以清除。              |
| `attachmentId`        | String | 否  | 上傳端點取得的 ID。省略則不變；傳入 `null` 以清除。        |

#### 必要 Scopes

`LIST_PAYMENT` 和 `LIST_PURCHASES`

#### 範例 — 新增備註與類別

```json theme={null}
{
  "recordId": "550e8400-e29b-41d4-a716-446655440000",
  "memo": "Q1 vendor payment",
  "transactionCategory": "Operating Expenses"
}
```

#### 範例 — 將檔案附加至現有交易

```json theme={null}
{
  "recordId": "550e8400-e29b-41d4-a716-446655440000",
  "attachmentId": "3f2a1b4c-e5d6-7890-abcd-ef1234567890"
}
```

#### 範例 — 清除備註

```json theme={null}
{
  "recordId": "550e8400-e29b-41d4-a716-446655440000",
  "memo": null
}
```

#### 範例回應

```json theme={null}
{
  "data": {
    "updateTransactionMetadata": {
      "record_id": "550e8400-e29b-41d4-a716-446655440000",
      "memo": "Q1 vendor payment",
      "transactionCategory": "Operating Expenses",
      "attachmentUrl": "https://storage.googleapis.com/..."
    }
  }
}
```

#### 錯誤

| 原因                        | 錯誤                                                                             |
| ------------------------- | ------------------------------------------------------------------------------ |
| 找不到 `recordId`，或其屬於另一個帳戶  | `INVALID_ARGUMENTS` — transaction not found                                    |
| 該交易類型不支援中繼資料              | `INVALID_ARGUMENTS` — transaction does not support metadata                    |
| `attachmentId` 不是有效的 UUID | `INVALID_ARGUMENTS` — Invalid attachment ID                                    |
| 在儲存空間找不到檔案（未上傳，或帳戶不正確）    | `INVALID_ARGUMENTS` — Attachment file not found. Please upload the file first. |

***

## 讀取註記

以下會回傳註記：

| 查詢 / Mutation               | 類型                   | 欄位                                             |
| --------------------------- | -------------------- | ---------------------------------------------- |
| `getTransactions`           | `Transaction`        | `memo`, `transactionCategory`, `attachmentUrl` |
| `getUserPurchases`          | `UserPurchase`       | `memo`, `transactionCategory`, `attachmentUrl` |
| `updateTransactionMetadata` | `Transaction`        | `memo`, `transactionCategory`, `attachmentUrl` |
| `depositCashBalance`        | `CashBalanceDeposit` | `attachmentUrl`                                |

> ⚠️ `attachmentUrl` 是簽名 URL，會在產生後不久過期。請勿儲存它——當你需要顯示或存取檔案時，重新抓取該交易資料。
