---
# System prepended metadata

title: mPOS API
tags: [mPOS]

---

---
tags: mPOS
---
<style>

/* .toc > ul:first-child > li:first-child {
    display: none;
} */

.markdown-body{
  max-width: 80%;
}
.red{color: red}
.blue{color: blue}
.green{color: forestgreen}
.obsolete{color: lightgrey; font-style: italic; }
.line-thru{text-decoration: line-through; } 
</style>

# mPOS API
[toc]

------
# API基本說明

- ### REQUEST 輸入
  - **content-type: application/json**
    - stated otherwise (e.g. Employee Login)
  - 欄位參照各API輸入格式
- ### RESPONSE 輸出
  - **content-type: application/json**
  - 基本欄位
    |COLUMN|TYPE|DESCRIPTION|
    |-|-|-|
    |result|integer|0: 查無資料<br/>1: OK<br/>2: Logic Error<br/>3: Database Error<br/>4: System Error<br/>5: Session 過期, 需重新登入取得新 Token|
    |message|string|回傳訊息|
    |returnList|any|回傳本體，各API各異|
  - API 回傳 `result != 1` 認定 API 結果不成功
- ### API 認證 (JWT Access Token)
  - 除 `status` 及 `employee/login` 外, 其餘API需要認證
  - `POST ./employee/login` 取得 token (參: [登入/驗證](#登入--驗證))
  - 發REQUEST時, 需在 http-header 加入 `Authorization: Bearer <access_token>`
  - 呼叫API認證失敗時, 回傳result=5
  - 參 [Access Token](/rJCLM2LOv)

<hr/>


# Status 狀態
## API Server 資訊/狀態
### GET **`./status`**
- API Server 資訊

#### RESPONSE
<table><thead><tr><th>JSON</th><th></th></tr></thead><tbody><tr><td>

```json
{
  "result": 1,
  "message": "",
  "returnList": {
    "server": "0.2.1 210415-1028_151c19f",
    "DBtime": "TUE 27 APR 2021 09:40:33 AM CST",
    "storeNo": "00219",
    "storeName": "燦坤實業(股)內湖旗艦分公司",
    "storeShortName": "內湖旗艦分公司",
    "addr": "台北市內湖區堤頂大道1段331號"
    "storeTel": "0227955270",
    "TKGUINo": "80358521",
    "creditPercent": 100,
    "storeType": "2",
    "storePrincipal": "XXX",
    "IP": "10.2.219.xxx",
    "receiptMSG": "財政部台北市國稅局內湖稽徵所...",
    "passport": 1,
  }
}
```
</td><td></td></tr></tbody>
<tbody><tr><td>

```json
{
  "result": 3,
  "message": "資料庫錯誤",
  "returnList": {
    "server": "0.2.1 210415-1028_151c19f",
  }
}
```
</td><td>API OK ,<br/>DB連線錯誤</td></tr></tbody>
</table>

|KEY|DESCRIPTION|
|-|-|
|server|API版本|
|DBtime|DB Datetime|
|storeNo|店號|
|storeName|門市名稱|
|storeShortName|門市簡稱|
|addr|門市住址|
|storeTel|電話|
|TKGUINo|門市統編|
|creditPercent|可賒帳信用額度%|
|storeType|門市類別("1":總公司,"2":門市,"3":良品倉)|
|storePrincipal|發票章負責人|
|IP|DB IP|
|receiptMSG|紙本電子發票使用的稅捐稽徵訊息|
|passport|可否退稅|


## API Server ping
### GET **`./status/ping`**
- 測試API連線
#### RESPONSE
<table><thead><tr><th>JSON</th><th></th></tr></thead><tbody><tr><td>

```json
{
  "result": 1,
  "message": "OK"
}
```
</td><td></td></tr></tbody></table>

## API Server 測試 DB 連線
### GET **`./status/db`**
- 測試DB連線/延遲: `SELECT 1 FROM DUAL`

#### RESPONSE
<table><thead><tr><th>JSON</th><th></th></tr></thead><tbody><tr><td><pre>{
  "result": 1
  "message": "OK (db_rt:7ms)",
}</pre></td><td>DB 連線OK + DB response time</td></tr></tbody> <tbody> <tr><td><pre>{
  "result": 3
  "message": "NOT OK",
}</pre></td><td>DB 連線異常</td></tr></table>

## 清除快取
### DELETE **`./status/cache`**
- 清除 JCache 快取暫存

#### RESPONSE
<table><thead><tr><th>JSON</th><th></th></tr></thead><tbody><tr><td><pre>{
  "result": 1,
  "message": "",
  "returnList": null
}</pre></td><td>Cache 清除成功</td></tr></tbody></table>

## 印表機 測試列印
### POST **`./status/printer/testprint`**
- 測試列印發票印表機
#### REQUEST
<table><thead><tr><th>VALUE</th><th></th></tr></thead><tbody><tr><td><pre>{<span class="red">
  "printerNo":"0", <span class="green">//印表機ID</span>
  "termNo":"0025"<span class="green">  //機號</span></span>
}</pre></td><td></td></tr></tbody></table>

#### RESPONSE
<table><thead><tr><th>JSON</th><th></th></tr></thead><tbody><tr><td><pre>{
  "result": 1,
  "message": "",
  "returnList": {
    "printJobId": 32838466,
    "deliverNo": "0000000000000",
    "invoice": "",
    "serialNo": "",
    "printer": "None/RP700/PRN0",
    "status": true,
    "state": 2,
    "msg": null
  }
}</pre></td><td>列印成功</td></tr></tbody><tbody><tr><td><pre>{
  "result": 2,
  "message": "...",
  "returnList": {
    "printJobId": 1004155780,
    "deliverNo": "0000000000000",
    "invoice": "",
    "serialNo": "",
    "printer": "None/RP700/PRN0",
    "status": false,
    "state": 2,
    "msg": "..."
  }
}</pre></td><td>列印異常</td></tr></tbody></table>

|KEY|DESCRIPTION|
|-|-|
|printer|印表機型號 / 印表機ID|
|state|印表機狀態<br/>0: OFFLINE<br/>1: DISCONNECTED<br/>2: ONLINE|
|status|`state==2`|
|msg|印表程式回傳訊息|

# Employee 員工
## 取得員工Employee 清單

- 從USER query 門市員工帳號資料

### GET **`./employee`**
### GET **`./employee?userLevel={userLevel}`**
<table><thead><tr><th>QUERYPARAM</th><th>DESCRIPTION</th></tr></thead><tbody><tr><td>userLevel</td><td>1:店長 2:組長 3:收銀員</td></tr></tbody></table>

#### RESPONSE
<table><thead><tr><th>JSON</th><th></th></tr></thead><tbody><tr><td><pre>{
  "result": 1,
  "message": "",
  "returnList": [
    {
      "userName": "XXX",
      "userId": "123456"
      "validationFlag": "0",
    }, 
    ...
  ]
}</pre></td><td></td></tr></tbody></table>

|KEY|DESCRIPTION|
|-|-|
|userName|使用者姓名|
|userId|使用者ID (6碼薪號)|
|validationFlag|0:離職<br/>1:在職|

## 登入 / 驗證

### POST **`./employee/auth`** (驗證 無紀錄)
### POST **`./employee/login`** (登入 有紀錄)

- 驗證成功後回傳 token 期限 至 營業日隔日之04:00
- 登入成功後記錄至 THD `OP_FUNC="1"`
- 參 [Access Token](/rJCLM2LOv)

#### REQUEST
-  **content-type: `x-www-form-urlencoded`**

|KEY|VALUE|DESCRIPTION|
|-|-|-|
|userId|<帳號>|登入帳號 (六碼薪號)|
|userPassword|<密碼>|POS機登入密碼|
|termNo|"0025"|機號|

#### RESPONSE

<table><thead><tr><th>JSON</th><th></th></tr></thead><tbody><tr><td><pre>{
  result: 1,
  message: "驗證成功",
  returnList: {
    "userName":"...",
    "userId":"...", 
    "userLevel":"1",
    "dateSys":"20210512",
    "token": &lt;JWT Access token&gt;
    <span class="obsolete">userinfo:{ <span style="color:#228b22">//to be removed</span>
      "userName":"...",
      "userId":"...", 
      "userLevel":"1",
      "dateSys":"20210512",
      }</span>
  }
}</pre></td><td>驗證成功</td></tr></tbody><tbody><tr><td><pre>{
  result: 2,
  message: "尚未日結",
  returnList: {
    "dateSys":"20210512";
    <span class="obsolete">userinfo:{ <span class="green">//to be removed</span>
      "dateSys":"20210512";
    }</span>
  }
}</pre></td><td>尚未日結</td></tr></tbody><tbody><tr><td><pre>{
  result: 2,
  message: "驗證失敗",
  returnList: {
    "userName":"...",
    "userId":"...", 
    "userLevel":"1",
    "dateSys":"20210512",
     <span class="obsolete">>userinfo:{ <span class="green">//to be removed</span>
      "userName":"...",
      "userId":"...", 
      "userLevel":"1",
      "dateSys":"20210512",
    }</span>
  }
}</pre></td><td>驗證失敗</td></tr></tbody><tbody><tr><td><pre>{
  result: 2,
  message: "帳號錯誤",
  returnList: {
    <span class="obsolete">userinfo:"" <span class="green">//to be removed</span></span>
  }
}</pre></td><td>驗證失敗</td></tr></tbody><tbody><tr><td><pre>{
  result: 2,
  message: "已離職",
  returnList: {
    "userName":"...",
    "userId":"...", 
    "userLevel":"1",
    "dateSys":"20210512",
    <span class="obsolete">userinfo:{ <span class="green">//to be removed</span>
      "userName":"...",
      "userId":"...", 
      "userLevel":"1",
      "dateSys":"20210512",
    }</span>
  }
}</pre></td><td>員工已離職</td></tr></tbody><tbody><tr><td><pre>{
  result: 2,
  message: "其他錯誤",
  returnList: {
      <span class="obsolete">userinfo:"" <span class="green">//to be removed</span></span>
  }
}</pre></td><td>其他錯誤</td></tr></tbody></table>

|KEY|DESCRIPTION|
|-|-|
|userName|使用者名稱|
|userId|使用者登入ID|
|userLevel|"1":店長<br/>"2":組長<br/>"3":收銀員|
|dateSys|營業日(YYYYMMDD)|
|token|Access Token (JWT) (登入成功後產生)|
## 交班
### POST **`./employee/logout`**

- 交班成功後記錄至 THD `OP_FUNC="2"`
- Blacklist token

#### REQUEST
-  **content-type: `x-www-form-urlencoded`**

|KEY | VALUE| DESCRIPTION |
| -|- |-|
|userId|<帳號>||
|termNo|"0025"|機號|

#### RESPONSE
<table><thead><tr><th>JSON</th><th></th></tr></thead><tbody><tr><td><pre>{
  result: 1,
  message: "交班成功",
  returnList: {
    dateSys: "20210512"
  }
}</pre></td><td></td></tr></tbody><tbody><tr><td><pre>{
  result: 2,
  message: "其他錯誤",
  returnList: {
    dateSys: ""
  }
}</pre></td><td></td></tr></tbody><tbody><tr><td><pre>{
  result: 2,
  message: "帳號錯誤",
  returnList: {
    dateSys: ""
  }
}</pre></td><td></td></tr></tbody></table>

|KEY|DESCRIPTION|
|-|-|
|dateSys|營業日(YYYYMMDD)|

## 日結

### POST **`./employee/settlement`**

- 日結成功後記錄至 THD `OP_FUNC="3"`

#### REQUEST
- content-type: ` x-www-form-urlencoded`

|KEY | VALUE| DESCRIPTION |
| -|- |-|
|userId|<帳號>||
|termNo|"0025"|機號|

#### RESPONSE
<table><thead><tr><th>JSON</th><th></th></tr></thead><tbody><tr><td><pre>{
  result: 1,
  message: "日結成功",
  returnList: {
    dateSys: yyyymmdd
  }
}</pre></td><td></td></tr></tbody><tbody><tr><td><pre>{
  result: 2,
  message: "其他錯誤",
  returnList: {
    dateSys: yyyymmdd
  }
}</pre></td><td></td></tr></tbody><tbody><tr><td><pre>{
  result: 2,
  message: "帳號錯誤",
  returnList: {
    dateSys: yyyymmdd
  }
}</pre></td><td></td></tr></tbody></table>

|KEY|DESCRIPTION|
|-|-|
|dateSys|營業日(YYYYMMDD)|


# Payment Router
## 授權

- [mPOS API 與 PR 授權流程](https://hackmd.io/kbtseYEYQ7WD8SCHya1jMA)

### POST **`./pr/payment/`**
- [授權成功/失敗 記錄至 TDL_PAY](https://hackmd.io/@chhuang/SySGFhNQu#prpayment)

#### REQUEST
<table><thead><tr><th>JSON</th></tr></thead><tbody><tr><td><span class="red">* 紅色: 必填欄位</span><pre>{<span class="red">
  "isOTP":"1", 
  "payMethod":"01",
  "orderNumber":"ON9843J23",
  "creditCardNumber":"1234567890123456",
  "expirationDate":"2501",
  "cvc":"123",
  "amount":"12800",
  "installments":"10",
  "redeem":"N",
  "postBackUrl":"",
  "memberID": "",
  "store":"",</span>
  "resultUrl":"",
  "productImageUrl":"",
  "productName":"",
  "authorizedStoreCode":"",
  "terminalCode":""
}</pre></td></tr></tbody></table>

|KEY|TYPE|DESCRIPTION|
|-|-|-|
|isOTP|string|是否OTP交易 (0:不啟用，1:啟用)|
|payMethod|string|交易方式(01:Credit Card / 02:LINE Pay )|
|orderNumber|string|訂單編號|
|creditCardNumber|string|信用卡卡號|
|expirationDate|string|信用卡效期(YYMM)|
|cvc|string|信用卡安全驗證碼|
|amount|string|交易金額|
|installments|string|分期期數|
|redeem|string|啟用紅利|
|postBackUrl|string|指定接續網址(isOTP=1時帶入)|
|memberID|string|會員編號 (用於記錄至TDL_PAY)|
|store|string|店號|
|<span class="obsolete">resultUrl</span>|
|<span class="obsolete">productImageUrl</span>|
|<span class="obsolete">productName</span>|
|<span class="obsolete">authorizedStoreCode</span>|
|<span class="obsolete">terminalCode</span>|





#### RESPONSE

<table><thead><tr><th>JSON</th></tr></thead><tbody><tr><td>

```json
{
  "result": 1,
  "message": "",
  "returnList": {
    "orderNumber":"ON9843J23",
    "paymentGateway":"台新",
    "authorizedStoreCode":"",
    "terminalCode":"",
    "store":"",
    "payKind":"SSL",
    "payMethod":"01",
    "amount":"12800",
    "maskedCardNumber":"1234********3456",
    "approveCode":"098",
    "transactionDate":"20200811",
    "transactionTime":"151101",
    "installmentType":"",
    "installPay":"",
    "installDownPay":"",
    "installPeriod":"",
    "postRedeemPoint":"",
    "postRedeemAmount":"",
    "redeemType":"",
    "redeemAmount":"",
    "redeemPoint":"",
    "hppUrl":""
  }
}
```
</td></tr></tbody></table>

|KEY|TYPE|DESCRIPTION|
|-|-|-|
|orderNumber|string|訂單編號|
|paymentGateway|string|收單行(NCCC/TSPG/TFB)|
|authorizedStoreCode|string|特店號|
|terminalCode|string|終端機號|
|store|string|店號|
|payKind|string|交易類型 (SSL/3D)|
|payMethod|string|交易方式(01:Credit Card / 02:LINE Pay / 99:iPass )|
|amount|string|交易金額|
|maskedCardNumber|string|遮蔽卡號|
|approveCode|string|授權碼|
|transactionDate|string|交易日期|
|transactionTime|string|交易時間|
|installmentType|string|分期手續費計價方式|
|installPay|string|每期金額|
|installDownPay|string|首期金額|
|installPeriod|string|分期期數|
|postRedeemPoint|string|紅利餘額|
|postRedeemAmount|string|紅利實付金額|
|redeemType|string|紅利折抵方式|
|redeemAmount|string|折抵金額|
|redeemPoint|string|折抵點數|
|hppUrl|string|3D驗證網址(isOTP=1時回覆該欄位，需透過該欄位開啟驗證網址)|


## 取消授權
### POST **`./pr/cancel/`**

- [取消授權成功/失敗 記錄至 TDL_PAY](https://hackmd.io/@chhuang/SySGFhNQu#prcancel)

#### REQUEST
<table><thead><tr><th>JSON</th><th>DESCRIPTION</th></tr></thead><tbody><tr><td><pre>{
  "orderNumber":"202102039999990011"
}
</pre></td><td>訂單編號</td></tr></tbody></table>

#### RESPONSE
<table><thead><tr><th>JSON</th><th>DESCRIPTION</th></tr></thead><tbody><tr><td><pre>{
  "result": 1,
  "message": "",
  "returnList": {
    "orderNumber":"202102039999990011"
  }
}</pre></td><td>退授權成功</td></tr></tbody><tbody><tr><td><pre>{
  "result": 2,
  "message": "...",
  "returnList": {
    "orderNumber":"202102039999990011"
  }
}</pre></td><td>退授權失敗</td></tr></tbody></table>

## 查詢交易
### POST **`./pr/query/`**
#### REQUEST

<span class="red">* 紅色: 必填</span>
<table><thead><tr><th>JSON</th><th>DESCRIPTION</th></tr></thead><tbody><tr><td><pre>{
  <span class="red">"queryType":"1",
  "orderNumber":"202102019999990001", </span>
}
</pre></td><td>單一查詢</td></tr></tbody><tbody><tr><td><pre>{
  <span class="red">"queryType":"1",
  "startDate":"20200801", 
  "endDate":"20200811",</span>
  "pageNumber":"1",
  "pageSize":"20"
}
</pre></td><td>日期範圍查詢</td></tr></tbody></table>

|KEY|TYPE|DESCRIPTION|
|-|-|-|
|queryType|string|"1": 收單行 query<br/>"2": DB query|
|orderNumber|string|訂單編號|
|startDate|string|交易時間(起)(yyyymmdd)|
|endDate|string|交易時間(迄)(yyyymmdd)|
|pageNumber|string|頁碼 (Default: "1")|
|pageSize|string|分頁筆數 (Default: "20")|

#### RESPONSE
<table><thead><tr><th>JSON</th></tr></thead> <tbody> <tr><td><h4><code>queryType=="1"</code></h4><pre>{
  "result": 1,
  "message": "",
  "returnList": {
    "totalPage": "",
    "paymentGatewayQueryRespString": "...",
    "transactions": [
      {
        "orderNumber": "202102039999990011",
        "creditcardNumber": "493817******0078",
        "expirationDate": "2812",
        "amount": "1",
        "installments": "0",
        "authorizedStoreCode": "",
        "terminalCode": "70502759",
        "transDate": "20210203",
        "transTime": "154659",
        "transMsg": "成功交易777777",
        "approveCode": "777777",
        "transCode": "00"
      }
    ]
  }
}</pre></td></tr></tbody> <tbody> <tr><td><h4><code>queryType=="2"</code></h4><pre>{
  "result": 1,
  "message": "",
  "returnList": {
    "totalPage": "",
    "currentPage": "",
    "paymentGatewayQueryRespString": "",
    "transactions": [
      {
        "oid": "406",
        "status": "01",
        "isotp": "1",
        "payMethod": "01",
        "orderNumber": "202102039999990011",
        "creditcardNumber": "493817******00078",
        "expirationDate": "2812",
        "cvc": "5**",
        "amount": "1",
        "installments": "0",
        "redeem": "N",
        "productImageUrl": "",
        "productName": "",
        "postbackUrl": "...",
        "resultUrl": "",
        "authorizedStoreCode": "6600800020",
        "terminalCode": "70502759",
        "store": "",
        "transDate": "",
        "transTime": "",
        "transMsg": "",
        "approveCode": "",
        "transCode": "",
        "transactionID": "",
        "transactionNumber": "5a02d336-d7ad-4c42-94b7-f7330911a411",
        "paymentGatewayOid": "8",
        "requestData": "...",
        "responseData": "...",
        "paymentRuleOid": "11",
        "version": "1",
        "createTime": "2021-02-03T15:46:03.202276+08:00",
        "creator": "...",
        "updateTime": "2021-02-03T15:46:03.461236+08:00",
        "modifier": "..."
      }
    ]
  }
}</pre></td></tr></tbody></table>

- returnList
  |KEY|DESCRIPTION|
  |-|-|
  |totalPage|總頁數|
  |currentPage|當前頁數|
  |paymentGatewayQueryRespString|收單行查詢回應字串|
  |transactions|交易清單|
  
  - transactions
    |KEY|DESCRIPTION|
    |-|-|
    |status|交易狀態|
    |isotp|是否OTP交易|
    |payMethod|交易方式 (01:CreditCard/ 02:LINEPay / 99:iPass )|
    |orderNumber|訂單編號|
    |creditcardNumber|信用卡卡號|
    |expirationDate|信用卡效期|
    |cvc|信用卡安全驗證碼|
    |amount|交易金額|
    |installments|分期期數|
    |redeem|啟用紅利|
    |productImageUrl|商品縮圖網址|
    |productName|商品名稱|
    |postbackUrl|指定接續網址|
    |resultUrl|後台交易結果通知網址|
    |authorizedStoreCode|特店號|
    |terminalCode|終端機號|
    |store|店號|
    |transDate|交易日期|
    |transTime|交易時間|
    |transMsg|交易訊息|
    |approveCode |授權碼|
    |transCode|銀行交易代碼|
    |transactionID|交易ID|
    |transactionNumber|交易識別碼|
    |paymentGatewayOid|收單行|
    |requestData|請求資料|
    |responseData|回覆資料|
    |callbackData|Callback資料|
    |paymentRuleTrace|規則判斷軌跡|
    |paymentRuleOid|付款規則|
    |version|版本|
    |createTime|建立時間|
    |creator|建立者|
    |updateTime|更新時間|
    |modifier|修改者|


## 查詢信用卡所屬銀行
### POST **`./pr/creditCardIssuer/`**
#### REQUEST
<table><thead><tr><th>JSON</th><th>DESCRIPTION</th></tr></thead><tbody><tr><td><pre><code>{
  "creditCardNumber":"4938170130000078"
}
</code></pre></td><td>信用卡號</td></tr></tbody></table>

#### RESPONSE
<table><thead><tr><th>JSON</th><th>DESCRIPTION</th></tr></thead><tbody><tr><td><pre lang="javascript">{
  "result": 1,
  "message": "",
  "returnList": {
    "bankID": "812",
    "bankName": "台新銀行"
  }
}</pre></td><td>OK</td></tr></tbody><tbody><tr><td><pre>{
  "result": 2,
  "message": "F005 查無發卡銀行資料",
  "returnList": {}
}</pre></td><td></td></tr></tbody></table>

---
# DailyAccount 讀帳
## 讀帳
### GET **`./transaction/dailyAccount/{termNo}`**

|PATHPARAM|DESCRIPTION|
|-|-|
|termNo|機號|


#### RESPONSE

<table>
   <thead><tr><th>JSON</th><th></th></tr></thead>
   <tbody>
      <tr><td>
<pre>{
  "result": 1,
  "message": "",
  "returnList": {
    "changes": 0,
    "drawerCash": 0,
    <del>"safeFund": 0,</del> <span class="green">//保留, 暫無用</span> 
    <del>"reserveFund": 0,</del> <span class="green">//保留, 暫無用</span> 
    "elecInvoiceAccount": {
      <del>"reservedCouponAmt": 0,</del> <span class="green">//保留, 暫無用</span> 
      "sponsorAmt": 0, <span class="green">// ecPaymentAmt</span>
      "discountAmt": 0,
      "linePayAmt": 0,
      "TKGoodsAmt": 0,
      "shoppingAmt": 0,
      "bankPointsAmt": 0,
      "excessAmt": 0,
      "pointsAMT": 0,
      "termPayIntRateAmt": 0,
      "oldGoodsAmt": 0,
      "otherGoodsAmt": 0,
      "FBAmt": 0,
      "invoiceRewAmt": 0,
      "subtotal": 238,
      "creditCardAmt": 0,
      "PGAmt": 0,
      "creditAmt": 238,
      "cash": 0
    },
    "collectionAccount": {
      <del>"reservedCouponAmt": 0,</del> <span class="green">//保留, 暫無用</span> 
      "sponsorAmt": 0, <span class="green">// ecPaymentAmt</span>
      "discountAmt": 0,
      "linePayAmt": 0,
      "TKGoodsAmt": 0,
      "shoppingAmt": 0,
      "bankPointsAmt": 0,
      "excessAmt": 0,
      "pointsAMT": 0,
      "termPayIntRateAmt": 0,
      "oldGoodsAmt": 0,
      "otherGoodsAmt": 0,
      "FBAmt": 0,
      "invoiceRewAmt": 0,
      "subtotal": 0,
      "creditCardAmt": 0,
      "PGAmt": 0,
      "creditAmt": 0,
      "cash": 0
    }
  }
}</pre>
</td><td></td>
      </tr>
   </tbody>
</table>




---

# SerialNo 交易序號

## 取得最新 交易序號 

### GET **`./transaction/currentSerial`**
- 取得所有機台最新交易序號
### GET **`./transaction/currentSerial?termNo={termNo}`**
- 取得單一機台最新交易序號

|QUERYPARAM|DESCRIPTION|
|-|-|
|termNo|機號|

#### RESPONSE

<table>
   <thead><tr><th>JSON</th> <th>DESCRIPTION</th></tr></thead>
   <tbody>
      <tr><td>
<pre>{
  "result": 1,
  "message": "",
  "returnList": [
    ...
    {
      "termNo": "0025",
      "serialNo": "03294"
    },
    {
      "termNo": "0027",
      "serialNo": "00078"
    },
    ...
  ]
}</pre>
</td>
         <td>所有機台 最新(已使用)交易序號</td>
      </tr>
   </tbody>
   <tbody>
      <tr><td>
<pre>{
  "result": 1,
  "message": "",
  "returnList": {
    "termNo": "0025",
    "serialNo": "03294"
  }
}</pre>

</td>
         <td>單一機台 最新(已使用)交易序號(termNo 有值)</td>
      </tr>
   </tbody>
   <tbody>
      <tr><td>
<pre>{
  "result": 2,
  "message": "機號錯誤",
  "returnList": {
    "termNo": &lt;termNo&gt;
  }
}</pre>
</td>
         <td>機號錯誤</td>
      </tr>
   </tbody>
</table>

| KEY| DESCRIPTION |
|-|-|
| termNo | 機號 |
| serialNo | 最新已使用 交易序號 |




---

# Invoice 發票
## 取得 發票號碼

- 從 INVOICE_H & INVOICE_D 取得發票設定
- 從 THD 取得最後使用發票號碼
- 判斷下一個可使用發票號碼

### GET **`./invoice/{termNo}`**

|PATHPARAM|DESCRIPTION|
|-|-|
|termNo|機號|

#### RESPONSE
<table>
   <thead><tr><th>JSON</th> <th>DESCRIPTION</th></tr></thead>
      <tbody>
      <tr><td>
      
```json
{
  "result": 1
  "message": "",
  "returnList": {
    "source": "SC",
    "termNo": "0025",
    "invoiceNo": "KS70560010",
    "remainInvoiceNo": 9989,
    "partNo": 1 //1,2
    "leadingLetters": "KS",
    "trailingNumbers": "70560010",
  }
}
```
</td>
         <td></td>
      </tr>
   </tbody>
         <tbody>
      <tr><td>
<pre>{
  "result": 3,
  "message": "機號無發票設定",
  "returnList": null
}</pre>
</td>
         <td>termNo(機號) INVOICE_H/_D裡沒有設定</td>
      </tr>
   </tbody>
         <tbody>
      <tr><td>
      
```json
{
  "result": 4
  "message": "發票號碼已用完，請通知相關單位處理",
  "returnList": {
    "source": "SC",
    "termNo": "0025",
    "invoiceNo": "...",
    "remainInvoiceNo": -1,
    "partNo": 1 //1,2
    "leadingLetters": "...",
    "trailingNumbers": "...",
  }
}
```
</td>
         <td>remainInvoiceNo &lt; 0</td>
      </tr>
   </tbody>
</table>

|KEY|DESCRIPTION|
|-|-|
|source|資料來源 (SC / ERP)|
|termNo|機號|
|invoiceNo|發票號碼|
|remainInvoiceNo|剩餘可用發票號碼數量|
|partNo|發票段號|
|leadingLetters|發票字母|
|trailingNumbers|發票號碼數字|


---
# Repair 維修單
## 取得 維修單

- TKPM0B 取得維修單號
- PRODUCT 取得 維修費用選項 (PRODUCT.SAL_TYPE == 4)

### GET **`./repair/{repairNo}`**

| PATHPARAM| DESCRIPTION |
| -------- | -------- |
| repairNo | 維修單號 |

#### RESPONSE
<table><thead><tr><th>JSON</th></tr></thead><tbody><tr><td>

```json
{
  "result":1,
  "message":"",
  "returnList":{
    "repairNo":null // 維修單 (null->維修單不存在)
    "amt":0,        // 金額
    "types":[       // 維修貨號
      {
        "pluNo":"029251",
        "pluName":"1C維修收入"
        "barcode2":"2955060100499",
        "barcode1":null,
        "pluSpec":"1C維修收入",
        "measureWord":"個",
        "direct":"N",
        "price":1,
        "vipPrice":1,
        "minPrice":0,
        "fbAmount":0,
        "validYear":3,
        "salType":"4",
        "attrib":null,
        "noDupItem":null,        
      },
      ...
    ]
  }
}
```

</td></tr></tbody></table>

|KEY|TYPE|DESCRIPTION|
|-|-|-|
|repairNo|string|維修單號<br/>(null 維修單不存在)|
|amt|integer|金額|
|types\[\]|object[]|維修貨號商品|
- types (參 [Product Model](https://hackmd.io/@chhuang/Hk4pnBrP_#Product))
  |KEY|TYPE|DESCRIPTION|
  |-|-|-|
  |pluNo|string|商品代號|
  |pluName|string|商品名稱|
  |barcode1|string|商品條碼 (國際碼)|
  |barcode2|string|商品條碼 (店內碼)|
  |pluSpec|string|商品規格(型號)|
  |measureWord|string|單位名稱|
  |direct|string|廠商指送(Y/N)|
  |price|integer|市價|
  |vipPrice|integer|會員價|
  |minPrice|integer|最低價|
  |fbAmount|integer|還元金金額|
  |validYear|integer|商品保固年限|
  |salType|string|"4": 維修費用|
  |attrib|string|"U": USIM卡貨號<br/>"S": 延保外加貨號|
  |noDupItem|string|null: 無限制</br>"1": 1筆交易只能賣一次|



---

# Transaction 交易

## 正常交易 / 結帳



- 檢查交易金額
  - `$0 <= 總金額 < $9,999,999`
  - `總金額==單品項加總金額`
- 交易成功後 自動產生新發票號碼並列印發票 and/or 收據
- 交易結果寫入 THD/TDL `OP_FUNC="4"`

### POST **`./transaction`**

#### REQUEST



<table><thead><tr><th>JSON</th><th>DESCRIPTION</th></tr></thead><tbody><tr><td>

|Transaction Model|
|-|
|[&lt;Transaction Model&gt;](https://hackmd.io/@chhuang/Hk4pnBrP_#Transaction-Model)|
<span class="red">* 紅色: 必填</span>
<pre>{  
  <span class="red">"printerNo": &lt;"0" or "2"&gt; ,
  "termNo": &lt;string&gt;,
  "opFunc": &lt;"4" or "P"&gt;,</span>
  "storeNo": "", <span class="green">/*</span>
  "ipAddr": "",<span class="green">   *</span>
  "seqNo": "",<span class="green">    * 後端自動補</span>
  "serialNo": "",<span class="green"> *</span>
  "timeT": "",<span class="green">    *</span>
  "dateSys": "",<span class="green">  *</span>
  "dateT": "",<span class="green">    */</span>
  "header": {
    <span class="red">"cashierNo": &lt;string&gt;,
    "sellerNo": &lt;string&gt;,
    "bossNo": &lt;string&gt;,
    "deliverNo": &lt;string&gt;,
    "repairNo": &lt;string&gt;, <span class="green">// 維修結帳使用</span>
    "opFuncSub": &lt;string&gt;,</span> <span class="green">// ""(正常交易/配達起單), "DLV_ACC"(配達結帳), "MTN_ACC"(維修單結帳), "DYOI_ALL"(代收)</span>
    "FETCNo": "", 
    "templateNo": "",
    "poNo": "",
    "diyID": "",
    "itemQty": 0, <span class="green">  /* 後端自動補</span>
    "apVersion": "", <span class="green">*/</span>
    "customer": {
      <span class="red">"memberID": &lt;string&gt;,
      "memberTel": &lt;string&gt;,</span>
      "abnormalMember": "",
      "customerCount": 0,
      "customerValid": "",
      "guestId": "",
      "memberUnregister": "",
      "membercode": ""
    },
    "payment": {
      <span class="red">"subtotal": &lt;integer&gt;,
      "cash": &lt;integer&gt;,
      "FBAmt": &lt;integer&gt;,
      "creditAmt": &lt;integer&gt;,
      "PGAmt": &lt;integer&gt;,
      "TKGoodsAmt": &lt;integer&gt;,
      "bankPointsAmt": &lt;integer&gt;,
      "discountAmt": &lt;integer&gt;,
      "excessAmt": &lt;integer&gt;,
      "invoiceRewAmt": &lt;integer&gt;,
      "oldGoodsAmt": &lt;integer&gt;,
      "otherGoodsAmt": &lt;integer&gt;,
      "pointsAmt": &lt;integer&gt;, 
      "ecPaymentAmt": &lt;integer&gt;, <span class="green">// New 20210126 </span>
      "shoppingAmt": &lt;integer&gt;,
      <del>"sponsorAmt": &lt;integer&gt;,</del> <span class="green">// Removed 20210126 </span>
      "promotionDiscountAmount": &lt;integer&gt;,
      "totalDiscountAmount": &lt;integer&gt;,
      "cashChange": &lt;integer&gt;,
      "pincode": &lt;string&gt;,</span>
      "debit":  &lt;integer&gt;,
      "couponChange": 0,
      "reservedAMT1": 0,
      "reservedAMT2": 0,
      "reservedCouponAmt": 0,
      "creditCard": {
        <span class="red">"creditCardAmt": &lt;integer&gt;,
        "creditCardNo": &lt;string&gt;,
        "approveCode":"777777", <span class="green">// 20210203 added 信用卡授權碼</span>
        "bankNo": &lt;string&gt;,
        "cardType": &lt;cardstringType&gt;,
        "installmentFlag": &lt;string&gt;,
        "installmentID": &lt;string&gt;,
        "installmentNumber": &lt;integer&gt;,
        "installmentName": &lt;string&gt;,
        "termPayIntRateAmt": &lt;integer&gt;,
        "bankOrderNo": &lt;string&gt;,</span>
        "creditCardConnectStatus": "",
        "unionPayFlag": "",
        "EDC": ""
      },
      "linePay": {
        <span class="red">"linePayAmt": &lt;integer&gt;,</span>
        "lineCreditCardAmt": 0,
        "lineDiscountAmt": 0,
        "lineOtherAmt": 0,
        "linePayOrder": "",
        "linePointAmt": 0,
        "lineiPASSAmt": 0,
      },
    },
    <span class="red">"receipt": {
      "tax": &lt;integer&gt;,
      "printReceipt": &lt;"Y" or "N"&gt;,
      "donateReceipt": &lt;"Y" or "N"&gt; Y/N,
      "GUINo": &lt;string&gt;,
      "commCode": &lt;string&gt;,
      "heartCode": &lt;string&gt;,
      "MOICANo": &lt;string&gt;,
      "passportNo": &lt;string&gt;,</span>
      "claimReceiptLotteryNo": "",
      "netSale": 0,
      "random": "",
      "receiptAmt": 0,
      "receiptCounter": 0,
      "receiptNo": "",
      "receiptType": "",
      "taxFreeReceiptCounter": 0,
      "taxFreeReceiptNo": "",
      "zeroTaxFlag": ""
    },
    "void": {...}
  },
  <span class="red">"data": [
    {
      "detailID": &lt;"001", "002", "003", ...&gt;,
      "inputType": &lt;"K" or "S"&gt;,
      "detailCode": &lt;"R" or "M" or "O"&gt;,
      "pluNo": &lt;string&gt;,
      "pluSpec": &lt;string&gt;,
      "name": &lt;string&gt;,
      "mmType": &lt;"N" or "F" or "B" or "T"&gt;,
      "priceType": &lt;"N" or "D"&gt;,
      "promoteID": &lt;string&gt;,
      "groupNo": &lt;string&gt;,
      "quantity": &lt;integer&gt;,
      "salesPromotionQuantity": &lt;integer&gt;,
      "storeBounds": &lt;integer&gt;,
      "taxFreeFlag": &lt;string&gt;,
      "barcodeNo": &lt;string&gt;,
      "collectNo": &lt;string&gt;,
      "keyinSeq1":&lt;string&gt;, <span class="green">// 20210219 added</span>
      "keyinSeq3":&lt;string&gt;, <span class="green">// 20210219 added</span>
      "barcode1": &lt;string&gt;,
      "barcode2": &lt;string&gt;,
      "barcode3": &lt;string&gt;,</span>
      <del>"mmNo": "",
      "vendorNo": "",
      "productCategoryNo": "",
      "pluSerialNo": "",</del> <span class="green">// 20210219 removed</span>
      <del>"cardNo": &lt;cardNo&gt;,</del><span class="green">// 20210219 removed</span>
      <span class="red">"price": {
        "normalAmt": &lt;integer&gt;,
        "taxIncludeAmt": &lt;integer&gt;,
        "qtyTaxAmt": &lt;integer&gt;,
        "salesPromotionAmt": &lt;integer&gt;,
        "mmShareDiscountAmt": &lt;integer&gt;,</span>
        "couponShareDiscountAmt": 0,
        "excessShareAmt": 0,
        "netSale": 0
      },
      <span class="red">"refund": {
        "priceChangeFlag": &lt;"" or "1"&gt;,
        "reasonNo": &lt;string&gt;,
        "competitorAmt": &lt;integer&gt;,
        "competitorNo": &lt;string&gt;,</span>
        "refunderID": "",
        "unitRefundReasonNo": ""
      },
      <span class="red">"warranty": {
        "warrantyPluNo": &lt;string&gt;,
        "warrantyPluSeq": &lt;string&gt;,
        "warrantyAccNo": &lt;string&gt;</span>
      }
    }
  ]
}
</pre></td><td></td></tr></tbody></table>

#### RESPONSE



<table>
   <thead><tr><th>JSON</th> <th>DESCRIPTION</th> </tr></thead>
   <tbody>
      <tr><td>
      
|Receipt Model|
|-|
|[&lt;Receipt Model&gt;](https://hackmd.io/@chhuang/BycnYBz5w)|
      
<pre>{
  "result": 1,
  "message": "",
  "returnList": {
    "dateT": "20210423",
    "serialNo": "03292",
    "deliverNo": "7052512823001",
    "receipt": { <span class="green">// 參 Receipt model</span>
      ...,
      "seller":{
        ...
      },
      "buyer": {
        ...
      },
      "payments":[
        ...
      ],
      "items":[
        ...
      ]
    },
    <span class="obsolete">"transactionStatus": true, <span class="green">// to be removed //</span>
    "message": ""</span>
  }
}</pre>
</td><td>交易成功</td>
      </tr>
   </tbody>
   <tbody>
      <tr><td>
<pre>{
  "result": 2,
  "message": "其他錯誤",
  "returnList": {
    "dateT": "",
    "serialNo": "",
    "deliverNo": "",
    "receipt": {...},
    <span class="obsolete">"transactionStatus": true, <span class="green">// to be removed //</span>
    "message": ""</span>
  }
}</pre>
</td>
         <td></td>
      </tr>
   </tbody>
   <tbody>
      <tr><td>
<pre>{
  "result": 2,
  "message": "無機號或收銀員編號傳入",
  "returnList": {...}
}</pre>
</td>
         <td></td>
      </tr>
   </tbody>
   <tbody>
      <tr><td>
<pre>{
  "result": 2,
  "message": "資料解析錯誤",
  "returnList": {...}
}</pre>
</td><td>JSON 錯誤</td>
      </tr>
   </tbody>
   <tbody>
      <tr><td>
<pre>{
  "result": 3,
  "message": "資料庫錯誤",
  "returnList": {...}
}</pre>
</td>
         <td></td>
      </tr>
   </tbody>
   <tbody>
      <tr><td>
<pre>{
  "result": 2,
  "message": "商品數量超過限制",
  "returnList": {...}
}</pre>
</td>
         <td></td>
      </tr>
   </tbody>
   <tbody>
      <tr><td>
<pre>{
  "result": 2,
  "message": "金額超出範圍",
  "returnList": {...}
}</pre>
</td>
         <td></td>
      </tr>
   </tbody>
   <tbody>
      <tr><td>
<pre>{
  "result": 2,
  "message": "付款別錯誤",
  "returnList": {...}
}</pre>
</td>
         <td></td>
      </tr>
   </tbody>
   <tbody>
      <tr><td>
<pre>{
  "result": 2,
  "message": "發票號碼錯誤",
  "returnList": {...}
}</pre>
</td>
         <td></td>
      </tr>
   </tbody>
   <tbody>
      <tr><td>
<pre>{
  "result": 2,
  "message": "交易未成立 印表機離線",
  "returnList": {...}
}</pre>
</td>
         <td>列印發票前<br/>印表機無回應</td>
      </tr>
   </tbody>
   <tbody>
      <tr><td>
<pre>{
  "result": 2,
  "message": "交易未成立 發票列印錯誤",
  "returnList": {...}
}</pre>
</td>
         <td>列印發票後<br/>印表機異常</td>
      </tr>
   </tbody>
   <tbody>
      <tr><td>
<pre>{
  "result": 2,
  "message": "促代碼錯誤",
  "returnList": {...}
}</pre>
</td>
         <td></td>
      </tr>
   </tbody>
  <tbody>
      <tr><td>
<pre>{
  "result": 2,
  "message": "品項金額加總錯誤",
  "returnList": {...}
}</pre>
</td>
         <td></td>
      </tr>
   </tbody>
   <tbody>
      <tr><td>
<pre>{
  "result": 2,
  "message": "單品項稅額加總錯誤",
  "returnList": {...}
}</pre>
</td>
         <td></td>
      </tr>
   </tbody>
   <tbody>
      <tr><td>
<pre>{
  "result": 2,
  "message": "折扣額不符",
  "returnList": {...}
}</pre>
</td>
         <td></td>
      </tr>
   </tbody>
</table>

|KEY|DESCRIPTION|
|-|-|
|dateT|交易日期之營業日|
|serialNo|交易序號|
|deliverNo|配達單號|
|receipt|發票號碼|

## 正常交易 (Dry Run)

- 交易 Dry Run
  - 交易結果 **不會** 寫入 THD/TDL
  - 不會進行發票列印

### POST **`./transaction/dry`**

- Request / Response Json 同 [`POST ./transaction`](#POST-transaction) 

#### REQUEST

[`POST ./transaction`](#POST-transaction)`#REQUEST`

#### RESPONSE

[`POST ./transaction`](#POST-transaction)`#RESPONSE`

## 退換貨 - 取得交易資料

### GET **`./transaction/checkvoid/{termNo}/{serialNo}`**

| PATHPARAM| DESCRIPTION |
| -------- | -------- |
| termNo | 機號 |
| serialNo | 交易序號 |

#### RESPONSE
<table>
   <thead><tr><th>JSON</th> <th>DESCRIPTION</th></tr></thead>
   <tbody>
      <tr><td>
      

<pre>{
  "result": 1,
  "message": "",
  "returnList": {
    transactionData: {...}, <span class="green">// Trasaction Model</span>
    returnReasonList: [...
      <span class="green">// &lt;reason JSON&gt; </span>
      { 
          reasonName: &lt;string&gt;,
          reasonID: &lt;string&gt;,
          reasonType: &lt;string&gt; 
      },
      ...
    ],
    <span class="obsolete">status: 1, <span class="green">// to be removed //</span>
    msg: ""</span>
  }
}</pre>
</td>
         <td>交易可銷退</td>
      </tr>
   </tbody>
   <tbody>
      <tr><td>
<pre>{
  "result": 2,
  "message": "交易已銷退",
  "returnList": {
    <span class="obsolete">status: 2, <span class="green">// to be removed //</span>
    msg: "交易已銷退"</span>
  }
}</pre>
</td>
         <td>交易已銷退</td>
      </tr>
   </tbody>
   <tbody>
      <tr><td>
<pre>{
  "result": 2,
  "message": "資料解析錯誤",
  "returnList": {
    <span class="obsolete">status: 2, <span class="green">// to be removed //</span>
    msg: "資料解析錯誤"</span>
  }
}</pre>
</td>
         <td>JSON 錯誤</td>
      </tr>
   </tbody>
   <tbody>
      <tr><td>
<pre>{
  "result": 3,
  "message": "資料庫錯誤",
  "returnList": {
    <span class="obsolete">status: 3, <span class="green">// to be removed //</span>
    msg: "資料庫錯誤"</span>
  }
}</pre>
</td>
         <td></td>
      </tr>
   </tbody>
</table>

|KEY|DESCRIPTION|
|-|-|
|transactionData|[&lt;Transaction Model&gt;](https://hackmd.io/@chhuang/Hk4pnBrP_#Transaction-Model)|
|returnReasonList\[\]|[&lt;Reason Model&gt;](https://hackmd.io/@chhuang/Hk4pnBrP_#Reason-Model)|


## 退換貨 - 確認銷退
### POST **`./transaction/void`**

#### REQUEST

- 除了`Transaction.header.refundReasonNo`需填以外，剩餘欄位原封不動

<table><thead><tr><th>JSON</th><th>DESCRIPTION</th></tr></thead><tbody><tr><td>
   
|Transaction Model|
|-|
|[&lt;Transaction Model&gt;](https://hackmd.io/@chhuang/Hk4pnBrP_#Transaction-Model)|
   <span class="red">* 必填</span>
<pre>{
  "opFunc": "8",
  ...
  "header": {
    <span class="red">"refundReasonNo": &lt;string&gt;</span>,
    ...
  },
  ...
}</pre>
   </td><td>
   
   - Transaction Model 自 `./transaction/checkvoid/` 得到的 `transactionData`
   - refundReasonNo 自 `./transaction/checkvoid/` 得到的 `returnReasonList.reasonID`
   </td></tr></tbody>
</table>


#### RESPONSE
<table><thead><tr><th>JSON</th><th>DESCRIPTION</th></tr></thead><tbody><tr><td><pre>{
  "result": 1,
  "message": "銷退成功",
  "returnList": {
    <span class="obsolete">"status": 1, <span class="green">// to be removed //</span>
    "msg": "銷退成功"</span>
  }
}</pre></td><td>銷退成功</td></tr></tbody><tbody><tr><td><pre>{
  "result": 2,
  "message": "交易已消退",
  "returnList": {
    <span class="obsolete">"status": 2, <span class="green">// to be removed //</span>
    "msg": "交易已消退"</span>
  }
}</pre></td><td>交易已消退</td></tr></tbody><tbody><tr><td><pre>{
  "result": 2,
  "message": "未填正確退貨原因",
  "returnList": {
    <span class="obsolete">"status": 2, <span class="green">// to be removed //</span>
    "msg": "未填正確退貨原因"</span>
  }
}</pre></td><td>錯誤 reasonNo</td></tr></tbody><tbody><tr><td><pre>{
  "result": 2,
  "message": "無機號或員編傳入",
  "returnList": {
    <span class="obsolete">"status": 2, <span class="green">// to be removed //</span>
    "msg": "無機號或員編傳入"</span>
  }
}</pre></td><td></td></tr></tbody><tbody><tr><td><pre>{
  "result": 2,
  "message": "資料解析錯誤",
  "returnList": {
    <span class="obsolete">"status": 2, <span class="green">// to be removed //</span>
    "msg": "資料解析錯誤"</span>
  }
}</pre></td><td>JSON 錯誤</td></tr></tbody><tbody><tr><td><pre>{
  "result": 3,
  "message": "資料庫錯誤",
  "returnList": {
    <span class="obsolete">"status": 3, <span class="green">// to be removed //</span>
    "msg": "資料庫錯誤"</span>
  }
}</pre></td><td></td></tr></tbody></table>

----

## 交易取消
### POST **`./transaction/cancel`**
#### REQUEST

- 除了以下必填以外，剩餘欄位照原銷售交易欄位填上

<span class="red">* 必填</span>
<table>
<thead>
<tr><th>JSON</th> <th></th></tr>
</thead>
<tbody>
<tr>
<td>

|Transaction Model|
|-|
|[&lt;Transaction Model&gt;](https://hackmd.io/@chhuang/Hk4pnBrP_#Transaction-Model)|
<pre>{  
  <span class="red">"termNo": &lt;string&gt;,</span>
  "opFunc": "5",
  ...
  "header": {
    <span class="red">"cashierNo": &lt;string&gt;,
    "sellerNo": &lt;string&gt;,
    "bossNo": &lt;string&gt;</span>,
    ...
  },
  ...
}
</pre></td>
<td></td>
</tr>
</tbody>
</table>

#### RESPONSE
<table><thead><tr><th>JSON</th><th>DESCRIPTION</th></tr></thead><tbody><tr><td><pre>{
  "result": 1,
  "message": "交易取消",
  "returnList": null
}</pre></td><td>OK</td></tr></tbody><tbody><tr><td><pre>{
  "result": 2,
  "message": "無機號或員編傳入",
  "returnList": null
}</pre></td><td></td></tr></tbody><tbody><tr><td><pre>{
  "result": 2,
  "message": "資料解析錯誤",
  "returnList": null
}</pre></td><td>JSON 錯誤</td></tr></tbody><tbody><tr><td><pre>{
  "result": 3,
  "message": "資料庫錯誤",
  "returnList": null
}
</pre></td><td></td></tr></tbody></table>

----
# SO 配達 / 轉POS機結帳


## 配達單號 deliverNo

### GET **`./transaction/deliverNo/{termNo}`**

- 取得最新可用配達單號

| PATHPARAM| DESCRIPTION |
| -------- | -------- |
| termNo | 機號 |


#### RESPONSE
<table><thead><tr><th>JSON</th><th></th></tr></thead><tbody><tr><td><pre>{
  "result": 1,
  "message": "",
  "returnList": {
    "deliverNo": &lt;deliverNo&gt;
    "receipt": {...}
  }
}</pre></td><td></td></tr></tbody></table>

| KEY| DESCRIPTION |
| -------- | -------- |
| deliverNo | 配達單號 |


## 取得 未結帳 配達交易資料
### GET **`./transaction/so/{dlvNo}`**

#### RESPONSE

<table><thead><tr><th>JSON</th><th></th></tr></thead><tbody><tr><td>

|Transaction Model|
|-|
|[&lt;Transaction Model&gt;](https://hackmd.io/@chhuang/Hk4pnBrP_#Transaction-Model)|
<span class="blue">* 重要欄位</span>
<pre>{
  "result": 1,
  "message": "",
  "returnList": {
    ...
    <span class="blue">"isPaid": "N", <span class="green">// OD10_PAY_FLAG</span>
    "allowMoreItems": "", <span class="green">// ACCEPT_PLU_INPUT ("" or "1")</span> </span>
    ...
    "header": {
      ...
      <span class="blue">"payment"</span>: {
        ...
        <span class="blue">"ecPaymentAmt": 0, <span class="green"> // COUPON02_AMT 網銷信用卡</span>
        "pointsAmt": 0,<span class="green"> // COUPON03_AMT 網銷購物金</span>
        "debit": 9999999,<span class="green"> // OD10_DEBIT 可賒帳金額</span></span>
        ...
      },
      ...
    },
    "data": [ ... ]
  }
}</pre></td><td></td></tr></tbody></table>

## 起 SO 單 (後台起單 / 轉POS機結帳)
### POST **`./transaction/so`**
#### REQUEST
- 除了以下必填以外，剩餘欄位可忽略

<table><thead><th>JSON</th><th></th></thead><tbody><tr>
<td>

|Transaction Model|
|-|
|[&lt;Transaction Model&gt;](https://hackmd.io/@chhuang/Hk4pnBrP_#Transaction-Model)|
<span class="red">* 必填欄位</span>
<pre>
{
  <span class="red">"expiryDate": &lt;string&gt;</span> or <span class="red">null, <span class="green">// "YYYYMMDD"</span> 
  "termNo": &lt;string&gt;</span>,
  "opFunc": "F",
  ...
  <span class="red">"header": {
    "cashierNo": &lt;string&gt;,
    "sellerNo": &lt;string&gt;,</span>
    ...
    <span class="red">"customer": {
      "memberID": &lt;string&gt;,
      "name": &lt;string&gt;, <span class="green">// default ""</span>
      "landline": &lt;string&gt;, <span class="green">// default ""</span>
      "mobile": &lt;string&gt;, <span class="green">// default ""</span>
      "address": &lt;string&gt;, <span class="green">// default ""</span>
      "address2": &lt;string&gt;, <span class="green">// default ""</span></span>
      <span style="color:darkred">"memberTel": &lt;string&gt;</span>, <span class="green">// ? not sure</span>
      ...
    },
   <span class="red"> "payment": {
      "subtotal": &lt;integer&gt;,</span>
      "promotionDiscountAmount": &lt;integer&gt;, <span class="green">// ? not sure</span>
      "totalDiscountAmount": &lt;integer&gt;, <span class="green">// ? not sure</span>
      ...
      <span class="red">"creditCard": { <span class="green">// 如果有選擇分期</span>
        "bankNo": &lt;string&gt;,
        "installmentID": &lt;string&gt;,
        "installmentNumber": &lt;integer&gt;,
        "termPayIntRateAmt": &lt;integer&gt;,</span>
        ...
      },
      ...
    },
    <span class="red">"receipt": {
      "GUINo": &lt;string&gt;,
      "MOICANo": &lt;string&gt;,
      "commCode": &lt;string&gt;,
      "heartCode": &lt;string&gt;,
      "passportNo": &lt;string&gt;,</span>
      ...
    },
    ...
  },
  "data": [
    {
      <span class="red">"detailID": &lt;string&gt;,
      "pluNo": &lt;string&gt;,
      "pluSpec": &lt;string&gt;,
      "mmType": &lt;string&gt;,
      "name":  &lt;string&gt;,
      "promoteID":  &lt;string&gt;,
      "quantity": &lt;integer&gt;,
      "storeBounds": &lt;integer&gt;,
      "salesPromotionQuantity": &lt;integer&gt;,
      "taxFreeFlag": &lt;string&gt;,
      "inputType": &lt;string&gt;,
      "priceType": &lt;string&gt;,
      "groupNo": &lt;string&gt;,
      "keyinSeq1": "",
      "keyinSeq3": "",
      "barcodeNo": "",</span>
      "barcode1": "",
      "barcode2": "",
      "barcode3": "",
      "collectNo": "",
      "detailCode": "",
      "mmNo": "",
      "productCategoryNo": "",
      "vendorNo": "",
      <span class="red">"price": {
        "qtyTaxAmt": &lt;integer&gt;,
        "normalAmt": &lt;integer&gt;,
        "taxIncludeAmt": &lt;integer&gt;,
        "couponShareDiscountAmt": &lt;integer&gt;,
        "excessShareAmt": &lt;integer&gt;,
        "mmShareDiscountAmt": &lt;integer&gt;,
        "salesPromotionAmt": &lt;integer&gt;</span>
        ...
      },
      ...
    }
  ]
}
</pre></td><td></td></tr></tbody></table>


#### RESPONSE

<table>
   <thead><tr><th>JSON</th> <th>DESCRIPTION</th></tr></thead>
   <tbody>
      <tr><td>
      
|Receipt Model|
|-|
|[&lt;Receipt Model&gt;](https://hackmd.io/@chhuang/BycnYBz5w)|
<pre>{
  "result": 1,
  "message": "",
  "returnList": {
    "deliverNo": &lt;配達單號&gt;,
    "receipt": { <span class="green">// 參 Receipt model</span>
      ...,
      "seller":{
        ...
      },
      "buyer": {
        ...
      },
      "payments":[
        ...
      ],
      "items":[
        ...
      ]
    },
  }
}</pre>
</td>
         <td></td>
      </tr>
   </tbody>
   <tbody>
      <tr><td>
<pre>{
  "result": 2,
  "message": "其他錯誤",
  "returnList": {
    "deliverNo": &lt;配達單號&gt;,
    "receipt": {...}
  }
}</pre>
</td>
         <td></td>
      </tr>
   </tbody>
   <tbody>
      <tr><td>
<pre>{
  "result": 2,
  "message": "無機號或收銀員編號傳入",
  "returnList": {
    "deliverNo": &lt;配達單號&gt;,
    "receipt": {...}
  }
}</pre>
</td>
         <td></td>
      </tr>
   </tbody>
   <tbody>
      <tr><td>
<pre>{
  "result": 2,
  "message": "資料解析錯誤",
  "returnList": {
    "deliverNo": &lt;配達單號&gt;,
    "receipt": {...}
  }
}</pre>
</td> <td>JSON 錯誤</td>
      </tr>
   </tbody>
   <tbody>
      <tr><td>
<pre>{
  "result": 3,
  "message": "資料庫錯誤",
  "returnList": {
    "deliverNo": &lt;配達單號&gt;,
    "receipt": {...}
  }
}</pre>
</td>  <td></td>
      </tr>
   </tbody>
   <tbody>
      <tr><td>
<pre>{
  "result": 2,
  "message": "商品數量超過限制",
  "returnList": {
    "deliverNo": &lt;配達單號&gt;,
    "receipt": {...}
  }
}</pre>
</td>
         <td></td>
      </tr>
   </tbody>
   <tbody>
      <tr><td>
<pre>{
  "result": 2,
  "message": "金額超出範圍",
  "returnList": {
    "deliverNo": &lt;配達單號&gt;,
    "receipt": {...}
  }
}</pre>
</td>
         <td></td>
      </tr>
   </tbody>
</table>

## 當日 轉POS未結帳 清單

- 從TKOD10/TKOD70 query 已執行後台起單 之 未結帳交易 (參 [起 SO 單 (後台起單 / 轉POS機結帳)](#起-SO-單-後台起單--轉POS機結帳))
- 用途為重印轉單單據 (參 [重印](#重印-POS結帳單據))

### GET **`./transaction/so`**

#### RESPONSE 
<table>
<thead>
<th>JSON</th> <th>DESCRIPTION</th>
</thead>
<tbody>
<tr>
<td><pre>
{
  "result": 1,
  "message": "",
  "returnList": [
    {&lt;Transaction Model&gt;...},
    {&lt;Transaction Model&gt;...},
    ...
  ]
}
</pre></td>
<td>回傳 <code>opFunc=="F"</code> 未結帳轉單</td>
</tr>
</tbody>
<tbody>
<tr>
<td><pre>
{
  "result": 0,
  "message": "無資料",
  "returnList": null
}
</pre></td>
<td style="vertical-align:top"></td>
</tr>
</tbody>
</table>

|Transaction Model|
|-|
|[&lt;Transaction Model&gt;](https://hackmd.io/@chhuang/Hk4pnBrP_#Transaction-Model)|

----

## 重印 POS結帳單據
### POST **`./transaction/so/reprint`**

#### REQUEST

- 只需填寫 printerNo，剩餘欄位勿更改，null 則不印

<table>
<thead>
<th>JSON</th> <th></th>
</thead>
<tbody>
<tr>
<td>

|Transaction Model|
|-|
|[&lt;Transaction Model&gt;](https://hackmd.io/@chhuang/Hk4pnBrP_#Transaction-Model)|

<span class="red">* 必填</span>
<pre>
{
  <span class="red">"printerNo": &lt;printerNo&gt;,</span>
  ...,
  ...,
  "data": [...]
}
</pre></td>
<td style="vertical-align:top"><br/></td>
</tr>
</tbody>
</table>

OR
### POST **`./transaction/so/reprint/{ordNo}`**
### POST **`./transaction/so/reprint/{ordNo}/{printerNo}`**

| PATHPARAM| DESCRIPTION |
| - | - |
| ordNo | 配達單號 |
| printerNo | 印表機代號 (null 則不印) |

#### REQUEST
None
#### RESPONSE 

<table><thead><tr><th>JSON</th><th>DESCRIPTION</th></tr></thead><tbody><tr><td><pre>{
  "result": 1,
  "message": "",
  "returnList": {
    "deliverNo": &lt;配達單號&gt;,
    "receipt": {
      "seller": {
        ...
      },
      "PONo": "",
      "numOfCopies": 1,
      "payments": null,
      "deliverNo": "7055013413002",
      "donateReceipt": "N",
      "tax": 28,
      "repairNo": "",
      "type": "so",
      "serialNo": "",
      "buyer": {
        ...
      },
      "printReceipt": "N",
      "random": "",
      "netSale": 562,
      "subtotal": 590,
      "receiptNo": "",
      "heartCode": "",
      "receiptAmt": 590,
      "time": "2021-10-13 11:06:51",
      "items": [
        {
          ...
        }
      ]
    }
  }
}</pre></td><td>printerNo == null</td></tr></tbody><tbody><tbody><tr><td><pre>{
  "result": 1,
  "message": "重印成功",
  "returnList": {
    "deliverNo": &lt;配達單號&gt;,
    "receipt": {
      "seller": {
       ...
      },
      "PONo": "",
      "numOfCopies": 1,
      "payments": null,
      "deliverNo": "7055013413002",
      "donateReceipt": "N",
      "tax": 28,
      "repairNo": "",
      "type": "so",
      "serialNo": "",
      "buyer": {
        ...
      },
      "printReceipt": "N",
      "random": "",
      "netSale": 562,
      "subtotal": 590,
      "receiptNo": "",
      "heartCode": "",
      "receiptAmt": 590,
      "time": "2021-10-13 11:06:51",
      "items": [
        {
          ...
        }
      ]
    }
  }
}</pre></td><td>printerNo != null</td></tr></tbody><tbody><tr><td><pre>{
  "result": 2,
  "message": "其他錯誤",
  "returnList": null
}</pre></td><td></td></tr></tbody><tbody><tr><td><pre>{
  "result": 2,
  "message": "資料解析錯誤",
  "returnList": null
}</pre></td><td>JSON 錯誤</td></tr></tbody><tbody><tr><td><pre>{
  "result": 3,
  "message": "資料庫錯誤",
  "returnList": null
}</pre></td><td></td></tr></tbody></table>


---
# BargainReason 退貨/變價原因

## 取得退貨/變價原因

### ~~POST **`./transaction/void/reason`**~~ (DEPRECATED) (still functional)
### POST **`./transaction/bargainReason`**

#### REQUEST
<table><thead><tr><th>JSON</th><th>DESCRIPTION</th></tr></thead><tbody><tr><td><pre>{
  "userID": &lt;userID&gt;,
  "userPassword": &lt;password&gt;,
  "bargainType": &lt;0 or 1 or 2&gt;
}</pre></td><td style="vertical-align:top">
<p><code>bargainType=0</code> 變價原因 

<code>bargainType=1</code> 退貨原因 

<code>bargainType=2</code> 維修變價原因</p>
</td></tr></tbody></table>

#### RESPONSE

<table><thead><tr><th>JSON</th><th>DESCRIPTION</th></tr></thead><tbody><tr><td>

|Reason Model|
|-|
|[&lt;Reason Model&gt;](https://hackmd.io/@chhuang/Hk4pnBrP_#Reason-Model)|
<pre>
{
  "result": 1,
  "message": "成功",
  "returnList": [
    { 
      "reasonName": "資訊展變價(無還元金)",
      "reasonID": "0",
      "reasonType": "C",
      "disLimit": 1,
      "fbFlag": "0"
    },
    ...
    {
      "reasonName": "競爭變價(無還元金)  ",
      "reasonID": "4",
      "reasonType": "C",
      "disLimit": 50,
      "fbFlag": "0",
      "competitor": [
        {
          "competitorNo": "01",
          "competitorName": "全國電子"
        },
        ...
      ]
    },
    ...
  ]
}</pre></td><td>bargainType=0<br/>變價原因 
</td></tr></tbody><tbody><tr><td>

|Reason Model|
|-|
|[&lt;Reason Model&gt;](https://hackmd.io/@chhuang/Hk4pnBrP_#Reason-Model)|
<pre>
{
  "result": 1,
  "message": "成功",
  "returnList": [
    { 
      "reasonName": "商品缺貨",
      "reasonType": "R",
      "reasonID": "01"
    },
    ...
  ]
}</pre></td><td>bargainType=1<br/>退貨原因</td>
</tr></tbody><tbody><tr><td>

|Reason Model|
|-|
|[&lt;Reason Model&gt;](https://hackmd.io/@chhuang/Hk4pnBrP_#Reason-Model)|
<pre>
{
  "result": 1,
  "message": "成功",
  "returnList": [
    {
      "reasonName": "代收處理費",
      "reasonID": "S",
      "reasonType": "C",
      "disLimit": 1,
      "fbFlag": "1"
    },
    ...
  ]
}</pre></td><td>bargainType=2<br/>維修變價原因</td></tr></tbody></table>


---

# Installment 分期
## 分期 - 銀行列表
### GET **`./installment`**

#### RESPONSE
<table><thead><tr><th>JSON</th></tr></thead><tbody><tr><td>

```json
{
  "result": 1,
  "message": "",
  "returnList":
    {
      "bankID": "808",
      "bankName": "玉山銀行"
    },
    {
      "bankID": "809",
      "bankName": "凱基銀行"
    },
    ...
  ]
}
```
</td></tr></tbody></table>



## 分期 - 銀行分期設定
### GET **`./installment/bank/{bankID}`**

#### RESPONSE
<table><thead><tr><th>JSON</th><th></th></tr></thead><tbody><tr><td><pre>{
  "result": 1,
  "message": "",
  "returnList":  [
    {
      "installmentNumber": "03",
      "bankID": "822",
      "installmentID": "258",
      "bankName": "中國信託商業銀行",
      "installmentName": "中國信託商業銀行03期",
      "installmentType": null
    },
    ...
  ]
}</pre></td><td></td></tr></tbody></table>

## 分期 - Products
### GET **`./installment/product/{productID}`**
#### RESPONSE

<table><thead><tr><th>JSON</th><th></th></tr></thead><tbody><tr><td>

```json
{
  {
    "result": 1,
    "message": "",
    "returnList": [
      {
        "installmentNumber": 3,
        "pluralityFlag": "1",
        "sequence": 1338444,
        "deductionRate": null,
        "deductionCode": null,
        "deductionType": "1",
        "deductionAMT": null
      },
      {
        "installmentNumber": 3,
        "pluralityFlag": "1",
        "sequence": 1336640,
        "deductionRate": null,
        "deductionCode": null,
        "deductionType": "1",
        "deductionAMT": null
      }
    ]
  }
}
```
</td><td></td></tr></tbody></table>

<hr>

# Member 會員

## 驗證會員
### **POST** **`./member`**
-  content-type: `x-www-form-urlencoded`

#### REQUEST
|KEY | VALUE| DESCRIPTION |
| -|- |-|
|queryType|"1"|查詢會員 by 會員卡號/編號|
|queryData|"49999999"||

|KEY | VALUE| DESCRIPTION |
| -|- |-|
|queryType|"2"|查詢會員 by 身分證號|
|queryData|"A123456789"||

|KEY | VALUE| DESCRIPTION |
| -|- |-|
|queryType|"3"|查詢會員 by mobile|
|queryData|"09xxxxxxxx"||

|KEY | VALUE| DESCRIPTION |
| -|- |-|
|queryType|"4"|查詢會員 by landline|
|queryData|"02xxxxxxxx"||

#### RESPONSE
<table><thead><tr><th>JSON</th><th></th></tr></thead><tbody><tr><td>

```json
{
  "result": 1,
  "message": "",
  "returnList": [
    {
      "CustNo": "2990499999993",
      "CustName": "TEST",
      "EndDate": "29991231",
      "MobileNo": "0923563698",
      "UnuseAmt": "10100"
    }
  ]
}
```
</td><td></td></tr></tbody></table>


|KEY|TYPE|DESCRIPTION|
|-|-|-|
|CustNo|string(13)|會員編號|
|CustName|string(30)|會員姓名|
|EndDate|string(08)|到期日 (YYYYMMDD)|
|MobileNo|string(32)|手機號碼|
|UnuseAmt|string(10)|還元餘額|

## 產生還原金使用紀錄
### POST **`./member/useFB`**
- 產生還原金使用紀錄

#### REQUEST
<table><thead><th>JSON</th></thead><tbody><tr><td>

```json
{
  "CardNo": "49999999",
  "OrdNo": "09999",
  "OrdDate": "20210309",
  "OrdAmt": 11750,
  "UseAmt": 1
}
```
</td></tr></tbody></table>

|KEY|DESCRIPTION|
|-|-|
|CardNo|會員卡號|
|OrdNo|該訂單流水號;<br/>- 對應THD.SERIAL_NO (Transaction.serialNo)|
|OrdDate|該訂單成立時間;<br/>- 對應THD.TDATE (Transaction.dateT)|
|OrdAmt|該訂單總金額;<br/>- 對應THD.SUBTOT (Transaction.header.payment.subtotal)|
|UseAmt|使用的還原金金額;<br/>- 對應THD.OTHER02_AMT(Transaction.header.payment.FBAmt)|

#### RESPONSE
<table><thead><tr><th>JSON</th></tr></thead><tbody><tr><td>

```json
{
  "result": 1,
  "message": "",
  "returnList": null
}
```
</td></tr></tbody>
<tbody><tr><td>

```json
{
  "result": 2,
  "message": "會員卡資料不存在!",
  "returnList": null
}
```
</td></tr></tbody>
<tbody><tr><td>

```json
{
  "result": 2,
  "message": "會員卡號格式錯誤!",
  "returnList": null
}
```
</td></tr></tbody>
<tbody><tr><td>

```json
{
  "result": 2,
  "message": "相同訂單編號重複抵用!",
  "returnList": null
}
```
</td></tr></tbody></table>

## 驗證pincode
### POST **`./member/validateWishFB`**
- 驗證pincode

#### REQUEST
<table><thead><tr><th>JSON</th></tr></thead><tbody><tr><td>

```json
{
  "pincode": "5badb202-b17a-471f-8367-19c44d78080b", /* 掃描出來的pincode */
}
```
</td></tr></tbody></table>


#### RESPONSE
<table><thead><tr><th>JSON</th></tr></thead><tbody><tr><td>

```json
{
  "result": 1,
  "message": "",
  "returnList": {
    "cardNumber": 12345678,
    "checkNumber": 1234,   
    "returnMoney": 123456  
  }
}
```
</td></tr></tbody></table>

|KEY|DESCRIPTION|
|-|-|
|cardNumber|燦坤卡號           number(8)|
|checkNumber|使用者身分證後四碼   number(4)|
|returnMoney|預計使用的還原金金額 number(6)|

## 使用pincode 並 產生還原金使用紀錄
### POST **`./member/useWishFB`**
- 使用pincode & 產生還原金使用紀錄

#### REQUEST

<table><thead><tr><th>JSON</th></tr></thead><tbody><tr><td>

```json
{
  "CardNo": "49999999",
  "OrdNo": "09999",
  "OrdDate": "20210309",
  "OrdAmt": 11750,
  "UseAmt": 1,
  "pincode": "5badb202-b17a-471f-8367-19c44d78080b"
}
```
</td></tr></tbody></table>

|KEY|DESCRIPTION|
|-|-|
|CardNo|會員卡號|
|OrdNo|該訂單流水號;<br/>- 對應THD.SERIAL_NO (Transaction.serialNo)|
|OrdDate|該訂單成立時間;<br/>- 對應THD.TDATE (Transaction.dateT)|
|OrdAmt|該訂單總金額;<br/>- 對應THD.SUBTOT (Transaction.header.payment.subtotal)|
|UseAmt|使用的還原金金額;<br/>- 對應THD.OTHER02_AMT(Transaction.header.payment.FBAmt)|
|pincode|掃描出來的pincode|


#### RESPONSE
<table><thead><tr><th>JSON</th></tr></thead><tbody><tr><td>

```json
{
  "result": 1,
  "message": "",
  "returnList": null
}
```
</td></tr></tbody><tbody><tr><td>

```json
{
  "result": 2,
  "message": "...",
  "returnList": null
}
```
</td></tr></tbody>
<tbody><tr><td>

```json
{
  "result": 4,
  "message": "...",
  "returnList": null
}
```
</td></tr></tbody></table>

---
# Collect 代收
## 查詢代收資訊
- 傳入3條代收條碼，從DYOI_BILLING檢查並回傳代收資訊
### GET **`./collect?bar1={bar1}&bar2={bar2}&bar3={bar3}`**
|QUERYPARAM|DESCRIPTION|
|-|-|
|bar1| 代收條碼1 |
|bar2| 代收條碼2 |
|bar3| 代收條碼3 |
#### RESPONSE
<table><thead><tr><th>JSON</th><th></th></tr></thead><tbody><tr><td><pre>
{
  "result": 1,
  "message": "",
  "returnList": {
    "price": 2800,
    "collectNo": "ACP",
    "barcode1": "100308ACP",
    "barcode2": "0000000217949060",
    "barcode3": "040800000002800",
    "name": "代收保費",
    "allowCreditCard": "1",
    "allowCoupon": "0",
    "receiptCopies": 3,
    "receiptRemark": "稅額:0 元;收款完成後須立即開通;",
    <span class="obsolete">"pluName": "代收保費",</span>
  }
}
</pre></td><td></td></tr></tbody><tbody><tr><td><pre>
{
  "result": 0,
  "message": "無資料",
  "returnList": null
}
</pre></td><td></td></tr></tbody><tbody><tr><td><pre>
{
  "result": 2,
  "message": "付款期限過期",
  "returnList": null
}
</pre></td><td></td></tr></tbody><tbody><tr><td><pre>
{
  "result": 2,
  "message": "不可0元代收",
  "returnList": null
}
</pre></td><td></td></tr></tbody><tbody><tr><td><pre>
{
  "result": 2,
  "message": "條碼長度不符 ...",
  "returnList": null
}
</pre></td><td></td></tr></tbody></table>

---
# Product 商品
## 商品資訊 (with 促代)

### GET **`./product/promotion/{pluNo/barcode}`**
| PATHPARAM| DESCRIPTION |
| - | - |
| pluNo/barcode | 貨號/商品條碼 |
#### RESPONSE

<table><thead><tr><th>JSON</th><th></th></tr></thead><tbody><tr><td>
      
  |Product Model|
  |-|
  |[&lt;Product Model&gt;](https://hackmd.io/@chhuang/Hk4pnBrP_#Product)|
<pre>{
  "result": 1,
  "message": "",
  "returnList": {
    "pluNo": "196481",
    "pluName": "iPad Air 10.5 Wi-Fi 64GB 太空灰",
    "barcode1": "0190199077591",
    "barcode2": "2000001964811",
    "pluSpec": "A2152",
    "measureWord": "PC",
    "direct": "N",
    "price": 15700,
    "vipPrice": 15700,
    "minPrice": 0,
    "fbAmount": 1,
    "validYear": 1,
    "salType": "1",
    "attrib": "B",
    "noDupItem": null,
    "regulation": [
      {
        "checkSeq": false, <span class="green">//true &rarr; <a href="#序號管理-檢查商品序號">POST ./product/checkSeq</a> </span>
        "ean13Check": "0",
        "length": "1,30",
        "invoice": "1",
        "renderWord": "刷機身序號(SerialNo)"
      }
    ],
    "warranty": [
      {
        "id": "114006",
        "name": "洗衣機3+2安家寶",
        "price": 3800,
        "remark": "",
        "year": 5
      },
      {
        "id": "205973",
        "name": "直立式洗衣機延長2年保固",
        "price": 1999,
        "remark": "條碼326",
        "year": 7
      },
      ...
    ],
    "mm": [
      {
        "promoteNo": "0431166",
        "promoteName": "IN-NB/PC/Mac/iPad加價購",
        "daysActive": [1,1,1,1,1,1,1],
        "beginDate": "20210101",
        "endDate": "20210131",
        "beginTime": "0000",
        "endTime": "2359",
        "mmType": "F",
        "amtType": "S",
        "mmAmount": 0,
        "degreeAmt1": 900,
        "degreeAmt2": 0,
        "degreeAmt3": 0,
        "degreeAmt4": 0,
        "degreeAmt5": 0,
        "discId": "01",
        "g1ShareValue": 0,
        "g2ShareValue": 0,
        "g3ShareValue": 0,
        "g4ShareValue": 0,
        "g5ShareValue": 0,
        "g6ShareValue": 0,
        "group1Qty": 0,
        "group2Qty": 0,
        "group3Qty": 0,
        "group4Qty": 0,
        "group5Qty": 0,
        "group6Qty": 0,
        "limitQTY": "0",
        "limitType": "0",
        "limited": "0",
        "shareEquFlag": "1",
        "storeBounds": null,
        "mmPlu": [
          {
            "pluNo": "173198",
            "pluName": "Canon MG3077 無線相片複合機",
            "pluSpec": "A4/無線/影印/掃描",
            "price": 1790,
            "vipPrice": 1790,
            "dmPrice": 1390,
            "mmGroupType": "F",
            "discAmt": null,
            "groupNo": null,
            "priceType": null,
            "returnRate": null,
            "warranty": []
          },
          ...
        ]
      }
    ], 
    ...
  }
}</pre></td><td></td></tr></tbody></table>

## 商品資訊 (無促代)
### GET **`./product/{pluNo/barcode}`**

| PATHPARAM| DESCRIPTION |
| - | - |
| pluNo/barcode | 貨號/商品條碼 |

#### RESPONSE

<table>
   <thead><tr><th>JSON</th> <th></th></tr></thead>
      <tbody>
      <tr><td>
      
|Product Model|
|-|
|[&lt;Product Model&gt;](https://hackmd.io/@chhuang/Hk4pnBrP_#Product)|
<pre>{
  "result": 1,
  "message": "",
  "returnList": {
    "pluNo": "196481",
    "pluName": "iPad Air 10.5 Wi-Fi 64GB 太空灰",
    "pluSpec": "A2152",
    "barcode1": "0190199077591",
    "barcode2": "2000001964811",
    "price": 15700,
    "vipPrice": 15700,
    "minPrice": 0,
    "attrib": "B",
    "direct": "N",
    "fbAmount": 1,
    "measureWord": "PC",
    "noDupItem": null,
    "salType": "1",
    "validYear": 1,
    "mm": [],
    "regulation": [
      {
        "checkSeq": false,
        "ean13Check": "0",
        "length": "1,30",
        "invoice": "1",
        "renderWord": "刷機身序號(SerialNo)"
      }
    ],
    "warranty": [
      {
        "id": "114006",
        "name": "洗衣機3+2安家寶",
        "price": 3800,
        "remark": "",
        "year": 5
      },
      {
        "id": "205973",
        "name": "直立式洗衣機延長2年保固",
        "price": 1999,
        "remark": "條碼326",
        "year": 7
      }
    ]
  }
}</pre>
</td>
         <td></td>
      </tr>
   </tbody>
</table>

## 序號管理: 檢查商品序號
### POST **`./product/checkSeq`**

#### REQUEST
<span class="red">* 必填</span>
<table><thead><tr><th>JSON</th><th></th></tr></thead><tbody><tr><td><pre>
{
  <span class="red">"SeqNo": &lt;string&gt;,
  "ItemNo": &lt;string&gt;,</span>
  <del>"StoreID": "705"</del>
}
</pre></td><td></td></tr></tbody></table>

|KEY|DESCRIPTION|
|-|-|
|SeqNo|序號|
|ItemNo|商品貨號|

#### RESPONSE
<table><thead><tr><th>JSON</th><th>DESCRIPTION</th></tr></thead><tbody><tr><td><pre>
{
  "result": 1,
  "message": "",
  "returnList": &lt;機器序號&gt;
}
</pre></td><td>OK</td></tr></tbody><tbody><tr><td><pre>
{
  "result": 2,
  "message": "-1 序號或IMEI碼不存在, 請重新輸入",
  "returnList": null
}
</pre></td><td></td></tr></tbody></table>


----
# FF 快速鍵

## 快速鍵設定
### GET **`./ff`**

#### RESPONSE
<table><thead><tr><th>JSON</th><th>DESCRIPTION</th></tr></thead><tbody><tr><td><pre>{
  "result": 1,
  "message": "",
  "returnList": {
    "link": [
      {
        "paperNo": "FFLP180925001"
        "label": "單品鍵設定",
        "dateB": "20110117",
        "dateE": "20991231",
        "items": [
          {
            "ffNo": "01",
            "id": 1,
            "pluName": "家電安裝費",
            "pluNo": "026465",
            "price": 2500
          },
          ...
        ]
      }
    ],
    "menu": [
      {
        "paperNo": "FFMP090819001"
        "label": "目錄鍵",
        "categoryName": "會員贈品",
        "categoryNo": "02",
        "dateB": "20090819",
        "dateE": "20991231",
        "items": [
          {
            "id": 1,
            "pluName": "大同6L電烤箱",
            "pluNo": "060608",
            "price": 890
          },
          ...
        ],
        ...
      },
      {
        "paperNo": "FFMP090819001"
        "label": "目錄鍵",
        "categoryName": "中華門號",
        "categoryNo": "05",
        "dateB": "20090819",
        "dateE": "20991231",
        "items": [
          {
            "id": 4,
            "pluName": "中華-699(24)",
            "pluNo": "106263",
            "price": 5000
          }, 
          ...
        ],
      }, 
      ...
    ]
  }
}</pre></td><td></td></tr></tbody></table>

## 快速鍵設定(Menu only) *(Deprecated)*
### GET **`./ff/menu`**

#### RESPONSE
<table>
<thead>
<tr><th>JSON</th><th>DESCRIPTION</th></tr>
</thead>
<tbody>
<tr>
<td><pre>{
  "result": 1,
  "message": "",
  "returnList": [
    {
      "label": "目錄鍵",
      "paperNo": "FFMP090819001",
      "categoryName": "會員贈品",
      "categoryNo": "02",
      "dateB": "20090819",
      "dateE": "20991231",
      "items": [
        {
          "id": 1,
          "pluName": "大同6L電烤箱",
          "pluNo": "060608",
          "price": 890
        },
        ...
      ]
    },
    ...
  ]
}</pre></td>
<td style="vertical-align:top"></td>
</tr>
</tbody>
</table>

## 快速鍵設定(Link only) *(Deprecated)*
### GET **`./ff/link`**

#### RESPONSE
<table>
<thead>
<tr><th>JSON</th><th>DESCRIPTION</th></tr>
</thead>
<tbody>
<tr>
<td><pre>{
  "paperNo": "FFLP180925001",
  "label": "單品鍵設定",
  "dateB": "20110117",
  "dateE": "20991231",
  "items": [
    {
      "ffNo": "01",
      "id": 1,
      "pluName": "家電安裝費",
      "pluNo": "026465",
      "price": 2500
    },
    {
      "ffNo": "02",
      ...
    },
    ...
  ]
}</pre></td>
<td style="vertical-align:top"></td>
</tr>
</tbody>
</table>

----
# Validate 黑名單

## 查詢會員是否為黑名單
### GET **`./validate/black?id={CUST_ID}&type={CUST_KIND}`**
<table><thead><tr><th>QUERYPARAM</th><th>DESCRIPTION</th></tr></thead><tbody><tr><td>id</td><td>1:會員卡號(13碼) 2:統編(8碼)</td></tr><tr><td>type</td><td>1:卡號 2:統編</td></tr></tbody></table>

#### RESPONSE
<table><thead><tr><th>JSON</th><th></th></tr></thead><tbody><tr><td><pre>{
  "result": 0,
  "message": "無資料",
  "returnList": null
}</pre></td><td>此會員非黑名單</td></tr></tbody><tbody><tr><td><pre>{
  "result": 1,
  "message": "...",
  "returnList": {
     "msg": "此會員卡帳戶異常，無法進行結帳，請洽燦坤客服中心",
     "id": "2990800896744",
     "type": "1"
  }
}</pre></td><td>此會員為黑名單</td></tr></tbody><tbody><tr><td><pre>{
  "result": 2,
  "message": "無資料",
  "returnList": null
}</pre></td><td>參數錯誤</td></tr></tbody></table>
----
----

# SQL
## Product

```sql
WITH pluParam AS (SELECT plu_no, ? withMM FROM ( 
  SELECT plu_no FROM product WHERE plu_no=? 
  UNION ALL ( 
    SELECT plu_no FROM product WHERE barcode1 = Lpad(?, 13, '0') 
    UNION 
    SELECT plu_no FROM product WHERE barcode2 = Lpad(?, 13, '0')) 
) WHERE ROWNUM = 1), 
warr AS ( 
--warranty
SELECT warr_accident.plu_no, Listagg(warr_kind||','||plu_name||','||warr_fee||','|| warr_year||','||plu_spec, ';' ) within GROUP(ORDER BY warr_kind) "warrantyInfo" 
  FROM warr_accident JOIN product on product.plu_no=warr_accident.warr_kind 
  WHERE begdate <= Trunc(SYSDATE) AND enddate >= Trunc(SYSDATE) GROUP BY warr_accident.plu_no ORDER BY "warrantyInfo"), 
pluPromo AS ( 
--product
SELECT product.PLU_NO "pluNo", product.PLU_NAME "pluName", product.PLU_SPEC "pluSpec", product.PRICE "price", product.VIP_PRICE "vipPrice", 
  product.BARCODE1 "barcode1", product.BARCODE2 "barcode2", product.FB_AMOUNT "fbAmount", product.SAL_TYPE "salType", product.DIRECT "direct", 
  product.VALID_YEAR "validYear", product.NO_DUP_ITEM "noDupItem", product.ATTRIB "attrib", product.UNIT "measureWord", product.MIN_PRICE "minPrice" , 
  CASE  WHEN attrib='U' THEN 
          'WORDING='||product.plu_spec 
        ELSE 
          (SELECT keyvalue from para_store where keyvalue LIKE '#PRODNO=' || product.plu_no || '%' AND rownum=1) 
        END "paraVal", product.auth_model "authModel", 
  (select "warrantyInfo" FROM warr WHERE warr.plu_no = product.plu_no) "warrantyInfo", 

--mm
  mm.PROMOTE_NO "promoteNo", MM_TYPE "mmType", PROMOTE_NAME "promoteName", b_date "beginDate", e_date "endDate", 
  TO_CHAR(TO_DATE(b_time, 'HH24:MI'), 'HH24MI') "beginTime", TO_CHAR(TO_DATE(e_time, 'HH24:MI'), 'HH24MI') "endTime", 
  NVL(week_1, 0)||NVL(week_2, 0)||NVL(week_3, 0)||NVL(week_4, 0)||NVL(week_5, 0)||NVL(week_6, 0)||NVL(week_7, 0) "wkDaysApplied", 
  AMT_TYPE "amtType", MM_AMOUNT "mmAmount", GROUP_1_QTY "group1Qty", GROUP_2_QTY "group2Qty", GROUP_3_QTY "group3Qty", 
  GROUP_4_QTY "group4Qty", GROUP_5_QTY "group5Qty", GROUP_6_QTY "group6Qty", DISC_ID "discId", G1_SHAREVALUE "g1ShareValue", 
  G2_SHAREVALUE "g2ShareValue", G3_SHAREVALUE "g3ShareValue", G4_SHAREVALUE "g4ShareValue", G5_SHAREVALUE "g5ShareValue", 
  G6_SHAREVALUE "g6ShareValue", STORE_BOUNDS "storeBounds", DEGREE_AMT1 "degreeAmt1", DEGREE_AMT2 "degreeAmt2", DEGREE_AMT3 "degreeAmt3", 
  DEGREE_AMT4 "degreeAmt4", DEGREE_AMT5 "degreeAmt5", LIMITED "limited", if_equ_div "shareEquFlag", limit_type "limitType", mm_cnt_qty "limitQTY", 

--mm_plu 
  "mmPluNo","groupNo","dmPrice", "mmGroupType", "priceType", "returnRate", 
  "discAmt", "mmPluName", "mmPluPrice","mmPluVipPrice", "mmPluSpec", "mmPluWarrantyInfo" 
 
  FROM product JOIN pluParam on product.plu_no=pluParam.plu_no 
          JOIN mm_plu ON mm_plu.plu_no = product.plu_no OR mm_plu.plu_no=product.prod_cate_no 
          JOIN mm ON mm.promote_no = mm_plu.promote_no 
          JOIN (SELECT mm_plu.promote_no "mmPluPromoteNo", product.plu_no "mmPluNo", GROUP_NO "groupNo", ROUND(DM_PRICE) "dmPrice", MM_GROUPTYPE "mmGroupType", 
                    PRICE_TYPE "priceType", RETURN_RATE "returnRate", DISC_AMT "discAmt", PLU_NAME "mmPluName", product.price "mmPluPrice", product.vip_price "mmPluVipPrice", 
                    product.PLU_SPEC "mmPluSpec", (select "warrantyInfo" FROM warr WHERE warr.plu_no = product.plu_no)  "mmPluWarrantyInfo" 
                    FROM mm_plu JOIN product ON mm_plu.plu_no = product.plu_no 
                ) mmproduct ON mmproduct."mmPluPromoteNo" = mm.promote_no 
  WHERE withMM=1 AND TO_CHAR(SYSDATE, 'yyyymmdd') BETWEEN b_date AND e_date 
        AND BITAND(POWER(2, MOD(TO_CHAR(SYSDATE, 'D') +5, 7)), BIN_TO_NUM(week_7,week_6,week_5,week_4,week_3,week_2,week_1)) > 0 
) 
SELECT "pluNo",  "pluName", "pluSpec", "price", "vipPrice", "barcode1", "barcode2", "fbAmount", "salType", "direct", 
 "validYear", "noDupItem", "attrib",  "measureWord", "minPrice" , "paraVal", "authModel", "warrantyInfo", 
 "promoteNo",  "mmType", "promoteName", "beginDate", "endDate", "beginTime", "endTime", "wkDaysApplied", 
 "amtType", "mmAmount", "group1Qty", "group2Qty", "group3Qty", "group4Qty", "group5Qty", "group6Qty", 
 "discId", "g1ShareValue", "g2ShareValue",  "g3ShareValue",  "g4ShareValue",  "g5ShareValue", "g6ShareValue",  "storeBounds", 
 "degreeAmt1", "degreeAmt2",  "degreeAmt3",  "degreeAmt4", "degreeAmt5", "limited", "shareEquFlag", "limitType", "limitQTY", 
 "mmPluNo","groupNo","dmPrice", "mmGroupType", "priceType", "returnRate", "discAmt", "mmPluName", "mmPluPrice","mmPluVipPrice", "mmPluSpec", 
 "mmPluWarrantyInfo" FROM pluPromo 
  UNION ALL 
--single product if no mm
SELECT product.plu_no "pluNo", product.plu_name "pluName", product.plu_spec "pluSpec", product.price "price", 
  product.vip_price "vipPrice", product.barcode1 "barcode1", product.barcode2 "barcode2", product.fb_amount "fbAmount", 
  product.sal_type "salType", product.direct "direct", product.valid_year "validYear", product.no_dup_item "noDupItem", 
  product.attrib "attrib", product.unit "measureWord", product.min_price "minPrice", 
  CASE  WHEN attrib='U' THEN 
          'WORDING='||product.plu_spec 
        ELSE 
          (SELECT keyvalue from para_store where keyvalue LIKE '#PRODNO=' || product.plu_no || '%' AND rownum=1) 
        END "paraVal", product.auth_model "authModel",
  (select "warrantyInfo" FROM warr WHERE warr.plu_no = product.plu_no) "warrantyInfo", 
  null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, 
  null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null 
FROM product JOIN pluParam on product.plu_no=pluParam.plu_no WHERE NOT EXISTS (select 1 from pluPromo) 
```
## Invoice/Receipt number generate
```sql
WITH inparam AS ( 
-- Basic parameters: termNo, storeNo
    SELECT '0025' termNo , keyvalue storeNo FROM para WHERE keyfld = 'STORE_NO' 
),
-- Invoice Setting query
invoiceSetting AS (SELECT part_no, invochar, invo_bnod, invo_enod FROM invoice_d d 
    JOIN inparam ON inparam.termno = d.term_no AND d.store_no = inparam.storeNo 
    WHERE d.invo_byymm = To_char(SYSDATE, 'yyyyMM') 
      AND d.invo_kind='1' 
      AND Nvl(d.mt_flag,'N') <> 'D' 
      AND EXISTS (SELECT 1 FROM invoice_h h 
         WHERE H.invoice_id = d.invoice_id 
           AND h.invoice_no = d.invoice_no 
           AND h.store_no = D.store_no 
           AND h.invo_byymm = d.invo_byymm 
           AND Nvl(h.mt_flag,'N') <> 'D') 
), 
-- Last existence invoice + 1, where letter char == invoiceSetting.invochar
nextInvoice AS (SELECT To_number(part_no) "partNo", invochar || nextinvono "invoiceNo", invo_enod - nextinvono "remainInvoiceNo" 
  FROM ( 
    -- Last invoice + 1
    SELECT Substr(b1_tax_no,1,2) lastinvochar, Substr(b1_tax_no,-8)+1 nextinvono 
    FROM thd JOIN inparam ON inparam.termno = term_no AND inparam.storeNo = store_no 
    WHERE tdate >= (To_char (SYSDATE, 'yyyymm') || '01') 
  ) JOIN invoiceSetting ON lastinvochar = invochar AND 
      (nextinvono BETWEEN invo_bnod AND invo_enod OR (part_no = (SELECT Max(part_no) FROM invoiceSetting))) order by part_no desc, invochar || nextinvono desc 
) 
-- Query newest unused Invoice: last used + 1 or initial value from Invoice 
SELECT "partNo", "invoiceNo", "remainInvoiceNo" FROM nextInvoice WHERE rownum = 1
UNION ALL 
SELECT To_number(part_no) "partNo", invochar || invo_bnod "invoiceNo", 
     invo_enod - invo_bnod "remainInvoiceNo" FROM invoiceSetting 
    WHERE NOT EXISTS (SELECT 1 FROM nextInvoice) AND part_no = (SELECT Min(part_no) from invoiceSetting)
```

```sql
-- Invoice Setting query
WITH invoiceSetting AS (SELECT term_no, part_no, invochar, invo_bnod, invo_enod 
  FROM invoice_d d 
  WHERE d.invo_byymm = To_char(SYSDATE, 'yyyyMM') 
    AND d.invo_kind='1' 
    AND Nvl(d.mt_flag,'N') <> 'D' 
    AND EXISTS (SELECT 1 FROM invoice_h
       WHERE H.invoice_id = d.invoice_id 
         AND h.invoice_no = d.invoice_no 
         AND h.store_no = D.store_no 
         AND h.invo_byymm = d.invo_byymm 
         AND Nvl(h.mt_flag,'N') <> 'D') 
), 
-- Last existence invoice + 1, where letter char == invoiceSetting.invochar
nextInvoice AS (SELECT lastInvo.term_no, To_number(part_no) "partNo", invochar || nextinvono "invoiceNo", invo_enod - nextinvono "remainInvoiceNo" 
  FROM ( 
    -- Last invoice + 1
    SELECT thd.term_no, Substr(b1_tax_no,1,2) lastinvochar, MAX(Substr(b1_tax_no,-8)+1) nextinvono 
    FROM thd  WHERE tdate >= (To_char (SYSDATE, 'yyyymm') || '01') 
    GROUP BY thd.term_no, Substr(b1_tax_no,1,2) 
  ) lastInvo JOIN invoiceSetting ON lastinvochar = invochar AND invoiceSetting.term_no = lastInvo.term_no AND 
      (nextinvono BETWEEN invo_bnod AND invo_enod OR (part_no = (SELECT Max(part_no) FROM invoiceSetting))) order by part_no desc, invochar || nextinvono desc 
) 
-- Query newest unused Invoice: last used + 1 or initial value from Invoice 
SELECT term_no "termNo", "partNo", "invoiceNo", "remainInvoiceNo" FROM nextInvoice 
  UNION ALL 
SELECT term_no "termNo", To_number(part_no) "partNo", invochar || invo_bnod "invoiceNo", 
     invo_enod - invo_bnod "remainInvoiceNo" FROM invoiceSetting 
    WHERE invoiceSetting.term_no not in (SELECT term_no FROM nextInvoice) AND part_no = (SELECT Min(part_no) from invoiceSetting) 
```
# FLOWCHART

## OP_FUNC flowchart
```mermaid
graph TD

start((LOGIN PAGE)) --> B(login<br/>OP_FUNC=1)

E --> G(logout/settlement<br/>OP_FUNC=2/3) --> start
B --> C{Need<br/>Settlement}
C -->|YES: LOGIN FAILED| D(Pre-login settlement<br/>OP_FUNC=3)-->start
C -->|NO: LOGIN SUCCESS| E((DASHBOARD))
E --> F(OTHER operation<br/>OP_FUNC=4,8,P,Q) --> E

```

# MISC

## How to determine 營業日/系統日判斷 (THD.TDATE / THD.SYS_DATE)

#### CASE: OP_FUNC = 1

```sql
TDATE = SYS_DATE = 
  SELECT GREATEST( MAX(sys_date), TO_CHAR(SYSDATE, 'yyyymmdd') ) 
  FROM thd 
  WHERE term_no='0025' AND store_no='00705';
```


:::spoiler Need settle 強迫日結:
```sql
SELECT count(1) "needSettle", NVL(MAX(sys_date), '00000000') "dateSys" FROM thd  
 JOIN 
 (SELECT MAX (tdate || LPAD (TRIM (seq_no), 6, '0')) tdateSeqNo, MAX (term_no) term_no 
  FROM thd WHERE op_func='3' AND term_no='0025') lastSettleRecord 
    ON thd.term_no = lastSettleRecord.term_no 
    AND thd.tdate || lpad(to_number(thd.seq_no), 6, '0') > tdateSeqNo 
WHERE thd.tdate < TO_CHAR (SYSDATE, 'yyyymmdd') AND op_func in ('4', '8', 'P', 'Q');
```
<!---->
:::

#### CASE: OP_FUNC = 3

```sql 
TDATE = 
  MAX(tdate) 
          
SYS_DATE =
  SELECT CASE WHEN (TO_CHAR(SYSDATE, 'HH24MI') BETWEEN '2350' AND '2359') 
         THEN 
            TO_CHAR (SYSDATE + 1, 'YYYYMMDD') 
         ELSE 
            TO_CHAR (SYSDATE, 'YYYYMMDD') 
         END FROM thd WHERE term_no='0025' AND store_no='00705';
``` 

#### CASE: OP_FUNC = 2,4,8,P,Q

```sql
TDATE = 
  MAX(tdate) 
          
SYS_DATE = 
  GREATEST(NVL(MAX(SYS_DATE), 0), TO_CHAR (SYSDATE, 'YYYYMMDD'))
``` 
<!---->



<!-- 
### CASE: OP_FUNC = 3
<pre>
IF lastSettle.YYYYMMDD &lt; today.YYYYMMDD THEN 
  IF records.op_func after lastSettle IS 4 or 8 THEN
    NEED SETTLE
  ELSE
    營業日 = today.date
ELSE
  營業日 = lastSettle.date
</pre>
 -->

