本文解說 ReceiptRoller 處理的交易資料正規模型 PosTransactionDto 的所有欄位。各 POS 供應商(Smaregi、Square、其他)的交易資料都會轉換為此模型後,透過資料庫、儀表板、REST API、MCP 工具來使用。
從外部系統經由 API 讀寫交易時,或想理解供應商端的欄位在 ReceiptRoller 上如何呈現時,請作為參考。
概要
PosTransactionDto 表示 1 筆交易(1 筆結帳)。明細(商品單位)以 LineItems 陣列保存,內部則以 LineItemsJson 的 JSON 持久化。
- 金額以
Currency 表示的貨幣(預設 JPY),除非另有說明,否則為含稅
- 所有日期時間以 UTC 保存,顯示時轉換為 JST
- 鍵:
TransactionId(ReceiptRoller 內部 ID)與 ExternalTransactionId(POS 供應商端的 ID)兩個
- 付款支援多個 tender(分開結帳),以
Payments 陣列保存(單一字串的 PaymentMethod 為向後相容而保留)
- 退款、外部串接 ID、卡片資訊、原始資料等,都經擴充以不遺漏供應商送出的資訊
識別碼
| 欄位 | 型別 | 說明 |
TransactionId | string | ReceiptRoller 內部的交易 ID。多數情況直接採用 POS 端的 ID(成為 idempotent upsert 的鍵) |
ExternalTransactionId | string | POS 供應商端的交易 ID。Smaregi: transactionHeadId,Square: Payment.Id |
OrganizationId | string (Guid) | 商業帳戶的 ID |
StoreId | string (Guid) | 店鋪 ID |
TerminalId | string (Guid) | POS 端末(收銀機)的 ID |
日期時間
| 欄位 | 型別 | 說明 |
TransactionDateTime | DateTime (UTC) | 結帳成立的時刻。從 Square created_at、Smaregi transactionDateTime 轉換 |
CreatedAt | DateTime (UTC) | ReceiptRoller 端的記錄建立時刻(稽核用) |
UpdatedAt | DateTime (UTC) | ReceiptRoller 端的記錄更新時刻(稽核用) |
金額
| 欄位 | 型別 | 說明 |
Currency | string | 所有金額的貨幣碼(ISO-4217,預設 JPY)。Square 從 money.currency,Smaregi 固定 JPY |
TotalAmount | decimal | 合計金額(含稅) |
TaxAmount | decimal | 消費稅額 |
SubtotalAmount | decimal | 小計(未稅)= TotalAmount - TaxAmount |
DiscountAmount | decimal | 折扣額(不以負值,而是以正值保存) |
TipAmount | decimal? | 小費、服務費。僅供應商另外送出時(Square tip_money)。無此項時為 null |
明細
| 欄位 | 型別 | 說明 |
LineItems | List<PosTransactionLineItemDto> | 商品單位的明細陣列(計算屬性。實體為 LineItemsJson) |
LineItemsJson | string (JSON) | 明細的 JSON 持久化格式。請勿直接讀取,使用 LineItems |
ItemCount | int | 明細數量的合計(LineItems.Sum(li => li.Quantity)) |
PosTransactionLineItemDto
| 欄位 | 型別 | 說明 |
ProductName | string | 商品名稱。有變體時為 "商品名 (變體名)" 格式 |
Quantity | int | 銷售數量 |
UnitPrice | decimal | 單價(未稅) |
Subtotal | decimal | 小計(含稅) |
TaxRate | decimal | 實效稅率(%)。Square 從明細自動計算,Smaregi 採用 taxRate |
TaxAmount | decimal? | 明細單位的稅額。Square total_tax_money,Smaregi tax。只有稅率而無稅額的供應商、過去資料則為 null |
DiscountAmount | decimal? | 明細單位的折扣額。Square total_discount_money。無明細別折扣的供應商則為 null |
Category | string | 商品類別。Smaregi 為 categoryName,Square 目前為空 |
Sku | string? | 供應商 SKU / 商品代碼。Smaregi 為 productCode。用於與 PIM 商品比對 |
CostPriceAtSale | decimal? | 銷售時點的 PIM 原價(未稅)快照。用於毛利計算。原價未設定則為 null |
ProductId | string? | 來源商品 ID(判明時) |
CatalogObjectId | string? | 供應商的目錄物件 ID(Square catalog_object_id,Smaregi productId)。用於系統間串接 |
Unit | string? | 銷售單位(「個」「kg」等)。僅供應商有此欄位時 |
Note | string? | 明細單位的備註 |
Modifiers | List<PosLineItemModifierDto>? | 明細的選項、加料(Square modifiers)。持有 Name 與 Amount |
付款
交易可以有多個 tender(分開結帳)。完整的內容明細保存於 Payments(實體為 PaymentsJson),單一字串的 PaymentMethod 為向後相容而保存「主要 tender」。
| 欄位 | 型別 | 說明 |
PaymentMethod | string (enum) | 將主要付款方式正規化:
Cash / CreditCard / QR / IC / Other |
Payments | List<PosPaymentDto> | tender 的完整內容明細(計算屬性。實體為 PaymentsJson) |
PaymentsJson | string (JSON) | tender 內容明細的 JSON 持久化格式 |
ReceiptNumber | string | 收據號碼(POS 端採番的號碼) |
PosPaymentDto
| 欄位 | 型別 | 說明 |
Method | string | 正規化後的方式(Cash / CreditCard / QR / IC / Other),或不支援時為供應商的原始名稱 |
Amount | decimal | 此 tender 的金額 |
TenderedAmount | decimal? | 收取金額(供應商回報時) |
ChangeAmount | decimal? | 找零(供應商回報時) |
Brand | string? | 卡片品牌(VISA、Mastercard 等)。僅卡片結帳 |
Last4 | string? | 卡片末 4 碼。可顯示(不保存 PAN) |
ExternalId | string? | 供應商端的付款 ID(與交易 ID 不同時) |
退款
(部分)退款交易的退款內容明細。保存於 Refund(實體為 RefundJson)。
| 欄位 | 型別 | 說明 |
Refund | PosRefundDto? | 退款內容明細(無則為 null) |
RefundJson | string (JSON) | 退款內容明細的 JSON 持久化格式 |
PosRefundDto
| 欄位 | 型別 | 說明 |
Amount | decimal | 退款額 |
IsPartial | bool | 是否為部分退款 |
Reason | string? | 退款理由 |
OriginalTransactionId | string? | 退款對象的原交易 |
RefundedAt | DateTime? | 退款日期時間 |
注: 模型與 API 的介面已備妥,若退款資料存在即會反映。由於 Square / Smaregi 會將退款作為另一個 Webhook 事件送出,端到端的退款接收以另外的同步處理因應。
外部串接、收據 URL
保存來源 POS 的各種 ID 與收據 URL,以便將交易對應回原始記錄。
| 欄位 | 型別 | 說明 |
ReceiptUrl | string | 顧客用收據 URL(Square receipt_url)。為結構化欄位(以前保存於 Notes,現已廢止) |
ExternalIds | PosExternalIdsDto? | 供應商橫跨 ID(計算屬性。實體為 ExternalIdsJson) |
ExternalIdsJson | string (JSON) | 外部 ID 的 JSON 持久化格式 |
PosExternalIdsDto
| 欄位 | 型別 | 說明 |
ProviderOrderId | string? | 供應商的訂單 ID(Square order_id) |
LocationId | string? | 供應商的據點 ID(Square location_id) |
ProviderCustomerId | string? | 供應商的顧客 ID(Square customer_id,Smaregi customerId) |
原始資料
| 欄位 | 型別 | 說明 |
RawJson | string (JSON) | 擷取時的來源原始承載。保存以便未模型化的欄位(卡片 fingerprint 等)也可還原。僅供伺服器內部用,API 不回傳 |
員工
| 欄位 | 型別 | 說明 |
StaffName | string | 負責員工名稱(無法取得時為空) |
StaffId | string | POS 供應商端的員工 ID(Square: team_member_id,Smaregi: staffId) |
狀態、來源
| 欄位 | 型別 | 說明 |
Status | string (enum) | Completed / Voided / Refunded / Pending。顯示用為 StatusDisplayName |
Source | string (enum) | API(從 POS 自動擷取)/ Webhook(從 POS 推播通知)/ CSV(整批擷取)/ Manual(手動輸入) |
Notes | string | 備註、備忘。收據 URL 已移動至 ReceiptUrl,因此這裡不再保存 |
CRM 串接
當交易關聯至顧客時(POS 端的會員資訊、電話、電子郵件一致等),ReceiptRoller 的 ICrmCustomerResolver 會填入以下欄位。
| 欄位 | 型別 | 說明 |
MembershipCode | string? | ReceiptRoller 會員編號。未關聯時為 null |
CrmCustomerId | string? | CRM 顧客記錄的 ID。未關聯時為 null |
供應商端的原始顧客 ID 可透過 ExternalIds.ProviderCustomerId 另外參照。
顯示用輔助
供 UI 端使用的計算屬性。不會直接保存於 DB。
PaymentMethodDisplayName — 付款方式的本地化標記(例:「信用卡」)
StatusDisplayName — 狀態的本地化標記(例:「完成」「取消」)
StatusBadgeClass — Bootstrap 徽章用 CSS 類別
SourceDisplayName — 來源的顯示名稱
FormattedDateTime — 「yyyy/MM/dd HH:mm」格式的日期時間
FormattedTotal — 加上千分位的合計金額
向後相容性
上述的擴充欄位皆為新增、nullable,以 JSON 欄位持久化。Table Storage 不需要遷移,既有列或既有的 LineItemsJson 皆維持有效。新欄位從新擷取的交易開始反映(要反映至過去資料需要重新同步)。
各供應商對應
各 POS 供應商具體如何填入哪個欄位,請參閱以下的各供應商對應文章。
相關指南