--- 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> -->