---
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": <JWT Access token>
<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": <termNo>
}
}</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 < 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|
|-|
|[<Transaction Model>](https://hackmd.io/@chhuang/Hk4pnBrP_#Transaction-Model)|
<span class="red">* 紅色: 必填</span>
<pre>{
<span class="red">"printerNo": <"0" or "2"> ,
"termNo": <string>,
"opFunc": <"4" or "P">,</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": <string>,
"sellerNo": <string>,
"bossNo": <string>,
"deliverNo": <string>,
"repairNo": <string>, <span class="green">// 維修結帳使用</span>
"opFuncSub": <string>,</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": <string>,
"memberTel": <string>,</span>
"abnormalMember": "",
"customerCount": 0,
"customerValid": "",
"guestId": "",
"memberUnregister": "",
"membercode": ""
},
"payment": {
<span class="red">"subtotal": <integer>,
"cash": <integer>,
"FBAmt": <integer>,
"creditAmt": <integer>,
"PGAmt": <integer>,
"TKGoodsAmt": <integer>,
"bankPointsAmt": <integer>,
"discountAmt": <integer>,
"excessAmt": <integer>,
"invoiceRewAmt": <integer>,
"oldGoodsAmt": <integer>,
"otherGoodsAmt": <integer>,
"pointsAmt": <integer>,
"ecPaymentAmt": <integer>, <span class="green">// New 20210126 </span>
"shoppingAmt": <integer>,
<del>"sponsorAmt": <integer>,</del> <span class="green">// Removed 20210126 </span>
"promotionDiscountAmount": <integer>,
"totalDiscountAmount": <integer>,
"cashChange": <integer>,
"pincode": <string>,</span>
"debit": <integer>,
"couponChange": 0,
"reservedAMT1": 0,
"reservedAMT2": 0,
"reservedCouponAmt": 0,
"creditCard": {
<span class="red">"creditCardAmt": <integer>,
"creditCardNo": <string>,
"approveCode":"777777", <span class="green">// 20210203 added 信用卡授權碼</span>
"bankNo": <string>,
"cardType": <cardstringType>,
"installmentFlag": <string>,
"installmentID": <string>,
"installmentNumber": <integer>,
"installmentName": <string>,
"termPayIntRateAmt": <integer>,
"bankOrderNo": <string>,</span>
"creditCardConnectStatus": "",
"unionPayFlag": "",
"EDC": ""
},
"linePay": {
<span class="red">"linePayAmt": <integer>,</span>
"lineCreditCardAmt": 0,
"lineDiscountAmt": 0,
"lineOtherAmt": 0,
"linePayOrder": "",
"linePointAmt": 0,
"lineiPASSAmt": 0,
},
},
<span class="red">"receipt": {
"tax": <integer>,
"printReceipt": <"Y" or "N">,
"donateReceipt": <"Y" or "N"> Y/N,
"GUINo": <string>,
"commCode": <string>,
"heartCode": <string>,
"MOICANo": <string>,
"passportNo": <string>,</span>
"claimReceiptLotteryNo": "",
"netSale": 0,
"random": "",
"receiptAmt": 0,
"receiptCounter": 0,
"receiptNo": "",
"receiptType": "",
"taxFreeReceiptCounter": 0,
"taxFreeReceiptNo": "",
"zeroTaxFlag": ""
},
"void": {...}
},
<span class="red">"data": [
{
"detailID": <"001", "002", "003", ...>,
"inputType": <"K" or "S">,
"detailCode": <"R" or "M" or "O">,
"pluNo": <string>,
"pluSpec": <string>,
"name": <string>,
"mmType": <"N" or "F" or "B" or "T">,
"priceType": <"N" or "D">,
"promoteID": <string>,
"groupNo": <string>,
"quantity": <integer>,
"salesPromotionQuantity": <integer>,
"storeBounds": <integer>,
"taxFreeFlag": <string>,
"barcodeNo": <string>,
"collectNo": <string>,
"keyinSeq1":<string>, <span class="green">// 20210219 added</span>
"keyinSeq3":<string>, <span class="green">// 20210219 added</span>
"barcode1": <string>,
"barcode2": <string>,
"barcode3": <string>,</span>
<del>"mmNo": "",
"vendorNo": "",
"productCategoryNo": "",
"pluSerialNo": "",</del> <span class="green">// 20210219 removed</span>
<del>"cardNo": <cardNo>,</del><span class="green">// 20210219 removed</span>
<span class="red">"price": {
"normalAmt": <integer>,
"taxIncludeAmt": <integer>,
"qtyTaxAmt": <integer>,
"salesPromotionAmt": <integer>,
"mmShareDiscountAmt": <integer>,</span>
"couponShareDiscountAmt": 0,
"excessShareAmt": 0,
"netSale": 0
},
<span class="red">"refund": {
"priceChangeFlag": <"" or "1">,
"reasonNo": <string>,
"competitorAmt": <integer>,
"competitorNo": <string>,</span>
"refunderID": "",
"unitRefundReasonNo": ""
},
<span class="red">"warranty": {
"warrantyPluNo": <string>,
"warrantyPluSeq": <string>,
"warrantyAccNo": <string></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|
|-|
|[<Receipt Model>](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">// <reason JSON> </span>
{
reasonName: <string>,
reasonID: <string>,
reasonType: <string>
},
...
],
<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|[<Transaction Model>](https://hackmd.io/@chhuang/Hk4pnBrP_#Transaction-Model)|
|returnReasonList\[\]|[<Reason Model>](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|
|-|
|[<Transaction Model>](https://hackmd.io/@chhuang/Hk4pnBrP_#Transaction-Model)|
<span class="red">* 必填</span>
<pre>{
"opFunc": "8",
...
"header": {
<span class="red">"refundReasonNo": <string></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|
|-|
|[<Transaction Model>](https://hackmd.io/@chhuang/Hk4pnBrP_#Transaction-Model)|
<pre>{
<span class="red">"termNo": <string>,</span>
"opFunc": "5",
...
"header": {
<span class="red">"cashierNo": <string>,
"sellerNo": <string>,
"bossNo": <string></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": <deliverNo>
"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|
|-|
|[<Transaction Model>](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|
|-|
|[<Transaction Model>](https://hackmd.io/@chhuang/Hk4pnBrP_#Transaction-Model)|
<span class="red">* 必填欄位</span>
<pre>
{
<span class="red">"expiryDate": <string></span> or <span class="red">null, <span class="green">// "YYYYMMDD"</span>
"termNo": <string></span>,
"opFunc": "F",
...
<span class="red">"header": {
"cashierNo": <string>,
"sellerNo": <string>,</span>
...
<span class="red">"customer": {
"memberID": <string>,
"name": <string>, <span class="green">// default ""</span>
"landline": <string>, <span class="green">// default ""</span>
"mobile": <string>, <span class="green">// default ""</span>
"address": <string>, <span class="green">// default ""</span>
"address2": <string>, <span class="green">// default ""</span></span>
<span style="color:darkred">"memberTel": <string></span>, <span class="green">// ? not sure</span>
...
},
<span class="red"> "payment": {
"subtotal": <integer>,</span>
"promotionDiscountAmount": <integer>, <span class="green">// ? not sure</span>
"totalDiscountAmount": <integer>, <span class="green">// ? not sure</span>
...
<span class="red">"creditCard": { <span class="green">// 如果有選擇分期</span>
"bankNo": <string>,
"installmentID": <string>,
"installmentNumber": <integer>,
"termPayIntRateAmt": <integer>,</span>
...
},
...
},
<span class="red">"receipt": {
"GUINo": <string>,
"MOICANo": <string>,
"commCode": <string>,
"heartCode": <string>,
"passportNo": <string>,</span>
...
},
...
},
"data": [
{
<span class="red">"detailID": <string>,
"pluNo": <string>,
"pluSpec": <string>,
"mmType": <string>,
"name": <string>,
"promoteID": <string>,
"quantity": <integer>,
"storeBounds": <integer>,
"salesPromotionQuantity": <integer>,
"taxFreeFlag": <string>,
"inputType": <string>,
"priceType": <string>,
"groupNo": <string>,
"keyinSeq1": "",
"keyinSeq3": "",
"barcodeNo": "",</span>
"barcode1": "",
"barcode2": "",
"barcode3": "",
"collectNo": "",
"detailCode": "",
"mmNo": "",
"productCategoryNo": "",
"vendorNo": "",
<span class="red">"price": {
"qtyTaxAmt": <integer>,
"normalAmt": <integer>,
"taxIncludeAmt": <integer>,
"couponShareDiscountAmt": <integer>,
"excessShareAmt": <integer>,
"mmShareDiscountAmt": <integer>,
"salesPromotionAmt": <integer></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|
|-|
|[<Receipt Model>](https://hackmd.io/@chhuang/BycnYBz5w)|
<pre>{
"result": 1,
"message": "",
"returnList": {
"deliverNo": <配達單號>,
"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": <配達單號>,
"receipt": {...}
}
}</pre>
</td>
<td></td>
</tr>
</tbody>
<tbody>
<tr><td>
<pre>{
"result": 2,
"message": "無機號或收銀員編號傳入",
"returnList": {
"deliverNo": <配達單號>,
"receipt": {...}
}
}</pre>
</td>
<td></td>
</tr>
</tbody>
<tbody>
<tr><td>
<pre>{
"result": 2,
"message": "資料解析錯誤",
"returnList": {
"deliverNo": <配達單號>,
"receipt": {...}
}
}</pre>
</td> <td>JSON 錯誤</td>
</tr>
</tbody>
<tbody>
<tr><td>
<pre>{
"result": 3,
"message": "資料庫錯誤",
"returnList": {
"deliverNo": <配達單號>,
"receipt": {...}
}
}</pre>
</td> <td></td>
</tr>
</tbody>
<tbody>
<tr><td>
<pre>{
"result": 2,
"message": "商品數量超過限制",
"returnList": {
"deliverNo": <配達單號>,
"receipt": {...}
}
}</pre>
</td>
<td></td>
</tr>
</tbody>
<tbody>
<tr><td>
<pre>{
"result": 2,
"message": "金額超出範圍",
"returnList": {
"deliverNo": <配達單號>,
"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": [
{<Transaction Model>...},
{<Transaction Model>...},
...
]
}
</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|
|-|
|[<Transaction Model>](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|
|-|
|[<Transaction Model>](https://hackmd.io/@chhuang/Hk4pnBrP_#Transaction-Model)|
<span class="red">* 必填</span>
<pre>
{
<span class="red">"printerNo": <printerNo>,</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": <配達單號>,
"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": <配達單號>,
"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": <userID>,
"userPassword": <password>,
"bargainType": <0 or 1 or 2>
}</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|
|-|
|[<Reason Model>](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|
|-|
|[<Reason Model>](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|
|-|
|[<Reason Model>](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|
|-|
|[<Product Model>](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 → <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|
|-|
|[<Product Model>](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": <string>,
"ItemNo": <string>,</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": <機器序號>
}
</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 < today.YYYYMMDD THEN
IF records.op_func after lastSettle IS 4 or 8 THEN
NEED SETTLE
ELSE
營業日 = today.date
ELSE
營業日 = lastSettle.date
</pre>
-->