From 71a059183a5f312bb47c54fcd11d5ab83cfad91e Mon Sep 17 00:00:00 2001 From: sky121113 Date: Thu, 28 May 2026 17:48:03 +0800 Subject: [PATCH] =?UTF-8?q?[REFACTOR]=20=E5=84=AA=E5=8C=96=E4=B8=AD?= =?UTF-8?q?=E5=9C=8B=E9=86=AB(Cmuh)=E5=94=AE=E8=B2=A8=E8=88=87=E9=A0=98?= =?UTF-8?q?=E8=97=A5=E6=B5=81=E7=A8=8B=EF=BC=8C=E9=87=8D=E6=A7=8B=20API=20?= =?UTF-8?q?=E9=80=A3=E7=B7=9A=E6=A8=A1=E7=B5=84=EF=BC=8C=E4=B8=A6=E8=87=AA?= =?UTF-8?q?=E5=8B=95=E5=8D=87=E7=89=88=E8=87=B3=2024?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 重構 Cmuh 的 SaleFlowHandler:新增 ORDC_EMPTY、MATERIAL_NOT_FOUND、STOCK_NOT_ENOUGH 等明確領藥錯誤代碼,最佳化多貨道庫存匹配與扣減邏輯,改善掃碼按鈕的動態 UI 綁定時序。 2. 增強 Dialog UI 提示:重構 PickupErrorTipDialog 與 DispatchDialog,優化 dialog_pickup_error_tip.xml 佈局結構,確保出貨異常時能正確顯示對應的中文 Toast 與圖示。 3. 重構 HttpAPI 與網路層:重構後台 API 與 HttpConnect 的 Socket/連線異常處理,確實向 UI 回傳網路錯誤訊息(非吞例外),提升在極端網路環境下的穩定度。 4. 健全持久化與日誌模組:強化 StarCloudAPI 機台 Token 變更時的本地 SQLite 同步邏輯,提升 Logs 模組的非同步儲存與排程上傳穩定性。 5. 自動升版:配合實體機台 OTA 發版鐵律,將 app/build.gradle 中的 verPatch 變數由 23 遞增至 24。 6. 更新工作流說明:優化 .agents/workflows/compiler-apk.md 文件中的智慧尺寸判斷指令說明。 --- .agents/workflows/compiler-apk.md | 107 +- AGENTS.md | 31 + app/build.gradle | 56 +- .../smartdevice/ui/SaleFlowHandler.java | 4 + .../smartdevice/ui/SaleFlowHandler.java | 142 ++- .../ui/dialog/PickupErrorTipDialog.java | 44 +- .../res/layout/dialog_pickup_error_tip.xml | 29 +- .../smartdevice/ui/SaleFlowHandler.java | 4 + .../com/unibuy/smartdevice/MainActivity.java | 32 +- .../java/com/unibuy/smartdevice/MyApp.java | 48 + .../unibuy/smartdevice/devices/ComPort.java | 12 + .../unibuy/smartdevice/exception/Logs.java | 8 +- .../unibuy/smartdevice/external/HttpAPI.java | 998 ++++++++++-------- .../smartdevice/external/StarCloudAPI.java | 32 + .../unibuy/smartdevice/tools/HttpConnect.java | 8 +- .../tools/TransactionFinalizeBuilder.java | 6 +- .../smartdevice/ui/FontendActivity.java | 5 + .../smartdevice/ui/devs/vmc/VmcFragment.java | 12 + .../ui/devs/vmc/VmcSlotListActivity.java | 25 +- .../smartdevice/ui/dialog/DispatchDialog.java | 135 ++- .../worker/UploadLogOneTimeWorker.java | 56 +- .../worker/UploadLogPeriodicWorker.java | 54 +- app/src/main/res/layout/activity_fontend.xml | 4 +- .../res/layout/recycler_vmc_slot_list.xml | 2 +- app/src/main/res/values-en/strings.xml | 9 +- app/src/main/res/values-ja/strings.xml | 9 +- app/src/main/res/values/strings.xml | 9 +- 27 files changed, 1271 insertions(+), 610 deletions(-) create mode 100644 AGENTS.md diff --git a/.agents/workflows/compiler-apk.md b/.agents/workflows/compiler-apk.md index 4ee952b..08cd42d 100644 --- a/.agents/workflows/compiler-apk.md +++ b/.agents/workflows/compiler-apk.md @@ -7,15 +7,15 @@ description: 自動編譯 Android APK、輸出至專屬目錄並安裝至實體 這個 Workflow 主要是協助您一鍵完成 Android 專案的編譯、匯出與安裝。當您呼叫 `/compiler-apk` 時,AI 會自動為您執行以下步驟: > [!TIP] -> **支援參數化指定編譯變體:** -> * 預設(不帶參數):編譯 **`Chengwai` (晟崴客製版)**。 -> * 您可以呼叫 `/compiler-apk General`(或 `general`)編譯 **`General` (通用版)**。 -> * 您可以呼叫 `/compiler-apk Cmuh`(或 `cmuh`)編譯 **`Cmuh` (中國醫客製版)**。 +> **支援智慧硬體判斷與參數化覆寫:** +> * 預設(不帶參數):編譯 **`Chengwai` 晟崴版 (S12XYU)**。 +> * **智慧判斷**:當編譯 **`中國醫 (Cmuh)`** 時,會自動識別並預設編譯 **`S9XYU` (Android 9 / 21.5 吋)**;編譯 **`General`** 與 **`Chengwai`** 時則預設編譯 **`S12XYU` (10 吋)**。 +> * **參數手動覆寫**:支援手動指定硬體尺寸。例如 `/compiler-apk Cmuh S12` 可強行編譯中國醫的 10 吋版本;`/compiler-apk General S9` 可強行編譯通用版的大螢幕 21.5 吋版本。 ## 步驟零:自動檢查變更與升級版號 在開始編譯之前,AI 助手會自動檢查是否有程式碼變更,以落實實體機台的 OTA 升級規範: 1. AI 助手將檢查 `git status --porcelain app/` 的輸出,以偵測是否有未提交的程式碼修改。 -2. 若偵測到變更,且本次任務尚未增加版號,AI 助手將自動讀取 `app/build.gradle` 並將其中的 `verPatch` 變數數值遞增 1(例如由 `5` 變更為 `6`)。 +2. 若偵測到變更,且本次任務尚未增加版號,AI 助手將自動讀取 `app/build.gradle` 並將其中的 `verPatch` 變數數值遞增 1。 3. 遞增完成後,向使用者呈報最新的版本號資訊,接著繼續執行步驟一。 ## 步驟一:設定環境並編譯 Debug APK @@ -29,14 +29,12 @@ description: 自動編譯 Android APK、輸出至專屬目錄並安裝至實體 export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 cd /home/mama/projects/TaiwanStar_general_size_s_Chengwai -# 取得目標 Flavor 參數,支援中文與英文別名自動對齊與防呆 +# 取得目標 Flavor 參數 RAW_INPUT="$1" TARGET_FLAVOR="Chengwai" if [ -n "$RAW_INPUT" ]; then - # 統一轉換為小寫以做比對 LOWER_INPUT=$(echo "$RAW_INPUT" | tr '[:upper:]' '[:lower:]') - if [ "$LOWER_INPUT" = "general" ] || [ "$LOWER_INPUT" = "通用" ] || [ "$LOWER_INPUT" = "通用版" ] || [ "$LOWER_INPUT" = "標準" ] || [ "$LOWER_INPUT" = "標準版" ]; then TARGET_FLAVOR="General" elif [ "$LOWER_INPUT" = "chengwai" ] || [ "$LOWER_INPUT" = "晟崴" ] || [ "$LOWER_INPUT" = "晟崴版" ]; then @@ -44,22 +42,37 @@ if [ -n "$RAW_INPUT" ]; then elif [ "$LOWER_INPUT" = "cmuh" ] || [ "$LOWER_INPUT" = "中國醫" ] || [ "$LOWER_INPUT" = "中國醫版" ]; then TARGET_FLAVOR="Cmuh" else - # 若非預設之中文別名,則嘗試做首字母大寫轉換(相容英文輸入,如 cmuh -> Cmuh) TARGET_FLAVOR=$(echo "$RAW_INPUT" | awk '{print toupper(substr($0,1,1))tolower(substr($0,2))}') fi fi +# 根據 Flavor 動態設定智慧硬體規格預設值 +TARGET_HARDWARE="S12XYU" +if [ "$TARGET_FLAVOR" = "Cmuh" ]; then + TARGET_HARDWARE="S9XYU" +fi + +# 取得手動指定的第二個硬體規格參數 (S9 / S12) +RAW_HW_INPUT="$2" +if [ -n "$RAW_HW_INPUT" ]; then + LOWER_HW=$(echo "$RAW_HW_INPUT" | tr '[:upper:]' '[:lower:]') + if [ "$LOWER_HW" = "s9" ] || [ "$LOWER_HW" = "s9xyu" ] || [ "$LOWER_HW" = "大螢幕" ] || [ "$LOWER_HW" = "21.5" ]; then + TARGET_HARDWARE="S9XYU" + elif [ "$LOWER_HW" = "s12" ] || [ "$LOWER_HW" = "s12xyu" ] || [ "$LOWER_HW" = "10" ]; then + TARGET_HARDWARE="S12XYU" + fi +fi + # 安全防護:檢查是否為支援的客製項目 if [ "$TARGET_FLAVOR" != "General" ] && [ "$TARGET_FLAVOR" != "Chengwai" ] && [ "$TARGET_FLAVOR" != "Cmuh" ]; then echo "❌ 不支援的 Flavor: $TARGET_FLAVOR,請使用 General, Chengwai 或 Cmuh。" exit 1 fi -echo "🚀 開始編譯: ${TARGET_FLAVOR}S12XYUDebug" +echo "🚀 開始編譯: ${TARGET_FLAVOR}${TARGET_HARDWARE}Debug" # 使用 clean 確保完整重新編譯,避免舊快取遮蔽 import 缺失等錯誤 -# --no-daemon:強制使用單次 JVM 進程,避免 Daemon 初始化期間被殘留訊號中斷 -./gradlew clean :app:assemble${TARGET_FLAVOR}S12XYUDebug --no-daemon +./gradlew clean :app:assemble${TARGET_FLAVOR}${TARGET_HARDWARE}Debug --no-daemon ``` ## 步驟二:導出 APK 到 outputs 資料夾 @@ -70,7 +83,7 @@ echo "🚀 開始編譯: ${TARGET_FLAVOR}S12XYUDebug" cd /home/mama/projects/TaiwanStar_general_size_s_Chengwai mkdir -p outputs -# 取得 Flavor 參數,支援中英文別名對齊 +# 取得 Flavor 參數 RAW_INPUT="$1" TARGET_FLAVOR="Chengwai" @@ -87,8 +100,33 @@ if [ -n "$RAW_INPUT" ]; then fi fi -# 動態尋找編譯產出的最新 APK 檔案,避免因版號變更導致寫死路徑失效 -APK_SOURCE=$(find app/build/outputs/apk/${TARGET_FLAVOR}S12XYU/debug/ -name "app-S_12_XY_U_${TARGET_FLAVOR}-*-debug.apk" | head -n 1) +# 根據 Flavor 動態設定智慧硬體規格預設值 +TARGET_HARDWARE="S12XYU" +if [ "$TARGET_FLAVOR" = "Cmuh" ]; then + TARGET_HARDWARE="S9XYU" +fi + +# 取得手動指定的第二個硬體規格參數 (S9 / S12) +RAW_HW_INPUT="$2" +if [ -n "$RAW_HW_INPUT" ]; then + LOWER_HW=$(echo "$RAW_HW_INPUT" | tr '[:upper:]' '[:lower:]') + if [ "$LOWER_HW" = "s9" ] || [ "$LOWER_HW" = "s9xyu" ] || [ "$LOWER_HW" = "大螢幕" ] || [ "$LOWER_HW" = "21.5" ]; then + TARGET_HARDWARE="S9XYU" + elif [ "$LOWER_HW" = "s12" ] || [ "$LOWER_HW" = "s12xyu" ] || [ "$LOWER_HW" = "10" ]; then + TARGET_HARDWARE="S12XYU" + fi +fi + +# 解析硬體規格來決定輸出檔案名格式 (S9 -> S_9, S12 -> S_12) +FORMATTED_HW="" +if [ "$TARGET_HARDWARE" = "S9XYU" ]; then + FORMATTED_HW="S_9_XY_U" +else + FORMATTED_HW="S_12_XY_U" +fi + +# 動態尋找編譯產出的最新 APK 檔案 +APK_SOURCE=$(find app/build/outputs/apk/${TARGET_FLAVOR}${TARGET_HARDWARE}/debug/ -name "app-${FORMATTED_HW}_${TARGET_FLAVOR}-*-debug.apk" | head -n 1) if [ -n "$APK_SOURCE" ]; then APK_NAME=$(basename "$APK_SOURCE") @@ -98,11 +136,19 @@ if [ -n "$APK_SOURCE" ]; then # 提取與計算版本資訊 MAJOR=$(grep "def verMajor" app/build.gradle | awk '{print $4}') + + # 若在 build.gradle 內 Major 是由 hardware 動態判定,直接讀取並在 Shell 依據當前規格計算 + if [ "$TARGET_HARDWARE" = "S9XYU" ]; then + MAJOR=21 + else + MAJOR=10 + fi + MINOR=$(grep "def verMinor" app/build.gradle | awk '{print $4}') PATCH=$(grep "def verPatch" app/build.gradle | awk '{print $4}') VERSION_NAME="${MAJOR}_0${MINOR}_${PATCH}_R" VERSION_CODE=$((MAJOR * 10000 + MINOR * 100 + PATCH)) - FLAVOR="${TARGET_FLAVOR}S12XYU" + FLAVOR="${TARGET_FLAVOR}${TARGET_HARDWARE}" echo "==================================================" echo "📢 後台更新 keyin 參考資料:" @@ -125,7 +171,7 @@ fi // turbo ADB_PATH="/mnt/c/Users/User/AppData/Local/Android/Sdk/platform-tools/adb.exe" -# 取得 Flavor 參數,支援中英文別名對齊 +# 取得 Flavor 參數 RAW_INPUT="$1" TARGET_FLAVOR="Chengwai" @@ -142,12 +188,37 @@ if [ -n "$RAW_INPUT" ]; then fi fi +# 根據 Flavor 動態設定智慧硬體規格預設值 +TARGET_HARDWARE="S12XYU" +if [ "$TARGET_FLAVOR" = "Cmuh" ]; then + TARGET_HARDWARE="S9XYU" +fi + +# 取得手動指定的第二個硬體規格參數 (S9 / S12) +RAW_HW_INPUT="$2" +if [ -n "$RAW_HW_INPUT" ]; then + LOWER_HW=$(echo "$RAW_HW_INPUT" | tr '[:upper:]' '[:lower:]') + if [ "$LOWER_HW" = "s9" ] || [ "$LOWER_HW" = "s9xyu" ] || [ "$LOWER_HW" = "大螢幕" ] || [ "$LOWER_HW" = "21.5" ]; then + TARGET_HARDWARE="S9XYU" + elif [ "$LOWER_HW" = "s12" ] || [ "$LOWER_HW" = "s12xyu" ] || [ "$LOWER_HW" = "10" ]; then + TARGET_HARDWARE="S12XYU" + fi +fi + +# 解析硬體規格來決定輸出檔案名格式 (S9 -> S_9, S12 -> S_12) +FORMATTED_HW="" +if [ "$TARGET_HARDWARE" = "S9XYU" ]; then + FORMATTED_HW="S_9_XY_U" +else + FORMATTED_HW="S_12_XY_U" +fi + # 檢查是否有設備連接 DEVICE_COUNT=$($ADB_PATH devices | grep -v "List of devices" | grep "device" | wc -l) if [ "$DEVICE_COUNT" -gt 0 ]; then echo "📱 偵測到 $DEVICE_COUNT 個設備,開始安裝..." - APK_TARGET=$(find outputs/ -name "app-S_12_XY_U_${TARGET_FLAVOR}-*-debug.apk" | head -n 1) + APK_TARGET=$(find outputs/ -name "app-${FORMATTED_HW}_${TARGET_FLAVOR}-*-debug.apk" | head -n 1) if [ -n "$APK_TARGET" ]; then $ADB_PATH install -r -d -t "/home/mama/projects/TaiwanStar_general_size_s_Chengwai/$APK_TARGET" echo "🚀 安裝完成,正在啟動 App..." diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..45d7b68 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,31 @@ +# TaiwanStar Agent Rules Index + +本文件為 Agent 規則入口與導覽摘要,不承載完整規範細節。 + +## Rule Sources (Single Source of Truth) + +以下檔案為唯一真實來源(Single Source of Truth): + +- [.agents/rules/star-cloud-api.md](.agents/rules/star-cloud-api.md) +- [.agents/rules/versioning.md](.agents/rules/versioning.md) + +任何規則更新,請只修改上述原始檔案;`AGENTS.md` 僅同步摘要與導覽。 + +## Critical Rules Snapshot + +### Star-Cloud API + +- 除 `B014`(綁定)外,請求需帶 `Authorization: Bearer [MachineToken]`。 +- 涉及 Token(`ApiKey`)變更時,必須同步持久化到資料庫。 +- 網路錯誤不可吞例外,需回傳可見錯誤到 UI(如 Toast/Handler)。 + +### Versioning + +- 禁止直接手改成品 `versionCode`/`versionName` 值。 +- 版號管理透過 `verMajor`、`verMinor`、`verPatch` 變數。 +- OTA 發版時,`versionCode` 必須嚴格遞增。 + +## When Rules Conflict + +- 規則細節若有衝突,以 `.agents/rules` 下原始規則檔為準。 +- `AGENTS.md` 僅作導覽與快速摘要,不作為完整規範來源。 diff --git a/app/build.gradle b/app/build.gradle index d1d6963..10642fc 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -5,12 +5,12 @@ plugins { // ========================================================================= // 核心版號與自動連動定義 // 每次發佈新版本給機台時,只需遞增 verPatch (修補版號)。 -// 例如:從 5 改為 6,對應的 versionName 就會自動變成 "10_08_6_R", -// versionCode 就會自動變大為 100806,以正確觸發實體機台的 OTA 自動更新。 +// 螢幕尺寸 (verMajor) 已改為下方依據編譯 Flavor (S12XYU / S9XYU) 自動動態判定, +// 避免不同尺寸機台間版本號產生衝突。 // ========================================================================= -def verMajor = 10 def verMinor = 1 -def verPatch = 6 +def verPatch = 24 + android { namespace 'com.unibuy.smartdevice' @@ -20,8 +20,9 @@ android { applicationId "com.unibuy.smartdevice" minSdk 21 targetSdk 34 - versionCode verMajor * 10000 + verMinor * 100 + verPatch - versionName "${verMajor}_0${verMinor}_${verPatch}_R" + // 預設以 10 吋進行基礎 Sync 估算,實際打包會由下方 applicationVariants 動態覆寫 + versionCode 10 * 10000 + verMinor * 100 + verPatch + versionName "10_0${verMinor}_${verPatch}_R" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } @@ -47,6 +48,11 @@ android { S12XYU { dimension "hardware" } + + S9XYU { + dimension "hardware" + minSdk 28 + } } buildTypes { @@ -57,23 +63,48 @@ android { } } - // 自定義打包檔案名稱,遵循公司命名規範:來源_安卓號_主板號_機器系列_專案名稱_螢幕大小_次版號_修補版號_環境 + // 自定義打包檔案名稱與動態版本號計算 + // 遵循公司命名規範:來源_安卓號_主板號_機器系列_專案名稱_螢幕大小_次版號_修補版號_環境 applicationVariants.all { variant -> + def project = variant.productFlavors[0].name // project dimension + def hardware = variant.productFlavors[1].name // hardware dimension + def buildType = variant.buildType.name + + // 根據硬體規格自動動態判定螢幕吋數 (verMajor) 與版號 + def verMajor = 10 + def calculatedMinor = verMinor // 預設套用全域次版號 + def calculatedPatch = verPatch // 預設套用全域修補版號 + + if (hardware == "S9XYU") { + verMajor = 21 // 21.5 吋 + + // 【預留擴充】若中國醫安卓 9 機台未來需要獨立的發版節奏,可直接在此單獨覆寫: + // calculatedMinor = 1 + // calculatedPatch = 6 + } else if (hardware == "S12XYU") { + verMajor = 10 // 10 吋 + } + + // 動態重算並覆寫此 Variant 的版本號,避免互相污染 + def calculatedVersionCode = verMajor * 10000 + calculatedMinor * 100 + calculatedPatch + def calculatedVersionName = "${verMajor}_0${calculatedMinor}_${calculatedPatch}_R" + + variant.outputs.each { output -> - def versionName = variant.versionName - def project = variant.productFlavors[0].name // project dimension - def hardware = variant.productFlavors[1].name // hardware dimension - def buildType = variant.buildType.name + output.versionCodeOverride = calculatedVersionCode + output.versionNameOverride = calculatedVersionName // 將 hardware flavor 名稱展開為公司規範格式 S12XYU → S_12_XY_U def hwFormatted = hardware .replaceAll(/^([A-Z])(\d+)([A-Z]+)([A-Z])$/, '$1_$2_$3_$4') // 輸出範例:app-S_12_XY_U_Chengwai-10_08_8_R-release.apk - output.outputFileName = "app-${hwFormatted}_${project}-${versionName}-${buildType}.apk" + output.outputFileName = "app-${hwFormatted}_${project}-${calculatedVersionName}-${buildType}.apk" } } + + compileOptions { sourceCompatibility JavaVersion.VERSION_11 targetCompatibility JavaVersion.VERSION_11 @@ -81,6 +112,7 @@ android { buildFeatures { viewBinding true + buildConfig true } packaging { diff --git a/app/src/Chengwai/java/com/unibuy/smartdevice/ui/SaleFlowHandler.java b/app/src/Chengwai/java/com/unibuy/smartdevice/ui/SaleFlowHandler.java index 2ffca5e..bd597c7 100644 --- a/app/src/Chengwai/java/com/unibuy/smartdevice/ui/SaleFlowHandler.java +++ b/app/src/Chengwai/java/com/unibuy/smartdevice/ui/SaleFlowHandler.java @@ -24,6 +24,10 @@ public class SaleFlowHandler { // 晟崴版 UI 設定,預設無動作 } + public void onSetupUI(android.view.View rootView) { + // 晟崴版 UI 設定,預設無動作 + } + public void onBuyRequested() { new MemberCardPickupDialog(context, handlerMain).show(); } diff --git a/app/src/Cmuh/java/com/unibuy/smartdevice/ui/SaleFlowHandler.java b/app/src/Cmuh/java/com/unibuy/smartdevice/ui/SaleFlowHandler.java index e11e04b..636fe6e 100644 --- a/app/src/Cmuh/java/com/unibuy/smartdevice/ui/SaleFlowHandler.java +++ b/app/src/Cmuh/java/com/unibuy/smartdevice/ui/SaleFlowHandler.java @@ -15,6 +15,7 @@ import com.unibuy.smartdevice.exception.LogsUnsupportedOperationException; import com.unibuy.smartdevice.structure.BuyStructure; import com.unibuy.smartdevice.structure.MedicineStructure; import com.unibuy.smartdevice.structure.ProductStructure; +import com.unibuy.smartdevice.structure.SlotStructure; import com.unibuy.smartdevice.tools.HandlerMain; import com.unibuy.smartdevice.tools.HandlerMainSchedulerOnClick; import com.unibuy.smartdevice.ui.dialog.FontendPickupCodeDialog; @@ -28,6 +29,9 @@ import org.json.JSONObject; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; @@ -41,6 +45,9 @@ import javax.crypto.spec.SecretKeySpec; * 5. 顯示領藥與錯誤 Dialog */ public class SaleFlowHandler { + private static final String ORDC_EMPTY = "ORDC_EMPTY"; + private static final String MATERIAL_NOT_FOUND = "MATERIAL_NOT_FOUND"; + private static final String STOCK_NOT_ENOUGH = "STOCK_NOT_ENOUGH"; protected final Context context; protected final SaleFlowCallback callback; @@ -60,10 +67,17 @@ public class SaleFlowHandler { * 在 Activity 的 onResume() 中會被呼叫,此時尋找並綁定 VmcFragment 中的掃碼按鈕 */ public void onSetupUI() { + onSetupUI(null); + } + + public void onSetupUI(View rootView) { if (context instanceof Activity) { - View btnScan = ((Activity) context).findViewById(R.id.scanbarcodebtn); + View btnScan = rootView != null ? rootView.findViewById(R.id.scanbarcodebtn) : ((Activity) context).findViewById(R.id.scanbarcodebtn); if (btnScan != null) { btnScan.setOnClickListener(new BtnQrCodeOnClick(handlerMain, context)); + MyApp.getInstance().getLogs().info("✅ 成功在 Cmuh SaleFlowHandler 綁定掃碼按鈕!"); + } else { + MyApp.getInstance().getLogs().info("❌ 在 Cmuh SaleFlowHandler 找不到掃碼按鈕 R.id.scanbarcodebtn!"); } } } @@ -109,6 +123,7 @@ public class SaleFlowHandler { protected void execute(HandlerMain handlerMain) { handlerMain.start(getClass().getSimpleName(), "@40秒內刷條碼"); openBarcode = true; + haveValuestate = false; try { UsbDev usbDev = new UsbDev(DeviceType.QRCODE_SCANNER); byte[] buffer = new byte[1000]; @@ -211,13 +226,16 @@ public class SaleFlowHandler { MyApp.getInstance().setDecryptedData(""); MyApp.getInstance().setDecryptedData(new String(decryptedBytes, StandardCharsets.UTF_8).trim()); + MyApp.getInstance().setCmuhPickupErrorMessage(""); String decryptedStr = MyApp.getInstance().getDecryptedData(); MyApp.getInstance().getLogs().info("decryptedStr=" + decryptedStr); - + JSONObject jsonObject = new JSONObject(decryptedStr); + if (checkORDCDispatchNumber(decryptedStr)) { + return false; + } addMedicineToByulist(jsonObject); - checkORDCDispatchNumber(decryptedStr); // 判斷領藥號是否已經領過 } catch (Exception e) { throw new LogsParseException(MyApp.getInstance().getLogs(), "錯誤:加密數據長度不是 16 的倍數,可能需要填充"); @@ -226,55 +244,45 @@ public class SaleFlowHandler { } public void addMedicineToByulist(JSONObject jsonObject) { - JSONArray itemsArray = null; try { - itemsArray = jsonObject.getJSONArray("ITEM"); + JSONArray itemsArray = jsonObject.getJSONArray("ITEM"); // 清空 BuyList,確保每次掃描都是新的出貨清單 MyApp.getInstance().getBuyList().clear(); int MedicineCount = 0; // 同一種商品全部貨道的總數量 String MedicineName = "", MedicineSlot = "", MedicineImg = "", MedicinePId = "", MemoSnDrgno = ""; ArrayList medicineList = new ArrayList<>(); - - // 先進行預判,確認所有 ITEM 都能成功出貨才繼續後面流程 - boolean stockCheckPassed = true; // 預設檢查通過 + Map> materialSlotMap = buildMaterialSlotMap(); for (int i = 0; i < itemsArray.length(); i++) { JSONObject itemObject = itemsArray.getJSONObject(i); - String ordc = itemObject.optString("ORDC"); - int requestQty = Integer.parseInt(itemObject.optString("QTY")); + String ordc = itemObject.optString("ORDC", "").trim(); + int requestQty = safeParseInt(itemObject.optString("QTY"), 0); + + if (ordc.isEmpty()) { + failWithCode(ORDC_EMPTY, context.getString(R.string.cmuh_ordc_empty)); + return; + } + List matchedSlots = materialSlotMap.get(ordc); + if (matchedSlots == null || matchedSlots.isEmpty()) { + failWithCode(MATERIAL_NOT_FOUND, context.getString(R.string.cmuh_material_not_found, ordc)); + return; + } int totalStock = 0; - - for (int j = 0; j < MyApp.getInstance().getSlotList(0).size(); j++) { - if (ordc.equals(MyApp.getInstance().getSlotList(0).get(j).getProduct().getMaterialCode()) - && MyApp.getInstance().getSlotList(0).get(j).getCount() > 0 - && MyApp.getInstance().getSlotList(0).get(j).getCount() <= 20) { - totalStock += MyApp.getInstance().getSlotList(0).get(j).getCount(); - } + for (SlotStructure slotData : matchedSlots) { + totalStock += slotData.getCount(); } - - if (totalStock == 0) { - MyApp.getInstance().getLogs().info("預判失敗:ORDC = " + ordc + " 找不到貨道或庫存為0"); - String storename = "@商品 [" + ordc + "] 無庫存或未設定貨道,請確認。"; - handlerMain.start("無庫存或未設定貨道,請確認", storename); - stockCheckPassed = false; - break; - } else if (totalStock < requestQty) { - MyApp.getInstance().getLogs().info("預判失敗:ORDC = " + ordc + " 庫存不足,總庫存:" + totalStock + ",需求:" + requestQty); - String storename = "@商品 [" + ordc + "] 庫存不足,請補貨後再掃描。"; - handlerMain.start("庫存不足", storename); - stockCheckPassed = false; - break; + if (requestQty <= 0 || totalStock < requestQty) { + failWithCode(STOCK_NOT_ENOUGH, context.getString(R.string.cmuh_stock_not_enough, ordc, requestQty, totalStock)); + return; } } - if (!stockCheckPassed) { - return; // 直接結束,不進入後續流程 - } - MyApp.getInstance().getLogs().info("itemsArray.length" + itemsArray.length()); for (int i = 0; i < itemsArray.length(); i++) { JSONObject itemObject = itemsArray.getJSONObject(i); + String ordc = itemObject.optString("ORDC", "").trim(); + int requestQty = safeParseInt(itemObject.optString("QTY"), 0); // 重新初始化這些變數 MedicineName = ""; @@ -283,29 +291,24 @@ public class SaleFlowHandler { MedicineImg = ""; MedicinePId = ""; MemoSnDrgno = ""; - - for (int j = 0; j < MyApp.getInstance().getSlotList(0).size(); j++) { - if (itemObject.optString("ORDC").equals(MyApp.getInstance().getSlotList(0).get(j).getProduct().getMaterialCode()) - && MyApp.getInstance().getSlotList(0).get(j).getCount() > 0 - && MyApp.getInstance().getSlotList(0).get(j).getCount() <= 20) { - MedicineCount += MyApp.getInstance().getSlotList(0).get(j).getCount(); - MedicineSlot += MyApp.getInstance().getSlotList(0).get(j).getSlot() + "-" + MyApp.getInstance().getSlotList(0).get(j).getCount() + ","; - - if (MedicineCount >= Integer.valueOf(itemObject.optString("QTY"))) { - MedicinePId = MyApp.getInstance().getSlotList(0).get(j).getProduct().getProductID(); - MedicineName = MyApp.getInstance().getSlotList(0).get(j).getProduct().getProductName(); - MedicineImg = MyApp.getInstance().getSlotList(0).get(j).getProduct().getProductImg(); - MemoSnDrgno = "{\"SN\": \"" + jsonObject.optString("SN") + "\", \"DRGNO\": \"" + jsonObject.optString("DRGNO") + "\"}"; - } + List matchedSlots = materialSlotMap.get(ordc); + for (SlotStructure matchedSlot : matchedSlots) { + MedicineCount += matchedSlot.getCount(); + MedicineSlot += matchedSlot.getSlot() + "-" + matchedSlot.getCount() + ","; + if (MedicineCount >= requestQty) { + MedicinePId = matchedSlot.getProduct().getProductID(); + MedicineName = matchedSlot.getProduct().getProductName(); + MedicineImg = matchedSlot.getProduct().getProductImg(); + MemoSnDrgno = "{\"SN\": \"" + jsonObject.optString("SN") + "\", \"DRGNO\": \"" + jsonObject.optString("DRGNO") + "\"}"; } } - medicineList.add(new MedicineStructure(itemObject.optString("ORDC"), MedicineCount, MedicineName, MedicineSlot, MedicineImg, MedicinePId, MemoSnDrgno)); + medicineList.add(new MedicineStructure(ordc, MedicineCount, MedicineName, MedicineSlot, MedicineImg, MedicinePId, MemoSnDrgno)); } /* 這裡將商品依據領藥數量加入 BuyList */ for (int i = 0; i < itemsArray.length(); i++) { JSONObject itemObject = itemsArray.getJSONObject(i); - int requestQty = Integer.parseInt(itemObject.optString("QTY")); + int requestQty = safeParseInt(itemObject.optString("QTY"), 0); if (requestQty <= medicineList.get(i).getMedicineCount()) { haveValuestate = true; @@ -351,6 +354,38 @@ public class SaleFlowHandler { } } + private Map> buildMaterialSlotMap() { + Map> materialSlotMap = new HashMap<>(); + List slotList = MyApp.getInstance().getSlotList(0); + for (SlotStructure slotData : slotList) { + if (slotData == null || slotData.getProduct() == null) continue; + String productId = slotData.getProduct().getProductID(); + String materialCode = slotData.getProduct().getMaterialCode(); + if (productId == null || productId.isEmpty() || "?".equals(productId)) continue; + if (materialCode == null || materialCode.trim().isEmpty()) continue; + if (slotData.getCount() <= 0 || slotData.getCount() > 20) continue; + materialSlotMap.computeIfAbsent(materialCode.trim(), k -> new ArrayList<>()).add(slotData); + } + return materialSlotMap; + } + + private int safeParseInt(String value, int defaultValue) { + try { + return Integer.parseInt(value); + } catch (Exception ignored) { + return defaultValue; + } + } + + private void failWithCode(String code, String message) { + String finalMessage = "@" + code + " " + message; + MyApp.getInstance().getLogs().info("[" + code + "] " + message); + MyApp.getInstance().setCmuhPickupErrorMessage(finalMessage.substring(1)); + haveValuestate = false; + openBarcode = false; + MyApp.getInstance().getBuyList().clear(); + } + public void addMedicineToBuyList(String MedicinePidStr, String MedicineNameStr, int SlotNumber, String MedicineImg, String MemoSnDrgno, int count) { ProductStructure productStructure = new ProductStructure(MedicinePidStr, MedicineImg, MedicineNameStr, 0, 0, 0, 0, MemoSnDrgno, "", "", ""); MyApp.getInstance().getLogs().info("aaaaaa " + MedicinePidStr + " " + MemoSnDrgno + " " + MedicineNameStr); @@ -358,7 +393,7 @@ public class SaleFlowHandler { MyApp.getInstance().getBuyList().add(buyProduct); } - public void checkORDCDispatchNumber(String decryptedStr) throws JSONException { + public boolean checkORDCDispatchNumber(String decryptedStr) throws JSONException { JSONObject jsonObject = new JSONObject(decryptedStr); JSONObject newItem = new JSONObject(); newItem.put("SN", jsonObject.optString("SN")); @@ -380,8 +415,11 @@ public class SaleFlowHandler { if (exists) { MyApp.getInstance().getLogs().info("⚠️ 此項目已存在,不新增!"); openBarcode = false; - handlerMain.start(getClass().getSimpleName(), "@此單已取物完成,請洽藥局發藥窗口!"); + haveValuestate = false; + MyApp.getInstance().setCmuhPickupErrorMessage("此單已取物完成,請洽藥局發藥窗口!"); MyApp.getInstance().getBuyList().clear(); + return true; } + return false; } } diff --git a/app/src/Cmuh/java/com/unibuy/smartdevice/ui/dialog/PickupErrorTipDialog.java b/app/src/Cmuh/java/com/unibuy/smartdevice/ui/dialog/PickupErrorTipDialog.java index 4866868..ee595df 100644 --- a/app/src/Cmuh/java/com/unibuy/smartdevice/ui/dialog/PickupErrorTipDialog.java +++ b/app/src/Cmuh/java/com/unibuy/smartdevice/ui/dialog/PickupErrorTipDialog.java @@ -1,10 +1,11 @@ package com.unibuy.smartdevice.ui.dialog; -import android.content.Context; - -import com.unibuy.smartdevice.DialogAbstract; -import com.unibuy.smartdevice.MyApp; -import com.unibuy.smartdevice.databinding.DialogPickupErrorTipBinding; +import android.content.Context; + +import com.unibuy.smartdevice.DialogAbstract; +import com.unibuy.smartdevice.MyApp; +import com.unibuy.smartdevice.R; +import com.unibuy.smartdevice.databinding.DialogPickupErrorTipBinding; import com.unibuy.smartdevice.structure.BuyStructure; import com.unibuy.smartdevice.structure.ProductStructure; import com.unibuy.smartdevice.tools.HandlerMain; @@ -103,15 +104,20 @@ public class PickupErrorTipDialog extends DialogAbstract { String decryptedStr = MyApp.getInstance().getDecryptedData(); getLogs().info(decryptedStr); - try { - JSONObject jsonObject = new JSONObject(decryptedStr); - binding.tvDrgnoid.setText("領藥號:"+jsonObject.optString("DRGNO")); - } catch (JSONException e) { - getLogs().warning(e); - } - - closeDialogCountdown = new CloseDialogOnThreadHandler(getHandlerMain()); - closeDialogCountdown.start(40); + try { + JSONObject jsonObject = new JSONObject(decryptedStr); + binding.tvDrgnoid.setText("領藥號:"+jsonObject.optString("DRGNO")); + } catch (JSONException e) { + getLogs().warning(e); + } + String errorMessage = MyApp.getInstance().getCmuhPickupErrorMessage(); + if (errorMessage == null || errorMessage.trim().isEmpty()) { + errorMessage = getCtx().getString(R.string.cmuh_pickup_failed_contact_counter); + } + binding.tvErrorMessage.setText(errorMessage); + + closeDialogCountdown = new CloseDialogOnThreadHandler(getHandlerMain()); + closeDialogCountdown.start(40); binding.btnNonPerson.setOnClickListener(v -> dialogCancel()); } @@ -140,11 +146,11 @@ public class PickupErrorTipDialog extends DialogAbstract { }*/ getTools().dialogClose(); cancel(); - } - - public void setButtonCancelText(long countdown) { - binding.btnNonPerson.setText("否("+countdown+")"); - } + } + + public void setButtonCancelText(long countdown) { + binding.btnNonPerson.setText(getCtx().getString(R.string.close_countdown, countdown)); + } public static class CloseDialogOnThreadHandler extends HandlerMainCountdown { public CloseDialogOnThreadHandler(HandlerMain handlerMain) { diff --git a/app/src/Cmuh/res/layout/dialog_pickup_error_tip.xml b/app/src/Cmuh/res/layout/dialog_pickup_error_tip.xml index 2ee699b..334cb42 100644 --- a/app/src/Cmuh/res/layout/dialog_pickup_error_tip.xml +++ b/app/src/Cmuh/res/layout/dialog_pickup_error_tip.xml @@ -34,13 +34,16 @@ app:layout_constraintTop_toBottomOf="@+id/linearLayout211" tools:ignore="MissingConstraints"> - + + android:layout_height="wrap_content" + android:layout_weight="1" + android:text="@string/close_40" + android:textSize="30sp" + tools:ignore="MissingConstraints" /> - \ No newline at end of file + diff --git a/app/src/General/java/com/unibuy/smartdevice/ui/SaleFlowHandler.java b/app/src/General/java/com/unibuy/smartdevice/ui/SaleFlowHandler.java index f91a78d..2c325b6 100644 --- a/app/src/General/java/com/unibuy/smartdevice/ui/SaleFlowHandler.java +++ b/app/src/General/java/com/unibuy/smartdevice/ui/SaleFlowHandler.java @@ -24,6 +24,10 @@ public class SaleFlowHandler { // 通用版 UI 設定,預設無動作 } + public void onSetupUI(android.view.View rootView) { + // 通用版 UI 設定,預設無動作 + } + public void onBuyRequested() { new BuyDialog(context, handlerMain).show(); } diff --git a/app/src/main/java/com/unibuy/smartdevice/MainActivity.java b/app/src/main/java/com/unibuy/smartdevice/MainActivity.java index 497f3e0..fa05f28 100644 --- a/app/src/main/java/com/unibuy/smartdevice/MainActivity.java +++ b/app/src/main/java/com/unibuy/smartdevice/MainActivity.java @@ -13,6 +13,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.Process; import android.text.InputType; +import android.util.Log; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; @@ -60,8 +61,10 @@ import com.unibuy.smartdevice.ui.tools.VideoImageMixedPlayer; import com.unibuy.smartdevice.utils.LanguageHelper; import java.util.List; +import java.util.Locale; public class MainActivity extends AppCompatActivityAbstract { + private static final String LOGIN_TRACE_TAG = "LoginTrace"; @Override protected Context setCtx() { return this; @@ -81,6 +84,11 @@ public class MainActivity extends AppCompatActivityAbstract { public void execute(Context context, int commandCode, String message) { super.execute(context, commandCode, message); if ("登入成功".equals(message)) { + if (pendingLoginTraceId != null) { + long now = System.currentTimeMillis(); + Log.i(LOGIN_TRACE_TAG, "[" + pendingLoginTraceId + "] callback=success totalMs=" + + (now - pendingLoginStartMs) + " msg=" + message); + } updateLoginStatus(); if (activeLoginDialog != null && activeLoginDialog.isShowing()) { activeLoginDialog.dismiss(); @@ -90,6 +98,15 @@ public class MainActivity extends AppCompatActivityAbstract { pendingAction.run(); pendingAction = null; } + pendingLoginTraceId = null; + pendingLoginStartMs = 0L; + } else if (pendingLoginTraceId != null && message != null + && (message.contains("登入失敗") || message.contains("網路錯誤") || message.contains("解析失敗"))) { + long now = System.currentTimeMillis(); + Log.w(LOGIN_TRACE_TAG, "[" + pendingLoginTraceId + "] callback=failure totalMs=" + + (now - pendingLoginStartMs) + " msg=" + message + " code=" + commandCode); + pendingLoginTraceId = null; + pendingLoginStartMs = 0L; } } }; @@ -99,6 +116,8 @@ public class MainActivity extends AppCompatActivityAbstract { private HttpAPI httpAPI; private StarCloudAPI starCloudAPI; private Runnable pendingAction; + private String pendingLoginTraceId; + private long pendingLoginStartMs; @Override protected void onCreate(Bundle savedInstanceState) { @@ -563,10 +582,14 @@ public class MainActivity extends AppCompatActivityAbstract { // 設定點擊事件 positiveButton.setOnClickListener(v -> { + long clickStartMs = System.currentTimeMillis(); String access = accessInput.getText().toString().trim(); String password = passwordInput.getText().toString().trim(); + String traceId = String.format(Locale.US, "L%tH% marketingPlanList; private List buyList; private String decryptedData; + private String cmuhPickupErrorMessage; private Map> memoMap; private CashSetStructure cashSetStructure; private AccessCodeStructure accessCodeStructure; @@ -410,6 +411,45 @@ public class MyApp extends Application { ); } + public static boolean checkAndReconnectDev() { + boolean isAlive = false; + Logs staticLogs = new Logs(MyApp.class); + + if (devXinYuanController != null) { + try { + // 發送同步包測試 + devXinYuanController.addSendBuffer( + devXinYuanController.getDevXinYuan().syncPackNo((byte) 0x01) + ); + Thread.sleep(100); + if (!devXinYuanController.getReadBufferByMax().isEmpty()) { + isAlive = true; + } + } catch (Exception e) { + isAlive = false; + } + } + + // 若不活躍則重連 + if (!isAlive) { + staticLogs.info("下位機失連,重新連線中..."); + if (devXinYuanController != null) { + devXinYuanController.shutdown(); + } + devXinYuanController = new DevXinYuanController(devXinYuanController.getHandlerMain()); + devXinYuanController.start(); + devXinYuanController.addSendBuffer( + devXinYuanController.getDevXinYuan().syncPackNo((byte) 0x01) + ); + try { + Thread.sleep(200); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + return true; + } + public void initMqtt() { String machineId = MyApp.getInstance().getMachine().getMachineID(); String apiKey = MyApp.getInstance().getMachine().getApiKey(); @@ -683,6 +723,14 @@ public class MyApp extends Application { return decryptedData; } + public void setCmuhPickupErrorMessage(String cmuhPickupErrorMessage) { + this.cmuhPickupErrorMessage = cmuhPickupErrorMessage; + } + + public String getCmuhPickupErrorMessage() { + return cmuhPickupErrorMessage; + } + public Map> getMemoMap() { return memoMap; } diff --git a/app/src/main/java/com/unibuy/smartdevice/devices/ComPort.java b/app/src/main/java/com/unibuy/smartdevice/devices/ComPort.java index b603ca6..e0c6e0a 100644 --- a/app/src/main/java/com/unibuy/smartdevice/devices/ComPort.java +++ b/app/src/main/java/com/unibuy/smartdevice/devices/ComPort.java @@ -46,6 +46,18 @@ public enum ComPort { } public String getFilepath() { + if (this == COM_PORT_S1) { + if ("Cmuh".equalsIgnoreCase(com.unibuy.smartdevice.BuildConfig.FLAVOR_project)) { + return "/dev/ttyS1"; + } + return "/dev/ttyS7"; + } + if (this == COM_PORT_S2) { + if ("Cmuh".equalsIgnoreCase(com.unibuy.smartdevice.BuildConfig.FLAVOR_project)) { + return "/dev/ttyS2"; + } + return "/dev/ttyS6"; + } return filepath; } diff --git a/app/src/main/java/com/unibuy/smartdevice/exception/Logs.java b/app/src/main/java/com/unibuy/smartdevice/exception/Logs.java index 3194488..913288b 100644 --- a/app/src/main/java/com/unibuy/smartdevice/exception/Logs.java +++ b/app/src/main/java/com/unibuy/smartdevice/exception/Logs.java @@ -12,6 +12,7 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; @@ -37,7 +38,7 @@ public class Logs { return className; } - public void writeFile(String data) { + public synchronized void writeFile(String data) { File txtDebug = new File(Tools.getExternalFilesDir(), "debug.txt"); if (txtDebug.exists()) { txtDebug.setReadable(true, false); @@ -48,8 +49,9 @@ public class Logs { data = dateTime + " " + data; try (FileOutputStream fos = new FileOutputStream(txtDebug, true)) { // try-with-resources 自動 close() - fos.write(data.getBytes()); - fos.write("\n".getBytes()); // 換行 + fos.write(data.getBytes(StandardCharsets.UTF_8)); + fos.write("\n".getBytes(StandardCharsets.UTF_8)); // 換行 + fos.flush(); } catch (IOException e) { warning(e); } diff --git a/app/src/main/java/com/unibuy/smartdevice/external/HttpAPI.java b/app/src/main/java/com/unibuy/smartdevice/external/HttpAPI.java index f4339a4..ca950be 100644 --- a/app/src/main/java/com/unibuy/smartdevice/external/HttpAPI.java +++ b/app/src/main/java/com/unibuy/smartdevice/external/HttpAPI.java @@ -133,11 +133,9 @@ public class HttpAPI { private Logs logs; private static String domainName = "https://demo-cloud.setdomains.work/"; private String domainNameByUnibuy = domainName + "api/v1/app/"; -// private String domainNameByUnibuy = domainName + "Unibuy/api/app/"; + // private String domainNameByUnibuy = domainName + "Unibuy/api/app/"; private String domainNameByAAT = domainName + "AAT/api/app/"; -// private String domainNameByAAT = domainName + "chi-hai-API/api/app/"; - public static String domainNameByNewHost = "http://152.42.211.122:8000/"; - public static String updateOnDomainNameByNewHost = HttpAPI.domainNameByNewHost + "api/machine/" + MyApp.getInstance().getMachine().getMachineID() + "/log/update"; + // private String domainNameByAAT = domainName + "chi-hai-API/api/app/"; private String esunpayApi = "https://mpayment.esuntrade.com/mPay/GatewayV2/API/V2/xTrade.ashx"; private HandlerMain handlerMain; private HandlerMain srcHandlerMain; @@ -183,11 +181,11 @@ public class HttpAPI { if (isReloadApi()) { getLogs().info("Reload Api download setting data"); try { - //uploadProductInfo(); + // uploadProductInfo(); downloadProductInfo(); getLogs().info("DOWNLOAD_SETTING_RESPONSE1"); } catch (LogsSettingEmptyException | LogsParseException e) { -// exception(context, e.getErrorCode(), e.getLocalizedMessage()); + // exception(context, e.getErrorCode(), e.getLocalizedMessage()); getLogs().warning(e); } } else { @@ -196,7 +194,7 @@ public class HttpAPI { downloadProductInfo(); getLogs().info("DOWNLOAD_SETTING_RESPONSE2"); } catch (LogsSettingEmptyException | LogsParseException e) { -// exception(context, e.getErrorCode(), e.getLocalizedMessage()); + // exception(context, e.getErrorCode(), e.getLocalizedMessage()); getLogs().warning(e); } } @@ -204,13 +202,14 @@ public class HttpAPI { case DOWNLOAD_PRODUCT_RESPONSE: if (isReloadApi()) { getLogs().info("Reload Api download images data"); - getSrcHandlerMain().start("HttpApi", RestartHostActivity.Option.IMAGE_RELOAD.getOption(), "image reload"); + getSrcHandlerMain().start("HttpApi", RestartHostActivity.Option.IMAGE_RELOAD.getOption(), + "image reload"); } else { super.execute(context, commandCode, message); try { downloadAdvertisement(); } catch (LogsSettingEmptyException | LogsParseException e) { -// exception(context, e.getErrorCode(), e.getLocalizedMessage()); + // exception(context, e.getErrorCode(), e.getLocalizedMessage()); getLogs().warning(e); } } @@ -219,10 +218,12 @@ public class HttpAPI { if (isReloadApi()) { super.execute(context, commandCode, message); getLogs().info("Reload Api download ok"); - getSrcHandlerMain().start("HttpApi", RestartHostActivity.Option.BACK_HOME.getOption(), "back home"); + getSrcHandlerMain().start("HttpApi", RestartHostActivity.Option.BACK_HOME.getOption(), + "back home"); } else { super.execute(context, commandCode, message); - getSrcHandlerMain().start(getClass().getSimpleName(), SettingActivity.Option.CHECK_AND_SAVE_STATUS.getOption(), "檢測中"); + getSrcHandlerMain().start(getClass().getSimpleName(), + SettingActivity.Option.CHECK_AND_SAVE_STATUS.getOption(), "檢測中"); } isReloadApi = false; break; @@ -237,15 +238,17 @@ public class HttpAPI { case GREEN_INVOICE_RESPONSE: try { JSONObject jsonObject = new JSONObject(message); - String[] names = new String[]{ + String[] names = new String[] { "rtnCode", "rtnMsg", "invoiceNo", "invoiceDate", "randomNumber", "loveCode" }; MyApp.getInstance().getReportInvoiceInfoData().setRtnCode(jsonObject.getString(names[0])); MyApp.getInstance().getReportInvoiceInfoData().setRtnMsg(jsonObject.getString(names[1])); MyApp.getInstance().getReportInvoiceInfoData().setInvoiceNo(jsonObject.getString(names[2])); - MyApp.getInstance().getReportInvoiceInfoData().setInvoiceDate(jsonObject.getString(names[3])); - MyApp.getInstance().getReportInvoiceInfoData().setRandomNumber(jsonObject.getString(names[4])); + MyApp.getInstance().getReportInvoiceInfoData() + .setInvoiceDate(jsonObject.getString(names[3])); + MyApp.getInstance().getReportInvoiceInfoData() + .setRandomNumber(jsonObject.getString(names[4])); MyApp.getInstance().getReportInvoiceInfoData().setLoveCode(jsonObject.getString(names[5])); reportInvoiceInfo(MyApp.getInstance().getReportInvoiceInfoData()); @@ -277,32 +280,34 @@ public class HttpAPI { public void response(int responseCode, String receive, HandlerMain handlerMain) { if (responseCode == 200) { try { - //{"message":"reboot","workID":"B010","status":"51"} + // {"message":"reboot","workID":"B010","status":"51"} JSONObject receiveByJsonObject = new JSONObject(receive); String workID = receiveByJsonObject.getString("workID"); int status = receiveByJsonObject.getInt("status"); String message = receiveByJsonObject.getString("message"); switch (status) { - case 49: //reload api - getSrcHandlerMain().start("HttpApi", FontendActivity.Option.RESET_SLOTNO.getOption(), "reset slot no."); + case 49: // reload api + getSrcHandlerMain().start("HttpApi", FontendActivity.Option.RESET_SLOTNO.getOption(), + "reset slot no."); MyApp.getInstance().setDetectHost(false); break; - case 51: //reboot - getSrcHandlerMain().start("HttpApi", FontendActivity.Option.RESTART_HOST.getOption(), "restart host"); + case 51: // reboot + getSrcHandlerMain().start("HttpApi", FontendActivity.Option.RESTART_HOST.getOption(), + "restart host"); break; - case 60: //reboot card machine + case 60: // reboot card machine new MainActivity.ButtonNfcResetOnClick(handlerMain).start(); MyApp.getInstance().setDetectHost(false); break; - case 61: //checkout + case 61: // checkout new MainActivity.ButtonNfcCheckoutOnClick(handlerMain).start(); MyApp.getInstance().setDetectHost(false); break; - case 70: //unlock + case 70: // unlock MyApp.getInstance().setDetectHost(false); break; - case 71: //lock + case 71: // lock MyApp.getInstance().setDetectHost(false); break; default: @@ -326,7 +331,8 @@ public class HttpAPI { }); } - private void detectHost(FormPostMainScheduler formPostRunMain) throws LogsSettingEmptyException, LogsParseException { + private void detectHost(FormPostMainScheduler formPostRunMain) + throws LogsSettingEmptyException, LogsParseException { checkMachineInfo(); try { @@ -339,7 +345,8 @@ public class HttpAPI { jsonObject.put("M_Stus2", "1"); jsonObject.put("M_Ver", DevXinYuanController.getVersion()); - formPostRunMain.start(domainNameByUnibuy + "machine/status/B010", jsonObject.toString(), null, null, HttpConnect.ContentType.X_WWW_FORM_URLENCODEED); + formPostRunMain.start(domainNameByUnibuy + "machine/status/B010", jsonObject.toString(), null, null, + HttpConnect.ContentType.X_WWW_FORM_URLENCODEED); } catch (JSONException e) { throw new LogsParseException(logs, ErrorCode.JSON_FORMAT_ERROR, e); } @@ -377,7 +384,8 @@ public class HttpAPI { }, account, password); } - private void login(FormPostMainScheduler formPostRunMain, String account, String password) throws LogsSettingEmptyException, LogsParseException { + private void login(FormPostMainScheduler formPostRunMain, String account, String password) + throws LogsSettingEmptyException, LogsParseException { checkMachineInfo(); try { @@ -387,27 +395,30 @@ public class HttpAPI { jsonObject.put("Su_Password", password); jsonObject.put("ip", "192.168.1.100"); jsonObject.put("type", "2"); - formPostRunMain.start(domainNameByUnibuy + "admin/login/B000", jsonObject.toString(), null, null, HttpConnect.ContentType.X_WWW_FORM_URLENCODEED); + formPostRunMain.start(domainNameByUnibuy + "admin/login/B000", jsonObject.toString(), null, null, + HttpConnect.ContentType.X_WWW_FORM_URLENCODEED); } catch (JSONException e) { throw new LogsParseException(logs, ErrorCode.JSON_FORMAT_ERROR, e); } } -// public void errorPost(int SlotID, String message, FormPostMainScheduler formPostRunMain) throws LogsSettingEmptyException, LogsParseException { -// checkMachineInfo(); -// -// try { -// JSONObject json = new JSONObject(); -// json.put("key", MyApp.getInstance().getMachine().getApiKey()); -// json.put("machine", MyApp.getInstance().getMachine().getMachineID()); -// json.put("tid", String.valueOf(SlotID)); -// json.put("type", message); -// json.put("time", System.currentTimeMillis()); -// formPostRunMain.start(domainNameByUnibuy + "machine/error_msg/B013", json.toString(), null, null, HttpConnect.ContentType.X_WWW_FORM_URLENCODEED); -// } catch (JSONException e) { -// throw new LogsParseException(logs, ErrorCode.JSON_FORMAT_ERROR, e); -// } -// } + // public void errorPost(int SlotID, String message, FormPostMainScheduler + // formPostRunMain) throws LogsSettingEmptyException, LogsParseException { + // checkMachineInfo(); + // + // try { + // JSONObject json = new JSONObject(); + // json.put("key", MyApp.getInstance().getMachine().getApiKey()); + // json.put("machine", MyApp.getInstance().getMachine().getMachineID()); + // json.put("tid", String.valueOf(SlotID)); + // json.put("type", message); + // json.put("time", System.currentTimeMillis()); + // formPostRunMain.start(domainNameByUnibuy + "machine/error_msg/B013", + // json.toString(), null, null, HttpConnect.ContentType.X_WWW_FORM_URLENCODEED); + // } catch (JSONException e) { + // throw new LogsParseException(logs, ErrorCode.JSON_FORMAT_ERROR, e); + // } + // } public void errorPost(int slotId, String message) throws LogsSettingEmptyException, LogsParseException { errorPost(slotId, message, new FormPostMainScheduler(getSrcHandlerMain()) { @@ -424,21 +435,21 @@ public class HttpAPI { @Override public void response(int responseCode, String receive, HandlerMain handlerMain) { - - if (responseCode == 200) { try { JSONObject response = new JSONObject(receive); // 處理成功響應 Log.i("API", "Error post successful: " + response.toString()); -// handlerMain.start(getClass().getSimpleName(), Option.TOAST.getOption(), "@B013 送出成功 code=" + responseCode); + // handlerMain.start(getClass().getSimpleName(), Option.TOAST.getOption(), + // "@B013 送出成功 code=" + responseCode); } catch (JSONException e) { Log.e("API", "Error parsing response", e); handlerMain.start(getClass().getSimpleName(), Option.TOAST.getOption(), "@B013 回應解析錯誤"); } } else { Log.e("API", "Error post failed with code: " + responseCode); - handlerMain.start(getClass().getSimpleName(), Option.TOAST.getOption(), "@B013 送出失敗 code=" + responseCode); + handlerMain.start(getClass().getSimpleName(), Option.TOAST.getOption(), + "@B013 送出失敗 code=" + responseCode); } } }); @@ -460,8 +471,7 @@ public class HttpAPI { json.toString(), null, null, - HttpConnect.ContentType.JSON - ); + HttpConnect.ContentType.JSON); } catch (JSONException e) { throw new LogsParseException(logs, ErrorCode.JSON_FORMAT_ERROR, e); } @@ -547,7 +557,9 @@ public class HttpAPI { } } - if (jsonObject.has("TP_APP_ID") && !jsonObject.getString("TP_APP_ID").isEmpty() && jsonObject.has("TP_PARTNER_KEY") && !jsonObject.getString("TP_PARTNER_KEY").isEmpty()) { + if (jsonObject.has("TP_APP_ID") && !jsonObject.getString("TP_APP_ID").isEmpty() + && jsonObject.has("TP_PARTNER_KEY") + && !jsonObject.getString("TP_PARTNER_KEY").isEmpty()) { String tpAppId = jsonObject.getString("TP_APP_ID"); String tpAppKey = jsonObject.getString("TP_APP_KEY"); MyApp.getInstance().getGreenpaySetting().setAppId(tpAppId); @@ -558,27 +570,32 @@ public class HttpAPI { MyApp.getInstance().getGreenpaySetting().setPartnerKey(tpPartnerkey); } - if (jsonObject.has("TP_LINE_MERCHANT_ID") && !jsonObject.getString("TP_LINE_MERCHANT_ID").isEmpty()) { + if (jsonObject.has("TP_LINE_MERCHANT_ID") + && !jsonObject.getString("TP_LINE_MERCHANT_ID").isEmpty()) { String lineMerchantId = jsonObject.getString("TP_LINE_MERCHANT_ID"); MyApp.getInstance().getGreenpayMerchant().setLineMerchantId(lineMerchantId); } - if (jsonObject.has("TP_PS_MERCHANT_ID") && !jsonObject.getString("TP_PS_MERCHANT_ID").isEmpty()) { + if (jsonObject.has("TP_PS_MERCHANT_ID") + && !jsonObject.getString("TP_PS_MERCHANT_ID").isEmpty()) { String psMerchantId = jsonObject.getString("TP_PS_MERCHANT_ID"); MyApp.getInstance().getGreenpayMerchant().setPsMerchantId(psMerchantId); } - if (jsonObject.has("TP_EASY_MERCHANT_ID") && !jsonObject.getString("TP_EASY_MERCHANT_ID").isEmpty()) { + if (jsonObject.has("TP_EASY_MERCHANT_ID") + && !jsonObject.getString("TP_EASY_MERCHANT_ID").isEmpty()) { String easyMerchantId = jsonObject.getString("TP_EASY_MERCHANT_ID"); MyApp.getInstance().getGreenpayMerchant().setEasyMerchantId(easyMerchantId); } - if (jsonObject.has("TP_PI_MERCHANT_ID") && !jsonObject.getString("TP_PI_MERCHANT_ID").isEmpty()) { + if (jsonObject.has("TP_PI_MERCHANT_ID") + && !jsonObject.getString("TP_PI_MERCHANT_ID").isEmpty()) { String piMerchantId = jsonObject.getString("TP_PI_MERCHANT_ID"); MyApp.getInstance().getGreenpayMerchant().setPiMerchantId(piMerchantId); } - if (jsonObject.has("TP_JKO_MERCHANT_ID") && !jsonObject.getString("TP_JKO_MERCHANT_ID").isEmpty()) { + if (jsonObject.has("TP_JKO_MERCHANT_ID") + && !jsonObject.getString("TP_JKO_MERCHANT_ID").isEmpty()) { String jkoMerchantId = jsonObject.getString("TP_JKO_MERCHANT_ID"); MyApp.getInstance().getGreenpayMerchant().setJkoMerchantId(jkoMerchantId); } @@ -587,29 +604,33 @@ public class HttpAPI { SettingsDao settingsDao = new SettingsDao(getSrcHandlerMain().getContext()); settingsDao.deleteAll(); - settingsDao.insertOne(new SettingStructure(MyApp.getInstance().getMachine().getClass().getSimpleName(), - new String[]{ - MyApp.getInstance().getMachine().getApiKey(), - MyApp.getInstance().getMachine().getMachineID() - })); + settingsDao.insertOne( + new SettingStructure(MyApp.getInstance().getMachine().getClass().getSimpleName(), + new String[] { + MyApp.getInstance().getMachine().getApiKey(), + MyApp.getInstance().getMachine().getMachineID() + })); - settingsDao.insertOne(new SettingStructure(MyApp.getInstance().getEsunpay().getClass().getSimpleName(), - new String[]{ - MyApp.getInstance().getEsunpay().getStoreID(), - MyApp.getInstance().getEsunpay().getTermID(), - MyApp.getInstance().getEsunpay().getHash() - })); + settingsDao.insertOne( + new SettingStructure(MyApp.getInstance().getEsunpay().getClass().getSimpleName(), + new String[] { + MyApp.getInstance().getEsunpay().getStoreID(), + MyApp.getInstance().getEsunpay().getTermID(), + MyApp.getInstance().getEsunpay().getHash() + })); - settingsDao.insertOne(new SettingStructure(MyApp.getInstance().getGreenInvoice().getClass().getSimpleName(), - new String[]{ - MyApp.getInstance().getGreenInvoice().getGreenMerchantID(), - MyApp.getInstance().getGreenInvoice().getGreenHashKey(), - MyApp.getInstance().getGreenInvoice().getGreenHashIV(), - MyApp.getInstance().getGreenInvoice().getGreenEmail() - })); + settingsDao.insertOne( + new SettingStructure(MyApp.getInstance().getGreenInvoice().getClass().getSimpleName(), + new String[] { + MyApp.getInstance().getGreenInvoice().getGreenMerchantID(), + MyApp.getInstance().getGreenInvoice().getGreenHashKey(), + MyApp.getInstance().getGreenInvoice().getGreenHashIV(), + MyApp.getInstance().getGreenInvoice().getGreenEmail() + })); - settingsDao.insertOne(new SettingStructure(MyApp.getInstance().getGreenpaySetting().getClass().getSimpleName(), - new String[]{ + settingsDao.insertOne(new SettingStructure( + MyApp.getInstance().getGreenpaySetting().getClass().getSimpleName(), + new String[] { String.valueOf(MyApp.getInstance().getGreenpaySetting().getAppId()), MyApp.getInstance().getGreenpaySetting().getAppKey(), MyApp.getInstance().getGreenpaySetting().getPartnerKey(), @@ -620,8 +641,9 @@ public class HttpAPI { MyApp.getInstance().getGreenpaySetting().getGpuseMerchantId() })); - settingsDao.insertOne(new SettingStructure(MyApp.getInstance().getGreenpayMerchant().getClass().getSimpleName(), - new String[]{ + settingsDao.insertOne(new SettingStructure( + MyApp.getInstance().getGreenpayMerchant().getClass().getSimpleName(), + new String[] { MyApp.getInstance().getGreenpayMerchant().getLineMerchantId(), MyApp.getInstance().getGreenpayMerchant().getPsMerchantId(), MyApp.getInstance().getGreenpayMerchant().getEasyMerchantId(), @@ -642,7 +664,8 @@ public class HttpAPI { getLogs().warning(e); } - handlerMain.start(getClass().getSimpleName(), Option.DOWNLOAD_SETTING_RESPONSE.getOption(), "儲存設定資料"); + handlerMain.start(getClass().getSimpleName(), Option.DOWNLOAD_SETTING_RESPONSE.getOption(), + "儲存設定資料"); } else { getLogs().error(ErrorCode.NETWORK_UNKNOWN_ERROR, "Response code error:" + responseCode); } @@ -650,15 +673,16 @@ public class HttpAPI { }); } - - private void downloadSetting(FormPostMainScheduler formPostRunMain) throws LogsSettingEmptyException, LogsParseException { -// checkMachineInfo(); + private void downloadSetting(FormPostMainScheduler formPostRunMain) + throws LogsSettingEmptyException, LogsParseException { + // checkMachineInfo(); try { JSONObject jsonObject = new JSONObject(); jsonObject.put("key", MyApp.getInstance().getMachine().getApiKey()); jsonObject.put("machine", MyApp.getInstance().getMachine().getMachineID()); - formPostRunMain.start(domainNameByUnibuy + "machine/setting/B014", jsonObject.toString(), null, null, HttpConnect.ContentType.X_WWW_FORM_URLENCODEED); + formPostRunMain.start(domainNameByUnibuy + "machine/setting/B014", jsonObject.toString(), null, null, + HttpConnect.ContentType.X_WWW_FORM_URLENCODEED); } catch (JSONException e) { throw new LogsParseException(logs, ErrorCode.JSON_FORMAT_ERROR, e); } @@ -687,16 +711,16 @@ public class HttpAPI { JSONObject productData = productItem.getJSONObject(i); /* - t060v09 售價 - t060v30 會員價 - t060v00 商品ID - t060v11 貨道上限 - t063v03 機台的商品價格 - t060v01 "啵啵魚捲", - t060v06 "https://unibuy.com.tw/Unibuy/dist/img/products/53317506.png", - */ + * t060v09 售價 + * t060v30 會員價 + * t060v00 商品ID + * t060v11 貨道上限 + * t063v03 機台的商品價格 + * t060v01 "啵啵魚捲", + * t060v06 "https://unibuy.com.tw/Unibuy/dist/img/products/53317506.png", + */ - getLogs().info("AAAAAAAAAAAAAAAAAAAAAAA"+productData); + getLogs().info("AAAAAAAAAAAAAAAAAAAAAAA" + productData); if (productData.has("t060v00") && productData.has("t060v06") && @@ -708,8 +732,7 @@ public class HttpAPI { productData.has("t060v40") && productData.has("t060v41") && productData.has("t060v01_en") && - productData.has("t060v01_jp") - ) { + productData.has("t060v01_jp")) { String imageUrl = productData.getString("t060v06"); int machinePrice = Integer.parseInt(productData.getString("t063v03")); int sellingPrice = Integer.parseInt(productData.getString("t060v09")); @@ -731,24 +754,22 @@ public class HttpAPI { marketingPlan, materialCode, productNameEn, - productNameJp - )); + productNameJp)); try { MyApp.getInstance().getSlotDataByPid(productData.getString("t060v00")) .setProduct(new ProductStructure( - productData.getString("t060v00"), - imageUrl, - productData.getString("t060v01"), - machinePrice, - sellingPrice, - memberPrice, - slotUpperLimit, - marketingPlan, - materialCode, + productData.getString("t060v00"), + imageUrl, + productData.getString("t060v01"), + machinePrice, + sellingPrice, + memberPrice, + slotUpperLimit, + marketingPlan, + materialCode, productNameEn, - productNameJp - )); + productNameJp)); } catch (LogsEmptyException e) { getLogs().ignore(e); } @@ -764,7 +785,8 @@ public class HttpAPI { SettingActivity.updateProgressUI(10, "下載中..."); getLogs().info("aaaaaaaaaaaaaaaaaaaaaaaaaaaaa30"); - handlerMain.start(getClass().getSimpleName(), Option.DOWNLOAD_PRODUCT_RESPONSE.getOption(), "成功載入" + MyApp.getInstance().getProductList().size() + "筆商品資料"); + handlerMain.start(getClass().getSimpleName(), Option.DOWNLOAD_PRODUCT_RESPONSE.getOption(), + "成功載入" + MyApp.getInstance().getProductList().size() + "筆商品資料"); } catch (JSONException e) { getLogs().error(ErrorCode.JSON_FORMAT_ERROR, e.getLocalizedMessage()); } @@ -794,14 +816,14 @@ public class HttpAPI { JSONObject productData = productItem.getJSONObject(i); /* - t060v09 售價 - t060v30 會員價 - t060v00 商品ID - t060v11 貨道上限 - t063v03 機台的商品價格 - t060v01 "啵啵魚捲", - t060v06 "https://unibuy.com.tw/Unibuy/dist/img/products/53317506.png", - */ + * t060v09 售價 + * t060v30 會員價 + * t060v00 商品ID + * t060v11 貨道上限 + * t063v03 機台的商品價格 + * t060v01 "啵啵魚捲", + * t060v06 "https://unibuy.com.tw/Unibuy/dist/img/products/53317506.png", + */ if (productData.has("t060v00") && productData.has("t060v06") && @@ -813,8 +835,7 @@ public class HttpAPI { productData.has("t060v40") && productData.has("t060v41") && productData.has("t060v01_en") && - productData.has("t060v01_jp") - ) { + productData.has("t060v01_jp")) { String imageUrl = productData.getString("t060v06"); int machinePrice = Integer.parseInt(productData.getString("t063v03")); int sellingPrice = Integer.parseInt(productData.getString("t060v09")); @@ -827,13 +848,14 @@ public class HttpAPI { Map productIndexs = new HashMap<>(); - for (int index = 0; index < MyApp.getInstance().getProductList().size(); index ++) { + for (int index = 0; index < MyApp.getInstance().getProductList().size(); index++) { ProductStructure product = MyApp.getInstance().getProductList().get(index); productIndexs.put(product.getProductID(), index); } int index = productIndexs.get(productData.getString("t060v00")); - MyApp.getInstance().getProductList().get(index).setProductName(productData.getString("t060v01")); + MyApp.getInstance().getProductList().get(index) + .setProductName(productData.getString("t060v01")); MyApp.getInstance().getProductList().get(index).setProductImg(imageUrl); MyApp.getInstance().getProductList().get(index).setMachinePrice(machinePrice); MyApp.getInstance().getProductList().get(index).setSellingPrice(sellingPrice); @@ -855,8 +877,7 @@ public class HttpAPI { marketingPlan, materialCode, productNameEn, - productNameJp - )); + productNameJp)); } } @@ -866,7 +887,8 @@ public class HttpAPI { productsDao.insertAll(MyApp.getInstance().getProductList()); productsDao.close(); - handlerMain.start(getClass().getSimpleName(), Option.DOWNLOAD_PRODUCT_RESPONSE.getOption(), "成功載入" + MyApp.getInstance().getProductList().size() + "筆商品資料"); + handlerMain.start(getClass().getSimpleName(), Option.DOWNLOAD_PRODUCT_RESPONSE.getOption(), + "成功載入" + MyApp.getInstance().getProductList().size() + "筆商品資料"); } catch (JSONException e) { getLogs().error(ErrorCode.JSON_FORMAT_ERROR, e.getLocalizedMessage()); } @@ -875,27 +897,31 @@ public class HttpAPI { }); } - private void downloadProductInfo(FormPostMainScheduler formPostRunMain) throws LogsSettingEmptyException, LogsParseException { + private void downloadProductInfo(FormPostMainScheduler formPostRunMain) + throws LogsSettingEmptyException, LogsParseException { checkMachineInfo(); try { JSONObject json = new JSONObject(); json.put("key", MyApp.getInstance().getMachine().getApiKey()); json.put("machine", MyApp.getInstance().getMachine().getMachineID()); - formPostRunMain.start(domainNameByUnibuy + "machine/do_sell_new/B012_new", json.toString(), null, null, HttpConnect.ContentType.X_WWW_FORM_URLENCODEED); + formPostRunMain.start(domainNameByUnibuy + "machine/do_sell_new/B012_new", json.toString(), null, null, + HttpConnect.ContentType.X_WWW_FORM_URLENCODEED); } catch (JSONException e) { throw new LogsParseException(logs, ErrorCode.JSON_FORMAT_ERROR, e); } } - private void uploadProductInfo(FormPostMainScheduler formPostRunMain) throws LogsSettingEmptyException, LogsParseException { + private void uploadProductInfo(FormPostMainScheduler formPostRunMain) + throws LogsSettingEmptyException, LogsParseException { checkMachineInfo(); try { JSONObject json = new JSONObject(); json.put("key", MyApp.getInstance().getMachine().getApiKey()); json.put("machine", MyApp.getInstance().getMachine().getMachineID()); - formPostRunMain.start(domainNameByUnibuy + "machine/do_sell_update/B012_update", json.toString(), null, null, HttpConnect.ContentType.X_WWW_FORM_URLENCODEED); + formPostRunMain.start(domainNameByUnibuy + "machine/do_sell_update/B012_update", json.toString(), null, + null, HttpConnect.ContentType.X_WWW_FORM_URLENCODEED); } catch (JSONException e) { throw new LogsParseException(logs, ErrorCode.JSON_FORMAT_ERROR, e); } @@ -933,7 +959,7 @@ public class HttpAPI { String flagString = adData.getString("t070v03"); MyApp.getInstance().getFontendAdUrlString().add(urlString); - /*將下面跑迴圈的程式,移到這裡就直接*/ + /* 將下面跑迴圈的程式,移到這裡就直接 */ if (isReloadApi()) { handlerMain.start(getClass().getSimpleName(), "下載一筆廣告中"); getLogs().info("下載一筆廣告中:" + urlString); @@ -947,42 +973,44 @@ public class HttpAPI { // 記錄兩個欄位: url 及 flag settingsDao.insertOne(new SettingStructure( VideoEoxPlayer.class.getSimpleName(), - new String[]{urlString, flagString} - )); + new String[] { urlString, flagString })); int persent = 20 + (i * 80 / adnum); SettingActivity.updateProgressUI(persent, "下載中..."); } - //要下載廣告 -// for (String urlString : MyApp.getInstance().getFontendAdUrlString()) { -// if (isReloadApi()) { -// handlerMain.start(getClass().getSimpleName(), "下載一筆廣告中"); -// getLogs().info("下載一筆廣告中:" + urlString); -// } else { -// handlerMain.start(getClass().getSimpleName(), "下載一筆廣告中"); -// } -// -// HttpConnect httpConnect = new HttpConnect(); -// File file = httpConnect.download(urlString, true); -// -// settingsDao.insertOne(new SettingStructure( -// VideoEoxPlayer.class.getSimpleName(), -// new String[]{ -// urlString -// })); -// } + // 要下載廣告 + // for (String urlString : MyApp.getInstance().getFontendAdUrlString()) { + // if (isReloadApi()) { + // handlerMain.start(getClass().getSimpleName(), "下載一筆廣告中"); + // getLogs().info("下載一筆廣告中:" + urlString); + // } else { + // handlerMain.start(getClass().getSimpleName(), "下載一筆廣告中"); + // } + // + // HttpConnect httpConnect = new HttpConnect(); + // File file = httpConnect.download(urlString, true); + // + // settingsDao.insertOne(new SettingStructure( + // VideoEoxPlayer.class.getSimpleName(), + // new String[]{ + // urlString + // })); + // } handlerMain.start(getClass().getSimpleName(), "下載完成"); - handlerMain.start(getClass().getSimpleName(), Option.DOWNLOAD_AD_RESPONSE.getOption(), "共載入" + MyApp.getInstance().getFontendAdUrlString().size() + "筆廣告資料"); + handlerMain.start(getClass().getSimpleName(), Option.DOWNLOAD_AD_RESPONSE.getOption(), + "共載入" + MyApp.getInstance().getFontendAdUrlString().size() + "筆廣告資料"); settingsDao.close(); -// handlerMain.start(getClass().getSimpleName(), Option.DOWNLOAD_AD_RESPONSE.getOption(), "共載入" + MyApp.getInstance().getFontendAdUrlString().size() + "筆廣告資料"); + // handlerMain.start(getClass().getSimpleName(), + // Option.DOWNLOAD_AD_RESPONSE.getOption(), "共載入" + + // MyApp.getInstance().getFontendAdUrlString().size() + "筆廣告資料"); } catch (JSONException e) { getLogs().error(ErrorCode.JSON_FORMAT_ERROR, "video url path format error"); - } catch (LogsFileNullException | LogsMalformedURLException | - LogsEmptyException | LogsIOException e) { + } catch (LogsFileNullException | LogsMalformedURLException | LogsEmptyException + | LogsIOException e) { getLogs().warning(e); } } @@ -990,14 +1018,16 @@ public class HttpAPI { }); } - private void downloadAdvertisement(FormPostMainScheduler formPostRunMain) throws LogsSettingEmptyException, LogsParseException { + private void downloadAdvertisement(FormPostMainScheduler formPostRunMain) + throws LogsSettingEmptyException, LogsParseException { checkMachineInfo(); try { JSONObject json = new JSONObject(); json.put("key", MyApp.getInstance().getMachine().getApiKey()); json.put("machine", MyApp.getInstance().getMachine().getMachineID()); - formPostRunMain.start(domainNameByUnibuy + "machine/ad/B005", json.toString(), null, null, HttpConnect.ContentType.X_WWW_FORM_URLENCODEED); + formPostRunMain.start(domainNameByUnibuy + "machine/ad/B005", json.toString(), null, null, + HttpConnect.ContentType.X_WWW_FORM_URLENCODEED); } catch (JSONException e) { throw new LogsParseException(logs, ErrorCode.JSON_FORMAT_ERROR, e); } @@ -1005,41 +1035,42 @@ public class HttpAPI { public void reportFlowInfo(ReportFlowInfoStructure data) throws LogsSettingEmptyException, LogsParseException { reportFlowInfo(new FormPostMainScheduler(getHandlerMain()) { - @Override - protected HandlerMain setHandlerMain() { - return getSrcHandlerMain(); - } + @Override + protected HandlerMain setHandlerMain() { + return getSrcHandlerMain(); + } - @Override - protected Class setCls() { - return getClass(); - } + @Override + protected Class setCls() { + return getClass(); + } - @Override - public void response(int responseCode, String receive, HandlerMain handlerMain) { - if (responseCode == 200) { - //儲存回傳的 message 為 reportFlowId - try { - JSONObject receiveByJsonObject = new JSONObject(receive); - String workApi = receiveByJsonObject.getString("workApi"); - int status = receiveByJsonObject.getInt("status"); - getLogs().info("bbbbbbbbbbbbbbbbbbbbbb status"+status); - String message = receiveByJsonObject.getString("message"); - getLogs().info("bbbbbbbbbbbbbbbbbbbbbb message"+message); + @Override + public void response(int responseCode, String receive, HandlerMain handlerMain) { + if (responseCode == 200) { + // 儲存回傳的 message 為 reportFlowId + try { + JSONObject receiveByJsonObject = new JSONObject(receive); + String workApi = receiveByJsonObject.getString("workApi"); + int status = receiveByJsonObject.getInt("status"); + getLogs().info("bbbbbbbbbbbbbbbbbbbbbb status" + status); + String message = receiveByJsonObject.getString("message"); + getLogs().info("bbbbbbbbbbbbbbbbbbbbbb message" + message); - if (status == 0) { - handlerMain.start(getClass().getSimpleName(), Option.REPORT_FLOW_RESPONSE.getOption(), message); - } else { - getLogs().error(ErrorCode.NETWORK_UNKNOWN_ERROR, "(555)" + message); - } - } catch (JSONException e) { - getLogs().warning(e); - } - } else { - getLogs().error(ErrorCode.NETWORK_UNKNOWN_ERROR, "reportFlowInfo responseCode:" + responseCode); - } - } - }, + if (status == 0) { + handlerMain.start(getClass().getSimpleName(), Option.REPORT_FLOW_RESPONSE.getOption(), + message); + } else { + getLogs().error(ErrorCode.NETWORK_UNKNOWN_ERROR, "(555)" + message); + } + } catch (JSONException e) { + getLogs().warning(e); + } + } else { + getLogs().error(ErrorCode.NETWORK_UNKNOWN_ERROR, "reportFlowInfo responseCode:" + responseCode); + } + } + }, String.valueOf(data.getFlowType()), data.getFlowSendInfo(), data.getFlowRequestInfo(), @@ -1054,7 +1085,10 @@ public class HttpAPI { data.getShoppingCartInfoByJsonArray()); } - private void reportFlowInfo(FormPostMainScheduler formPostRunMain, String flowType, String flowSendInfo, String flowRequestInfo, String productId, String totalPrice, String invoiceInfo, String orderId, String flowBarCcde, String flowStatusType, String giveChange, String usePoints, JSONArray shoppingCartInfoByJsonArray) throws LogsSettingEmptyException, LogsParseException { + private void reportFlowInfo(FormPostMainScheduler formPostRunMain, String flowType, String flowSendInfo, + String flowRequestInfo, String productId, String totalPrice, String invoiceInfo, String orderId, + String flowBarCcde, String flowStatusType, String giveChange, String usePoints, + JSONArray shoppingCartInfoByJsonArray) throws LogsSettingEmptyException, LogsParseException { checkMachineInfo(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()); @@ -1065,7 +1099,7 @@ public class HttpAPI { json.put("req2", MyApp.getInstance().getMachine().getMachineID()); json.put("req3", String.valueOf(flowType)); json.put("req4", flowSendInfo); -// json.put("req5", flowRequestInfo); + // json.put("req5", flowRequestInfo); json.put("req5", removeNonPrintable(flowRequestInfo)); json.put("req6", productId); json.put("req7", totalPrice); @@ -1076,7 +1110,7 @@ public class HttpAPI { json.put("req12", flowStatusType); json.put("req13", giveChange); json.put("req14", usePoints); - json.put("req15", ""); //系統保留不使用 + json.put("req15", ""); // 系統保留不使用 json.put("req16", shoppingCartInfoByJsonArray); formPostRunMain.start(domainNameByAAT + "B600", json.toString(), null, null, HttpConnect.ContentType.JSON); } catch (JSONException e) { @@ -1085,58 +1119,63 @@ public class HttpAPI { } public String removeNonPrintable(String input) { - if (input == null) return null; + if (input == null) + return null; return input.replaceAll("[^\\x20-\\x7E]", ""); } - public void reportInvoiceInfo(ReportInvoiceInfoStructure data) throws LogsSettingEmptyException, LogsParseException { + public void reportInvoiceInfo(ReportInvoiceInfoStructure data) + throws LogsSettingEmptyException, LogsParseException { getLogs().info("sendData:" + data.toString()); reportInvoiceInfo(new FormPostMainScheduler(getHandlerMain()) { - @Override - protected HandlerMain setHandlerMain() { - return getSrcHandlerMain(); - } + @Override + protected HandlerMain setHandlerMain() { + return getSrcHandlerMain(); + } - @Override - protected Class setCls() { - return getClass(); - } + @Override + protected Class setCls() { + return getClass(); + } - @Override - public void response(int responseCode, String receive, HandlerMain handlerMain) { - if (responseCode == 200) { - //儲存回傳的 message 為 reportFlowId - try { - JSONObject receiveByJsonObject = new JSONObject(receive); - String workApi = receiveByJsonObject.getString("workApi"); - int status = receiveByJsonObject.getInt("status"); - String message = receiveByJsonObject.getString("message"); + @Override + public void response(int responseCode, String receive, HandlerMain handlerMain) { + if (responseCode == 200) { + // 儲存回傳的 message 為 reportFlowId + try { + JSONObject receiveByJsonObject = new JSONObject(receive); + String workApi = receiveByJsonObject.getString("workApi"); + int status = receiveByJsonObject.getInt("status"); + String message = receiveByJsonObject.getString("message"); - if (status == 0) { - handlerMain.start(getClass().getSimpleName(), Option.REPORT_INVOICE_RESPONSE.getOption(), message); - } else { - getLogs().error(ErrorCode.NETWORK_UNKNOWN_ERROR, "(634)" + message); - } - } catch (JSONException e) { - getLogs().warning(e); - } - } else { - getLogs().error(ErrorCode.NETWORK_UNKNOWN_ERROR, "reportInvoiceInfo responseCode:" + responseCode); - } - } - }, - data.getReportFlowId(), - data.getRtnCode(), - data.getRtnMsg(), - data.getInvoiceNo(), - data.getInvoiceDate(), - data.getRandomNumber(), - data.getLoveCode()); + if (status == 0) { + handlerMain.start(getClass().getSimpleName(), Option.REPORT_INVOICE_RESPONSE.getOption(), + message); + } else { + getLogs().error(ErrorCode.NETWORK_UNKNOWN_ERROR, "(634)" + message); + } + } catch (JSONException e) { + getLogs().warning(e); + } + } else { + getLogs().error(ErrorCode.NETWORK_UNKNOWN_ERROR, "reportInvoiceInfo responseCode:" + responseCode); + } + } + }, + data.getReportFlowId(), + data.getRtnCode(), + data.getRtnMsg(), + data.getInvoiceNo(), + data.getInvoiceDate(), + data.getRandomNumber(), + data.getLoveCode()); } - private void reportInvoiceInfo(FormPostMainScheduler formPostRunMain, String reportFlowId, String rtnCode, String rtnMsg, String invoiceNo, String invoiceDate, String randomNumber, String loveCode) throws LogsSettingEmptyException, LogsParseException { + private void reportInvoiceInfo(FormPostMainScheduler formPostRunMain, String reportFlowId, String rtnCode, + String rtnMsg, String invoiceNo, String invoiceDate, String randomNumber, String loveCode) + throws LogsSettingEmptyException, LogsParseException { checkMachineInfo(); try { @@ -1161,52 +1200,57 @@ public class HttpAPI { public void checkAccessCode(AccessCodeStructure data) throws LogsSettingEmptyException, LogsParseException { checkAccessCode(new FormPostMainScheduler(getSrcHandlerMain()) { - @Override - protected HandlerMain setHandlerMain() { - return getSrcHandlerMain(); - } + @Override + protected HandlerMain setHandlerMain() { + return getSrcHandlerMain(); + } - @Override - protected Class setCls() { - return getClass(); - } + @Override + protected Class setCls() { + return getClass(); + } - @Override - public void response(int responseCode, String receive, HandlerMain handlerMain) { - if (responseCode == 200) { - try { - //{"data":[{"res1":"46357"}],"message":"執行命令成功","workID":"B024","status":"00"} - //{"message":"passCode error","workID":"B024","status":"74"} - JSONObject receiveByJsonObject = new JSONObject(receive); - String workID = receiveByJsonObject.getString("workID"); - String status = receiveByJsonObject.getString("status"); - String message = receiveByJsonObject.getString("message"); + @Override + public void response(int responseCode, String receive, HandlerMain handlerMain) { + if (responseCode == 200) { + try { + // {"data":[{"res1":"46357"}],"message":"執行命令成功","workID":"B024","status":"00"} + // {"message":"passCode error","workID":"B024","status":"74"} + JSONObject receiveByJsonObject = new JSONObject(receive); + String workID = receiveByJsonObject.getString("workID"); + String status = receiveByJsonObject.getString("status"); + String message = receiveByJsonObject.getString("message"); - if (status.equals("00")) { - JSONArray jsonArray = receiveByJsonObject.getJSONArray("data"); + if (status.equals("00")) { + JSONArray jsonArray = receiveByJsonObject.getJSONArray("data"); String res1 = jsonArray.getJSONObject(0).getString("res1"); MyApp.getInstance().getReportFlowInfoData().setReportFlowId(res1); - MyApp.getInstance().getReportFlowInfoData().setFlowBarCode(MyApp.getInstance().getAccessCodeStructure().getPassCode()); + MyApp.getInstance().getReportFlowInfoData() + .setFlowBarCode(MyApp.getInstance().getAccessCodeStructure().getPassCode()); MyApp.getInstance().getReportAccessCodeStructure().setAccessCodeId(res1); - MyApp.getInstance().getReportAccessCodeStructure().setPassCode(MyApp.getInstance().getAccessCodeStructure().getPassCode()); - handlerMain.start(handlerMain.getLogs().getClassName(), CheckoutAccessCodeDialog.Option.CHANGE_DISPATCH.getOption(), "change dispatch"); - } else { - handlerMain.start(handlerMain.getLogs().getClassName(), CheckoutAccessCodeDialog.Option.SET_STATUS_TEXT.getOption(), message); - } - } catch (JSONException e) { - throw new RuntimeException(e); - } - } else { - getLogs().error(ErrorCode.NETWORK_UNKNOWN_ERROR, "reportInvoiceInfo responseCode:" + responseCode); - } - } - }, - data.getPassCode()); + MyApp.getInstance().getReportAccessCodeStructure() + .setPassCode(MyApp.getInstance().getAccessCodeStructure().getPassCode()); + handlerMain.start(handlerMain.getLogs().getClassName(), + CheckoutAccessCodeDialog.Option.CHANGE_DISPATCH.getOption(), "change dispatch"); + } else { + handlerMain.start(handlerMain.getLogs().getClassName(), + CheckoutAccessCodeDialog.Option.SET_STATUS_TEXT.getOption(), message); + } + } catch (JSONException e) { + throw new RuntimeException(e); + } + } else { + getLogs().error(ErrorCode.NETWORK_UNKNOWN_ERROR, "reportInvoiceInfo responseCode:" + responseCode); + } + } + }, + data.getPassCode()); } - private void checkAccessCode(FormPostMainScheduler formPostRunMain, String passCode) throws LogsSettingEmptyException, LogsParseException { + private void checkAccessCode(FormPostMainScheduler formPostRunMain, String passCode) + throws LogsSettingEmptyException, LogsParseException { checkMachineInfo(); try { @@ -1216,7 +1260,8 @@ public class HttpAPI { json.put("machine", MyApp.getInstance().getMachine().getMachineID()); json.put("passCode", passCode); - formPostRunMain.start(domainNameByUnibuy + "sell/PassCode/B024", json.toString(), null, null, HttpConnect.ContentType.JSON); + formPostRunMain.start(domainNameByUnibuy + "sell/PassCode/B024", json.toString(), null, null, + HttpConnect.ContentType.JSON); } catch (JSONException e) { throw new LogsParseException(logs, ErrorCode.JSON_FORMAT_ERROR, e); } @@ -1238,8 +1283,8 @@ public class HttpAPI { public void response(int responseCode, String receive, HandlerMain handlerMain) { if (responseCode == 200) { try { - //{"data":[{"res1":"46357"}],"message":"執行命令成功","workID":"B024","status":"00"} - //{"message":"passCode error","workID":"B024","status":"74"} + // {"data":[{"res1":"46357"}],"message":"執行命令成功","workID":"B024","status":"00"} + // {"message":"passCode error","workID":"B024","status":"74"} JSONObject receiveByJsonObject = new JSONObject(receive); String workID = receiveByJsonObject.getString("workID"); String status = receiveByJsonObject.getString("status"); @@ -1248,25 +1293,30 @@ public class HttpAPI { if (status.equals("00")) { JSONArray jsonArray = receiveByJsonObject.getJSONArray("data"); String res1 = jsonArray.getJSONObject(0).getString("res1"); // put id - String res2 = jsonArray.getJSONObject(0).getString("res2"); //mode - String res3 = jsonArray.getJSONObject(0).getString("res3"); //出貨商品代碼 - String res4 = jsonArray.getJSONObject(0).getString("res4"); //折扣金額 - String res5 = jsonArray.getJSONObject(0).getString("res5"); //折扣折數 + String res2 = jsonArray.getJSONObject(0).getString("res2"); // mode + String res3 = jsonArray.getJSONObject(0).getString("res3"); // 出貨商品代碼 + String res4 = jsonArray.getJSONObject(0).getString("res4"); // 折扣金額 + String res5 = jsonArray.getJSONObject(0).getString("res5"); // 折扣折數 MyApp.getInstance().getReportFlowInfoData().setReportFlowId(res1); - MyApp.getInstance().getReportFlowInfoData().setFlowBarCode(MyApp.getInstance().getFreeGiftStructure().getPassCode()); + MyApp.getInstance().getReportFlowInfoData() + .setFlowBarCode(MyApp.getInstance().getFreeGiftStructure().getPassCode()); MyApp.getInstance().getReportFreeGiftCodeStructure().setFreeGiftId(res1); - MyApp.getInstance().getReportFreeGiftCodeStructure().setPassCode(MyApp.getInstance().getFreeGiftStructure().getPassCode()); + MyApp.getInstance().getReportFreeGiftCodeStructure() + .setPassCode(MyApp.getInstance().getFreeGiftStructure().getPassCode()); MyApp.getInstance().getReportFreeGiftCodeStructure().setMode(Integer.parseInt(res2)); MyApp.getInstance().getReportFreeGiftCodeStructure().setProductId(res3); - MyApp.getInstance().getReportFreeGiftCodeStructure().setDiscountAmount(Integer.parseInt(res4)); - MyApp.getInstance().getReportFreeGiftCodeStructure().setDiscountPercentage(Float.parseFloat(res5)); + MyApp.getInstance().getReportFreeGiftCodeStructure() + .setDiscountAmount(Integer.parseInt(res4)); + MyApp.getInstance().getReportFreeGiftCodeStructure() + .setDiscountPercentage(Float.parseFloat(res5)); if (Integer.parseInt(res2) == 0 && !res3.isEmpty()) { try { SlotStructure slotProduct = MyApp.getInstance().getSlotDataByPid(res3); - BuyStructure buyProduct = new BuyStructure(slotProduct.getField(), slotProduct.getSlot(), slotProduct.getProduct(), 1); + BuyStructure buyProduct = new BuyStructure(slotProduct.getField(), + slotProduct.getSlot(), slotProduct.getProduct(), 1); buyProduct.setFreeGift(true); MyApp.getInstance().getBuyList().add(buyProduct); } catch (LogsEmptyException e) { @@ -1274,9 +1324,11 @@ public class HttpAPI { } } - handlerMain.start(handlerMain.getLogs().getClassName(), CheckoutFreeGiftCodeDialog.Option.CHANGE_BUY.getOption(), "change buy"); + handlerMain.start(handlerMain.getLogs().getClassName(), + CheckoutFreeGiftCodeDialog.Option.CHANGE_BUY.getOption(), "change buy"); } else { - handlerMain.start(handlerMain.getLogs().getClassName(), CheckoutFreeGiftCodeDialog.Option.SET_STATUS_TEXT.getOption(), message); + handlerMain.start(handlerMain.getLogs().getClassName(), + CheckoutFreeGiftCodeDialog.Option.SET_STATUS_TEXT.getOption(), message); } } catch (JSONException e) { throw new RuntimeException(e); @@ -1286,10 +1338,11 @@ public class HttpAPI { } } }, - data.getPassCode()); + data.getPassCode()); } - private void freeGiftCode(FormPostMainScheduler formPostRunMain, String passCode) throws LogsSettingEmptyException, LogsParseException { + private void freeGiftCode(FormPostMainScheduler formPostRunMain, String passCode) + throws LogsSettingEmptyException, LogsParseException { checkMachineInfo(); try { @@ -1299,7 +1352,8 @@ public class HttpAPI { json.put("machine", MyApp.getInstance().getMachine().getMachineID()); json.put("passCode", passCode); - formPostRunMain.start(domainNameByUnibuy + "sell/Freebie/B027", json.toString(), null, null, HttpConnect.ContentType.JSON); + formPostRunMain.start(domainNameByUnibuy + "sell/Freebie/B027", json.toString(), null, null, + HttpConnect.ContentType.JSON); } catch (JSONException e) { throw new LogsParseException(logs, ErrorCode.JSON_FORMAT_ERROR, e); } @@ -1326,13 +1380,14 @@ public class HttpAPI { } } }, - data.getAccessCodeId(), - data.getPassCode(), - String.valueOf(data.getSlot()), - data.getProductId()); + data.getAccessCodeId(), + data.getPassCode(), + String.valueOf(data.getSlot()), + data.getProductId()); } - private void reportAccessCode(FormPutMainScheduler formPutRunMain, String accessCodeId, String passCode, String rid, String pid) throws LogsSettingEmptyException, LogsParseException { + private void reportAccessCode(FormPutMainScheduler formPutRunMain, String accessCodeId, String passCode, String rid, + String pid) throws LogsSettingEmptyException, LogsParseException { checkMachineInfo(); try { @@ -1347,44 +1402,48 @@ public class HttpAPI { json.put("type", "2"); json.put("time", System.currentTimeMillis()); - getLogs().info("sendData:"+json.toString()); + getLogs().info("sendData:" + json.toString()); - formPutRunMain.start(domainNameByUnibuy + "sell/PassCode/B024", json.toString(), null, null, HttpConnect.ContentType.JSON); + formPutRunMain.start(domainNameByUnibuy + "sell/PassCode/B024", json.toString(), null, null, + HttpConnect.ContentType.JSON); } catch (JSONException e) { throw new LogsParseException(logs, ErrorCode.JSON_FORMAT_ERROR, e); } } - public void reportFreeGiftCode(ReportFreeGiftCodeStructure data) throws LogsSettingEmptyException, LogsParseException { + public void reportFreeGiftCode(ReportFreeGiftCodeStructure data) + throws LogsSettingEmptyException, LogsParseException { reportFreeGiftCode(new FormPutMainScheduler(getHandlerMain()) { - @Override - protected HandlerMain setHandlerMain() { - return getSrcHandlerMain(); - } + @Override + protected HandlerMain setHandlerMain() { + return getSrcHandlerMain(); + } - @Override - protected Class setCls() { - return getClass(); - } + @Override + protected Class setCls() { + return getClass(); + } - @Override - public void response(int responseCode, String receive, HandlerMain handlerMain) { - if (responseCode == 200) { - handlerMain.start(getClass().getSimpleName(), receive); - } else { - getLogs().error(ErrorCode.NETWORK_UNKNOWN_ERROR, "reportInvoiceInfo responseCode:" + responseCode); - } - } - }, - data.getFreeGiftId(), - data.getPassCode(), - String.valueOf(data.getSlot()), - String.valueOf(data.getReportFlowId()), - data.getProductId(), - String.valueOf(data.getMoney())); + @Override + public void response(int responseCode, String receive, HandlerMain handlerMain) { + if (responseCode == 200) { + handlerMain.start(getClass().getSimpleName(), receive); + } else { + getLogs().error(ErrorCode.NETWORK_UNKNOWN_ERROR, "reportInvoiceInfo responseCode:" + responseCode); + } + } + }, + data.getFreeGiftId(), + data.getPassCode(), + String.valueOf(data.getSlot()), + String.valueOf(data.getReportFlowId()), + data.getProductId(), + String.valueOf(data.getMoney())); } - private void reportFreeGiftCode(FormPutMainScheduler formPutRunMain, String freeGiftCodeId, String passCode, String tid, String reportFlowId, String pid, String money) throws LogsSettingEmptyException, LogsParseException { + private void reportFreeGiftCode(FormPutMainScheduler formPutRunMain, String freeGiftCodeId, String passCode, + String tid, String reportFlowId, String pid, String money) + throws LogsSettingEmptyException, LogsParseException { checkMachineInfo(); try { @@ -1400,28 +1459,30 @@ public class HttpAPI { json.put("pid", pid); json.put("money", money); - getLogs().info("sendData:"+json.toString()); + getLogs().info("sendData:" + json.toString()); - formPutRunMain.start(domainNameByUnibuy + "sell/Freebie/B027", json.toString(), null, null, HttpConnect.ContentType.JSON); + formPutRunMain.start(domainNameByUnibuy + "sell/Freebie/B027", json.toString(), null, null, + HttpConnect.ContentType.JSON); } catch (JSONException e) { throw new LogsParseException(logs, ErrorCode.JSON_FORMAT_ERROR, e); } } - public void reportDispatchInfo(ReportDispatchInfoStructure data) throws LogsSettingEmptyException, LogsParseException { + public void reportDispatchInfo(ReportDispatchInfoStructure data) + throws LogsSettingEmptyException, LogsParseException { reportDispatchInfo(new FormPostMainScheduler(getHandlerMain()) { - @Override - protected HandlerMain setHandlerMain() { - return getSrcHandlerMain(); - } + @Override + protected HandlerMain setHandlerMain() { + return getSrcHandlerMain(); + } - @Override - protected Class setCls() { + @Override + protected Class setCls() { return getClass(); } - @Override - public void response(int responseCode, String receive, HandlerMain handlerMain) { + @Override + public void response(int responseCode, String receive, HandlerMain handlerMain) { if (responseCode == 200) { try { JSONObject receiveByJsonObject = new JSONObject(receive); @@ -1430,15 +1491,15 @@ public class HttpAPI { String message = receiveByJsonObject.getString("message"); if (status == 0) { -// handlerMain.start(Option.REPORT_DISPATCH_RESPONSE.getOption(), message); + // handlerMain.start(Option.REPORT_DISPATCH_RESPONSE.getOption(), message); } else { - getLogs().error(ErrorCode.NETWORK_UNKNOWN_ERROR, "(697)"+message); + getLogs().error(ErrorCode.NETWORK_UNKNOWN_ERROR, "(697)" + message); } } catch (JSONException e) { getLogs().error(ErrorCode.JSON_FORMAT_ERROR, "B602 json format error"); } } else { - getLogs().error(ErrorCode.NETWORK_UNKNOWN_ERROR, "reportDispatchInfo responseCode:"+responseCode); + getLogs().error(ErrorCode.NETWORK_UNKNOWN_ERROR, "reportDispatchInfo responseCode:" + responseCode); } } }, @@ -1456,7 +1517,10 @@ public class HttpAPI { String.valueOf(data.getUsePoints())); } - private void reportDispatchInfo(FormPostMainScheduler formPostRunMain, String reportFlowId, String flowType, String productId, String slot, String fullPrice, String orderId, String remaining, String mamberBarCcde, String VoucherId, String dispatchStatusType, String ownPrice, String usePoints) throws LogsSettingEmptyException, LogsParseException { + private void reportDispatchInfo(FormPostMainScheduler formPostRunMain, String reportFlowId, String flowType, + String productId, String slot, String fullPrice, String orderId, String remaining, String mamberBarCcde, + String VoucherId, String dispatchStatusType, String ownPrice, String usePoints) + throws LogsSettingEmptyException, LogsParseException { checkMachineInfo(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()); @@ -1480,7 +1544,7 @@ public class HttpAPI { json.put("req15", ownPrice); json.put("req16", usePoints); - getLogs().info("reportDispatchInfo:"+json.toString()); + getLogs().info("reportDispatchInfo:" + json.toString()); formPostRunMain.start(domainNameByAAT + "B602", json.toString(), null, null, HttpConnect.ContentType.JSON); } catch (JSONException e) { @@ -1488,7 +1552,8 @@ public class HttpAPI { } } - public void memberVerification(MemberVerificationStructure data) throws LogsSettingEmptyException, LogsParseException { + public void memberVerification(MemberVerificationStructure data) + throws LogsSettingEmptyException, LogsParseException { memberVerification(new FormPostMainScheduler(getSrcHandlerMain()) { @Override protected HandlerMain setHandlerMain() { @@ -1510,25 +1575,28 @@ public class HttpAPI { String message = receiveByJsonObject.getString("message"); switch (MyApp.getInstance().getMemberVerificationStructure().getVerificationType()) { - case 0: //商品ID>0 (有點擊商品) + case 0: // 商品ID>0 (有點擊商品) break; - case 1: //req3 為空字串且req4=0 (會員純驗證) + case 1: // req3 為空字串且req4=0 (會員純驗證) break; - case 2: //req3=0 (會員兌換商品列表) + case 2: // req3=0 (會員兌換商品列表) if (status == 103) { String pid = receiveByJsonObject.getString("pid"); MyApp.getInstance().getReportFlowInfoData().setReportFlowId(pid); - MyApp.getInstance().getReportFlowInfoData().setFlowBarCode(MyApp.getInstance().getMemberVerificationStructure().getMemberBarCode()); + MyApp.getInstance().getReportFlowInfoData().setFlowBarCode( + MyApp.getInstance().getMemberVerificationStructure().getMemberBarCode()); - handlerMain.start(handlerMain.getLogs().getClassName(), FontendPickupCodeDialog.Option.CHANGE_BUY.getOption(), pid); + handlerMain.start(handlerMain.getLogs().getClassName(), + FontendPickupCodeDialog.Option.CHANGE_BUY.getOption(), pid); } else { - handlerMain.start(handlerMain.getLogs().getClassName(), FontendPickupCodeDialog.Option.SET_STATUS_TEXT.getOption(), message); + handlerMain.start(handlerMain.getLogs().getClassName(), + FontendPickupCodeDialog.Option.SET_STATUS_TEXT.getOption(), message); } break; - case 3: //線上訂單現下結帳 + case 3: // 線上訂單現下結帳 break; - case 4: //會員證品 + case 4: // 會員證品 break; } } catch (JSONException e) { @@ -1543,7 +1611,8 @@ public class HttpAPI { String.valueOf(data.getVerificationType())); } - private void memberVerification(FormPostMainScheduler formPostRunMain, String productId, String productPrice, String memberBarCode, String verificationType) throws LogsSettingEmptyException, LogsParseException { + private void memberVerification(FormPostMainScheduler formPostRunMain, String productId, String productPrice, + String memberBarCode, String verificationType) throws LogsSettingEmptyException, LogsParseException { checkMachineInfo(); try { @@ -1560,7 +1629,8 @@ public class HttpAPI { } } - public void reportElectricInfo(JSONArray electricInfoByJsonArray) throws LogsSettingEmptyException, LogsParseException { + public void reportElectricInfo(JSONArray electricInfoByJsonArray) + throws LogsSettingEmptyException, LogsParseException { reportElectricInfo(new FormPostMainScheduler(getHandlerMain()) { @Override protected HandlerMain setHandlerMain() { @@ -1579,14 +1649,15 @@ public class HttpAPI { JSONArray jsonArray = new JSONObject(receive).getJSONArray("pending"); getLogs().info("pending date:" + jsonArray.toString()); - //](200)receive:{"workApi":"/api/app/B710","status":100,"message":"Success","pending":[{"pid":"53341352","cid":"1","status":"3","num":"3600.0"}]} - for (int index=0; index < jsonArray.length(); index++) { + // ](200)receive:{"workApi":"/api/app/B710","status":100,"message":"Success","pending":[{"pid":"53341352","cid":"1","status":"3","num":"3600.0"}]} + for (int index = 0; index < jsonArray.length(); index++) { JSONObject jsonObject = jsonArray.getJSONObject(index); int slot = Integer.parseInt(jsonObject.getString("cid")); int state = Integer.parseInt(jsonObject.getString("status")); float second = Float.parseFloat(jsonObject.getString("num")); - SlotStructure slotData = MyApp.getInstance().getSlotData(SlotField.ELECTRIC.getField(), slot); + SlotStructure slotData = MyApp.getInstance().getSlotData(SlotField.ELECTRIC.getField(), + slot); if (state == 3) { if (second > 0) { @@ -1594,7 +1665,8 @@ public class HttpAPI { Date timeEpiredDate = new Date(); if (slotData.getOtherData().has("timeExpired")) { try { - timeEpiredDate = sdf.parse(slotData.getOtherData().getString("timeExpired")); + timeEpiredDate = sdf + .parse(slotData.getOtherData().getString("timeExpired")); } catch (JSONException | ParseException e) { getLogs().warning(e); } @@ -1605,7 +1677,7 @@ public class HttpAPI { Calendar calendar = Calendar.getInstance(); calendar.setTime(timeEpiredDate); - calendar.add(Calendar.MINUTE, (int) ((second/60)+1)); + calendar.add(Calendar.MINUTE, (int) ((second / 60) + 1)); timeEpiredDate = calendar.getTime(); timeEpiredString = sdf.format(timeEpiredDate); getLogs().debug("timeEpiredString2:" + timeEpiredString); @@ -1624,7 +1696,8 @@ public class HttpAPI { } } - getHandlerMain().start(getLogs().getClassName(), ElectricFragment.Option.SHIPPED_PRODUCT.getOption(), "SHIPPED_PRODUCT"); + getHandlerMain().start(getLogs().getClassName(), + ElectricFragment.Option.SHIPPED_PRODUCT.getOption(), "SHIPPED_PRODUCT"); } } } catch (JSONException e) { @@ -1637,7 +1710,8 @@ public class HttpAPI { }, electricInfoByJsonArray); } - private void reportElectricInfo(FormPostMainScheduler formPostRunMain, JSONArray electricInfoByJsonArray) throws LogsSettingEmptyException, LogsParseException { + private void reportElectricInfo(FormPostMainScheduler formPostRunMain, JSONArray electricInfoByJsonArray) + throws LogsSettingEmptyException, LogsParseException { checkMachineInfo(); try { @@ -1654,26 +1728,29 @@ public class HttpAPI { } } - public void postInvoiceByGreen(PostInvoiceByGreenStructure data) throws LogsSettingEmptyException, LogsParseException { + public void postInvoiceByGreen(PostInvoiceByGreenStructure data) + throws LogsSettingEmptyException, LogsParseException { postInvoiceByGreen(new FormPostMainScheduler(getHandlerMain()) { - @Override - protected HandlerMain setHandlerMain() { - return getSrcHandlerMain(); - } + @Override + protected HandlerMain setHandlerMain() { + return getSrcHandlerMain(); + } - @Override - protected Class setCls() { + @Override + protected Class setCls() { return getClass(); } - @Override - public void response(int responseCode, String receive, HandlerMain handlerMain) { + @Override + public void response(int responseCode, String receive, HandlerMain handlerMain) { if (responseCode == 200) { try { String dataString = new JSONObject(receive).getString("Data"); getLogs().info("dataString date:" + dataString); - String AESDecode = Tools.fromAES(dataString, MyApp.getInstance().getGreenInvoice().getGreenHashKey(), MyApp.getInstance().getGreenInvoice().getGreenHashIV()); + String AESDecode = Tools.fromAES(dataString, + MyApp.getInstance().getGreenInvoice().getGreenHashKey(), + MyApp.getInstance().getGreenInvoice().getGreenHashIV()); String urlDecode = URLDecoder.decode(AESDecode, Key.STRING_CHARSET_NAME); getLogs().info("urlDecode date:" + urlDecode); @@ -1684,38 +1761,43 @@ public class HttpAPI { String invoiceNo = jsonDecodeData.getString("InvoiceNo"); String invoiceDate = jsonDecodeData.getString("InvoiceDate"); String randomNumber = jsonDecodeData.getString("RandomNumber"); - String loveCode = MyApp.getInstance().getPostInvoiceByGreenData().getInvoiceData().getLoveCode(); + String loveCode = MyApp.getInstance().getPostInvoiceByGreenData().getInvoiceData() + .getLoveCode(); getLogs().info("decode date:" + jsonDecodeData); - handlerMain.start(getClass().getSimpleName(), Option.GREEN_INVOICE_RESPONSE.getOption(), new StringRefactoring(new Object[]{ - rtnCode, rtnMsg, invoiceNo, invoiceDate, randomNumber, loveCode - }) { - @Override - public String refactoring(Object[] source) { - String[] names = new String[]{ - "rtnCode", "rtnMsg", "invoiceNo", "invoiceDate", "randomNumber", "loveCode" - }; + handlerMain.start(getClass().getSimpleName(), Option.GREEN_INVOICE_RESPONSE.getOption(), + new StringRefactoring(new Object[] { + rtnCode, rtnMsg, invoiceNo, invoiceDate, randomNumber, loveCode + }) { + @Override + public String refactoring(Object[] source) { + String[] names = new String[] { + "rtnCode", "rtnMsg", "invoiceNo", "invoiceDate", "randomNumber", + "loveCode" + }; - JSONObject jsonObject = new JSONObject(); - for(int index = 0; index < names.length; index++) { - try { - jsonObject.put(names[index], source[index]); - } catch (JSONException e) { - throw new RuntimeException(e); + JSONObject jsonObject = new JSONObject(); + for (int index = 0; index < names.length; index++) { + try { + jsonObject.put(names[index], source[index]); + } catch (JSONException e) { + throw new RuntimeException(e); + } + } + + return jsonObject.toString(); } - } - - return jsonObject.toString(); - } - }.toString()); - } catch (InvalidAlgorithmParameterException | NoSuchPaddingException | IllegalBlockSizeException | UnsupportedEncodingException | NoSuchAlgorithmException | BadPaddingException | InvalidKeyException e) { - getLogs().error(ErrorCode.NETWORK_UNKNOWN_ERROR, "(870)"+e.getLocalizedMessage()); + }.toString()); + } catch (InvalidAlgorithmParameterException | NoSuchPaddingException | IllegalBlockSizeException + | UnsupportedEncodingException | NoSuchAlgorithmException | BadPaddingException + | InvalidKeyException e) { + getLogs().error(ErrorCode.NETWORK_UNKNOWN_ERROR, "(870)" + e.getLocalizedMessage()); } catch (JSONException e) { getLogs().error(ErrorCode.JSON_FORMAT_ERROR, e.getLocalizedMessage()); } } else { - getLogs().error(ErrorCode.NETWORK_UNKNOWN_ERROR, "postInvoiceByGreen responseCode:"+responseCode); + getLogs().error(ErrorCode.NETWORK_UNKNOWN_ERROR, "postInvoiceByGreen responseCode:" + responseCode); } } }, @@ -1726,7 +1808,9 @@ public class HttpAPI { data.getInvoiceItem()); } - private void postInvoiceByGreen(FormPostMainScheduler formPostRunMain, String orderId, String reportFlowId, int totalPrice, InvoiceStructure invoiceData, List invoiceItem) throws LogsSettingEmptyException, LogsParseException { + private void postInvoiceByGreen(FormPostMainScheduler formPostRunMain, String orderId, String reportFlowId, + int totalPrice, InvoiceStructure invoiceData, List invoiceItem) + throws LogsSettingEmptyException, LogsParseException { checkMachineInfo(); if (MyApp.getInstance().getGreenInvoice().getGreenMerchantID().isEmpty() || @@ -1755,15 +1839,19 @@ public class HttpAPI { JSONObject json = new JSONObject(); json.put("MerchantID", MyApp.getInstance().getGreenInvoice().getGreenMerchantID()); String relateNumber = UUID.randomUUID().toString().replace("-", "").substring(0, 30); -// String relateNumber = MyApp.getInstance().getMachine().getMachineID() + reportFlowId + System.currentTimeMillis(); + // String relateNumber = MyApp.getInstance().getMachine().getMachineID() + + // reportFlowId + System.currentTimeMillis(); json.put("RelateNumber", relateNumber); json.put("CustomerID", MyApp.getInstance().getMachine().getMachineID()); json.put("Print", invoiceData.getCustomerIdentifier().isEmpty() ? "0" : "1"); json.put("CustomerIdentifier", invoiceData.getCustomerIdentifier()); - json.put("CustomerName", invoiceData.getCustomerIdentifier().isEmpty() ? "" : invoiceData.getCustomerIdentifier()); - json.put("CustomerAddr", invoiceData.getCustomerIdentifier().isEmpty() ? "" : invoiceData.getCustomerIdentifier()); + json.put("CustomerName", + invoiceData.getCustomerIdentifier().isEmpty() ? "" : invoiceData.getCustomerIdentifier()); + json.put("CustomerAddr", + invoiceData.getCustomerIdentifier().isEmpty() ? "" : invoiceData.getCustomerIdentifier()); json.put("CustomerPhone", invoiceData.getPhone()); - json.put("CustomerEmail", invoiceData.getPhone().isEmpty() ? MyApp.getInstance().getGreenInvoice().getGreenEmail() : ""); + json.put("CustomerEmail", + invoiceData.getPhone().isEmpty() ? MyApp.getInstance().getGreenInvoice().getGreenEmail() : ""); json.put("ClearanceMark", ""); json.put("Donation", "0"); json.put("LoveCode", ""); @@ -1812,7 +1900,8 @@ public class HttpAPI { getLogs().info("json data:" + json.toString()); String urlEncode = URLEncoder.encode(json.toString(), Key.STRING_CHARSET_NAME); - String AESEncode = Tools.toAES(urlEncode, MyApp.getInstance().getGreenInvoice().getGreenHashKey(), MyApp.getInstance().getGreenInvoice().getGreenHashIV()); + String AESEncode = Tools.toAES(urlEncode, MyApp.getInstance().getGreenInvoice().getGreenHashKey(), + MyApp.getInstance().getGreenInvoice().getGreenHashIV()); JSONObject RqHeader = new JSONObject(); RqHeader.put("Timestamp", unixTime); @@ -1824,16 +1913,18 @@ public class HttpAPI { jsonSendData.put("MerchantID", MyApp.getInstance().getGreenInvoice().getGreenMerchantID()); jsonSendData.put("Data", AESEncode); - formPostRunMain.start("https://einvoice.ecpay.com.tw/B2CInvoice/Issue", jsonSendData.toString(), null, null, HttpConnect.ContentType.JSON); + formPostRunMain.start("https://einvoice.ecpay.com.tw/B2CInvoice/Issue", jsonSendData.toString(), null, null, + HttpConnect.ContentType.JSON); } catch (JSONException e) { throw new LogsParseException(getLogs(), ErrorCode.JSON_FORMAT_ERROR); - } catch (UnsupportedEncodingException | InvalidAlgorithmParameterException | NoSuchPaddingException | IllegalBlockSizeException | NoSuchAlgorithmException | - BadPaddingException | InvalidKeyException e) { + } catch (UnsupportedEncodingException | InvalidAlgorithmParameterException | NoSuchPaddingException + | IllegalBlockSizeException | NoSuchAlgorithmException | BadPaddingException | InvalidKeyException e) { throw new LogsParseException(getLogs(), e.getLocalizedMessage()); } } - public void esunpay(String barcode, int totalPrice) throws LogsSettingEmptyException, LogsUnsupportedOperationException { + public void esunpay(String barcode, int totalPrice) + throws LogsSettingEmptyException, LogsUnsupportedOperationException { esunpay(barcode, totalPrice, new FormPostMainScheduler(getSrcHandlerMain()) { @Override protected HandlerMain setHandlerMain() { @@ -1855,11 +1946,13 @@ public class HttpAPI { String responseStatus = jsonObject.getString("Status"); getLogs().info("Status:" + responseStatus); if (responseStatus.equals("S")) { - //完成交易 - getHandlerMain().start(getClass().getSimpleName(), Option.TRANSACTION_SUCCESSFUL.getOption(), dataDecoder.replace("\t", "ⓣ")); + // 完成交易 + getHandlerMain().start(getClass().getSimpleName(), + Option.TRANSACTION_SUCCESSFUL.getOption(), dataDecoder.replace("\t", "ⓣ")); } else { - //Status:F 交易失敗 - getHandlerMain().start(getClass().getSimpleName(), Option.TRANSACTION_FAILED.getOption(), jsonObject.getString("ErrorDesc")); + // Status:F 交易失敗 + getHandlerMain().start(getClass().getSimpleName(), Option.TRANSACTION_FAILED.getOption(), + jsonObject.getString("ErrorDesc")); } } catch (UnsupportedEncodingException e) { getLogs().error(ErrorCode.ENCODING_AND_DECODING_ERROR, e.getLocalizedMessage()); @@ -1873,10 +1966,11 @@ public class HttpAPI { }); } - private void esunpay(String barcode, int totalPrice, FormPostMainScheduler formPostRunMain) throws LogsSettingEmptyException, LogsUnsupportedOperationException { + private void esunpay(String barcode, int totalPrice, FormPostMainScheduler formPostRunMain) + throws LogsSettingEmptyException, LogsUnsupportedOperationException { if (MyApp.getInstance().getEsunpay().getStoreID().isEmpty() || MyApp.getInstance().getEsunpay().getTermID().isEmpty() || - MyApp.getInstance().getEsunpay().getHash().isEmpty()) { + MyApp.getInstance().getEsunpay().getHash().isEmpty()) { throw new LogsSettingEmptyException(logs, "esunpay data is empty"); } @@ -1895,12 +1989,13 @@ public class HttpAPI { logs.info("transactionData data:" + TransactionData.toString()); -// "tradeapipayment{'StoreID':'xxxx', }sfsdgsdgwegg" + // "tradeapipayment{'StoreID':'xxxx', }sfsdgsdgwegg" JSONObject jsonObject = new JSONObject(); jsonObject.put("Type", "tradeapi"); jsonObject.put("Action", "payment"); jsonObject.put("TransactionData", URLEncoder.encode(TransactionData.toString(), Key.STRING_CHARSET_NAME)); - String HashDigest = Tools.getSHA256(jsonObject.getString("Type") + jsonObject.getString("Action") + jsonObject.getString("TransactionData") + MyApp.getInstance().getEsunpay().getHash()); + String HashDigest = Tools.getSHA256(jsonObject.getString("Type") + jsonObject.getString("Action") + + jsonObject.getString("TransactionData") + MyApp.getInstance().getEsunpay().getHash()); jsonObject.put("HashDigest", HashDigest); logs.info("send data:" + jsonObject.toString()); MyApp.getInstance().getReportFlowInfoData().setFlowSendInfo(jsonObject.toString()); @@ -1925,10 +2020,13 @@ public class HttpAPI { JSONObject receiveByJsonObject = new JSONObject(receive); getLogs().info("dataString date:" + receiveByJsonObject.toString()); - if (receiveByJsonObject.has("status") && receiveByJsonObject.getString("status").equals("success")) { - getHandlerMain().start(getClass().getSimpleName(), Option.TRANSACTION_SUCCESSFUL.getOption(), "transaction_successful"); + if (receiveByJsonObject.has("status") + && receiveByJsonObject.getString("status").equals("success")) { + getHandlerMain().start(getClass().getSimpleName(), + Option.TRANSACTION_SUCCESSFUL.getOption(), "transaction_successful"); } else { - getHandlerMain().start(getClass().getSimpleName(), Option.TRANSACTION_FAILED.getOption(), "transaction_failed"); + getHandlerMain().start(getClass().getSimpleName(), Option.TRANSACTION_FAILED.getOption(), + "transaction_failed"); } } catch (JSONException e) { getLogs().error(ErrorCode.JSON_FORMAT_ERROR, e.getLocalizedMessage()); @@ -1950,7 +2048,8 @@ public class HttpAPI { }); } - private void linepay(String barcode, int totalPrice, FormPostMainScheduler formPostRunMain) throws LogsParseException, LogsSettingEmptyException { + private void linepay(String barcode, int totalPrice, FormPostMainScheduler formPostRunMain) + throws LogsParseException, LogsSettingEmptyException { checkMachineInfo(); try { @@ -1966,7 +2065,8 @@ public class HttpAPI { MyApp.getInstance().getReportFlowInfoData().setFlowSendInfo(json.toString()); - formPostRunMain.start(domainNameByNewHost + "api/linepay/pay", json.toString(), null, null, HttpConnect.ContentType.JSON); + formPostRunMain.start(StarCloudAPI.domainNameByNewHost + "api/linepay/pay", json.toString(), null, null, + HttpConnect.ContentType.JSON); } catch (JSONException e) { throw new LogsParseException(logs, ErrorCode.JSON_FORMAT_ERROR, e); } @@ -1974,45 +2074,48 @@ public class HttpAPI { public void reportSlotList(ReportSlotListStructure data) throws LogsSettingEmptyException, LogsParseException { reportSlotList(new FormPutMainScheduler(getHandlerMain()) { - @Override - protected HandlerMain setHandlerMain() { - return getSrcHandlerMain(); - } + @Override + protected HandlerMain setHandlerMain() { + return getSrcHandlerMain(); + } - @Override - protected Class setCls() { - return getClass(); - } + @Override + protected Class setCls() { + return getClass(); + } - @Override - public void response(int responseCode, String receive, HandlerMain handlerMain) { - if (responseCode == 200) { - handlerMain.start(getClass().getSimpleName(), receive); - } else { - getLogs().error(ErrorCode.NETWORK_UNKNOWN_ERROR, "reportInvoiceInfo responseCode:" + responseCode); - } - } - }, + @Override + public void response(int responseCode, String receive, HandlerMain handlerMain) { + if (responseCode == 200) { + handlerMain.start(getClass().getSimpleName(), receive); + } else { + getLogs().error(ErrorCode.NETWORK_UNKNOWN_ERROR, "reportInvoiceInfo responseCode:" + responseCode); + } + } + }, data.getAccount(), data.getVmctype()); } - private void reportSlotList(FormPutMainScheduler formPutRunMain, String account, String vmctype) throws LogsSettingEmptyException, LogsParseException { + private void reportSlotList(FormPutMainScheduler formPutRunMain, String account, String vmctype) + throws LogsSettingEmptyException, LogsParseException { checkMachineInfo(); try { JSONArray jsonArray = new JSONArray(); - for (SlotField slotField: SlotField.values()) { + for (SlotField slotField : SlotField.values()) { for (SlotStructure slotData : MyApp.getInstance().getSlotList(slotField.getField())) { JSONObject productData = new JSONObject(); -// getLogs().info("aaaaaaaaaaaaaaaaaaaaaaa"+slotData.getProduct().getProductID()); + // getLogs().info("aaaaaaaaaaaaaaaaaaaaaaa"+slotData.getProduct().getProductID()); try { - if(!slotData.getProduct().getProductID().equals("?") || slotData.getProduct().getProductID() != "?") { + if (!slotData.getProduct().getProductID().equals("?") + || slotData.getProduct().getProductID() != "?") { productData.put("t060v00", slotData.getProduct().getProductID()); productData.put("num", String.valueOf(slotData.getCount())); - productData.put("tid", String.valueOf(slotData.getSlot()));// + slotField.getField());//這一行將Field把它隱藏起來,怕多出一個類別碼,客戶不好判斷 + productData.put("tid", String.valueOf(slotData.getSlot()));// + + // slotField.getField());//這一行將Field把它隱藏起來,怕多出一個類別碼,客戶不好判斷 productData.put("status", "0"); - }else{ + } else { continue; } } catch (JSONException e) { @@ -2026,20 +2129,23 @@ public class HttpAPI { jsonObject2.put("key", MyApp.getInstance().getMachine().getApiKey()); jsonObject2.put("machine", MyApp.getInstance().getMachine().getMachineID()); jsonObject2.put("account", account); - //String vmcType = myApp.AppConfig.getString("vmcType", ""); - //if (vmcType.equals("XinYuan")) { - //String subVMC = myApp.AppConfig.getString("subVMC1", ""); + // String vmcType = myApp.AppConfig.getString("vmcType", ""); + // if (vmcType.equals("XinYuan")) { + // String subVMC = myApp.AppConfig.getString("subVMC1", ""); jsonObject2.put("vmcType", vmctype); - /*} else if (vmcType.equals("Easivend")) { - String[] subVMC1 = myApp.AppConfig.getString("subVMC1", "").split(","); - String[] subVMC2 = myApp.AppConfig.getString("subVMC2", "").split(","); - jsonObject2.put("vmcType", subVMC1[0] + "," + subVMC2[0]); - }*/ + /* + * } else if (vmcType.equals("Easivend")) { + * String[] subVMC1 = myApp.AppConfig.getString("subVMC1", "").split(","); + * String[] subVMC2 = myApp.AppConfig.getString("subVMC2", "").split(","); + * jsonObject2.put("vmcType", subVMC1[0] + "," + subVMC2[0]); + * } + */ jsonObject2.put("data", jsonArray); - getLogs().info("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa="+jsonObject2.toString()); + getLogs().info("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=" + jsonObject2.toString()); - formPutRunMain.start(domainNameByUnibuy + "products/supplementary/B009", jsonObject2.toString(), null, null, HttpConnect.ContentType.JSON); + formPutRunMain.start(domainNameByUnibuy + "products/supplementary/B009", jsonObject2.toString(), null, null, + HttpConnect.ContentType.JSON); } catch (JSONException e) { throw new LogsParseException(logs, ErrorCode.JSON_FORMAT_ERROR, e); } @@ -2088,8 +2194,7 @@ public class HttpAPI { json.toString(), null, null, - HttpConnect.ContentType.JSON - ); + HttpConnect.ContentType.JSON); } catch (JSONException e) { throw new LogsParseException(logs, ErrorCode.JSON_FORMAT_ERROR, e); } @@ -2115,23 +2220,22 @@ public class HttpAPI { JSONArray deliveryItem = receiveByJsonObject.getJSONArray("data"); JSONObject deliveryData = deliveryItem.getJSONObject(0); - /* - req1 執行命令id - req2 貨道id - */ + /* + * req1 執行命令id + * req2 貨道id + */ int slotid = Integer.parseInt(deliveryData.getString("tid")); int slotnum = Integer.parseInt(deliveryData.getString("num")); - getLogs().info("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"+slotid+" "+slotnum); + getLogs().info("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + slotid + " " + slotnum); slotid = slotid; SlotsDao slotsDao = new SlotsDao(handlerMain.getContext()); - slotsDao.updateCount(0,slotid,slotnum);//更新該貨道的數量(庫存) + slotsDao.updateCount(0, slotid, slotnum);// 更新該貨道的數量(庫存) slotsDao.close(); - AppUtils.resetApp(handlerMain.getContext()); } catch (JSONException e) { @@ -2142,14 +2246,16 @@ public class HttpAPI { }); } - private void reportSlotPost(FormPostMainScheduler formPostRunMain) throws LogsSettingEmptyException, LogsParseException { + private void reportSlotPost(FormPostMainScheduler formPostRunMain) + throws LogsSettingEmptyException, LogsParseException { checkMachineInfo(); try { JSONObject json = new JSONObject(); json.put("key", MyApp.getInstance().getMachine().getApiKey()); json.put("machine", MyApp.getInstance().getMachine().getMachineID()); - formPostRunMain.start(domainNameByUnibuy + "machine/reload_msg/B017", json.toString(), null, null, HttpConnect.ContentType.X_WWW_FORM_URLENCODEED); + formPostRunMain.start(domainNameByUnibuy + "machine/reload_msg/B017", json.toString(), null, null, + HttpConnect.ContentType.X_WWW_FORM_URLENCODEED); } catch (JSONException e) { throw new LogsParseException(logs, ErrorCode.JSON_FORMAT_ERROR, e); } diff --git a/app/src/main/java/com/unibuy/smartdevice/external/StarCloudAPI.java b/app/src/main/java/com/unibuy/smartdevice/external/StarCloudAPI.java index e4a004e..410d922 100644 --- a/app/src/main/java/com/unibuy/smartdevice/external/StarCloudAPI.java +++ b/app/src/main/java/com/unibuy/smartdevice/external/StarCloudAPI.java @@ -35,6 +35,10 @@ import java.util.ArrayList; public class StarCloudAPI { private static final String TAG = "StarCloudAPI"; + public static String domainNameByNewHost = "https://logs.setdomains.work/"; + public static String updateOnDomainNameByNewHost = domainNameByNewHost + "api/machine/" + + MyApp.getInstance().getMachine().getMachineID() + "/log/update"; + private String getBaseUrl() { if ("prod".equals(MyApp.getInstance().getMachine().getMqttEnv())) { return "https://starcloud.taiwan-star.com.tw/api/v1/app/"; @@ -55,9 +59,14 @@ public class StarCloudAPI { * B000: 管理員登入驗證 */ public void login(final String account, final String password) { + login(account, password, "NO_TRACE", System.currentTimeMillis()); + } + + public void login(final String account, final String password, final String traceId, final long startMs) { Log.i(TAG, "login() called for account: " + account); final String url = getBaseUrl() + "admin/login/B000"; Log.i(TAG, "Starting B000 request to: " + url); + Log.i("LoginTrace", "[" + traceId + "] b000_start fromUiMs=" + (System.currentTimeMillis() - startMs)); // 不依賴 FormPostMainScheduler (會靜默吞掉 IO exception) // 直接用 Thread + HttpURLConnection 確保錯誤一定看得到 @@ -66,6 +75,7 @@ public class StarCloudAPI { public void run() { int responseCode = -1; String receive = ""; + long threadStartMs = System.currentTimeMillis(); try { JSONObject json = new JSONObject(); json.put("Su_Account", account); @@ -90,10 +100,15 @@ public class StarCloudAPI { conn.setDoOutput(true); byte[] bodyBytes = json.toString().getBytes("UTF-8"); + long writeStartMs = System.currentTimeMillis(); conn.getOutputStream().write(bodyBytes); conn.getOutputStream().flush(); + Log.i("LoginTrace", "[" + traceId + "] b000_write_done tMs=" + (System.currentTimeMillis() - writeStartMs)); + long responseStartMs = System.currentTimeMillis(); responseCode = conn.getResponseCode(); + Log.i("LoginTrace", "[" + traceId + "] b000_response_code=" + responseCode + + " waitMs=" + (System.currentTimeMillis() - responseStartMs)); java.io.InputStream is = (responseCode >= 200 && responseCode < 300) ? conn.getInputStream() : conn.getErrorStream(); java.io.BufferedReader br = new java.io.BufferedReader( @@ -105,8 +120,12 @@ public class StarCloudAPI { conn.disconnect(); Log.d(TAG, "B000 Response (" + responseCode + "): " + receive); + Log.i("LoginTrace", "[" + traceId + "] b000_network_done totalNetMs=" + + (System.currentTimeMillis() - threadStartMs)); } catch (final Exception e) { Log.e(TAG, "B000 Network Error", e); + Log.e("LoginTrace", "[" + traceId + "] b000_network_error afterMs=" + + (System.currentTimeMillis() - threadStartMs) + " err=" + e.getMessage()); new android.os.Handler(android.os.Looper.getMainLooper()).post(new Runnable() { @Override public void run() { @@ -122,6 +141,7 @@ public class StarCloudAPI { new android.os.Handler(android.os.Looper.getMainLooper()).post(new Runnable() { @Override public void run() { + long mainStartMs = System.currentTimeMillis(); if (finalCode >= 200 && finalCode < 300) { try { JSONObject res = new JSONObject(finalReceive); @@ -129,16 +149,28 @@ public class StarCloudAPI { MyApp.getInstance().setSuAccess(res.optString("Su_Account", account)); // 移除覆蓋 ApiKey 的邏輯,因為 B000 回傳的可能是 Admin Token,但我們需要保留 Machine Token Log.i(TAG, "Login success for user: " + account); + Log.i("LoginTrace", "[" + traceId + "] b000_parse_success parseMs=" + + (System.currentTimeMillis() - mainStartMs) + + " totalMs=" + (System.currentTimeMillis() - startMs)); handlerMain.start("StarCloudAPI", 200, "登入成功"); } else { + Log.w("LoginTrace", "[" + traceId + "] b000_business_fail code=401 parseMs=" + + (System.currentTimeMillis() - mainStartMs) + + " totalMs=" + (System.currentTimeMillis() - startMs)); handlerMain.start("StarCloudAPI", 401, "登入失敗: " + res.optString("message", "帳號密碼錯誤")); } } catch (Exception e) { Log.e(TAG, "B000 Parse Error: " + e.getMessage()); + Log.e("LoginTrace", "[" + traceId + "] b000_parse_error parseMs=" + + (System.currentTimeMillis() - mainStartMs) + + " totalMs=" + (System.currentTimeMillis() - startMs) + + " err=" + e.getMessage()); handlerMain.start("StarCloudAPI", 500, "登入解析失敗: " + e.getMessage()); } } else { + Log.w("LoginTrace", "[" + traceId + "] b000_http_fail code=" + finalCode + + " totalMs=" + (System.currentTimeMillis() - startMs)); handlerMain.start("StarCloudAPI", finalCode, "網路錯誤 (" + finalCode + "): " + finalReceive); } diff --git a/app/src/main/java/com/unibuy/smartdevice/tools/HttpConnect.java b/app/src/main/java/com/unibuy/smartdevice/tools/HttpConnect.java index f62d102..8838398 100644 --- a/app/src/main/java/com/unibuy/smartdevice/tools/HttpConnect.java +++ b/app/src/main/java/com/unibuy/smartdevice/tools/HttpConnect.java @@ -361,10 +361,11 @@ public class HttpConnect { return outputFile; } - public void uploadFile(String uploadUrl, File logFile) { + public boolean uploadFile(String uploadUrl, File logFile) { HttpURLConnection connection = null; DataOutputStream outputStream = null; FileInputStream fileInputStream = null; + boolean uploadSuccess = false; String boundary = "*****"; // 分隔符 String lineEnd = "\r\n"; @@ -373,7 +374,7 @@ public class HttpConnect { try { if (!logFile.exists()) { logs.debug("檔案不存在:" + logFile.getAbsolutePath()); - return; + return false; } logs.debug("開始上傳:" + logFile.getAbsolutePath()); @@ -413,6 +414,7 @@ public class HttpConnect { if (responseCode == HttpURLConnection.HTTP_OK) { logs.info("Log 上傳成功!"); logFile.delete(); + uploadSuccess = true; } else { logs.debug("Log 上傳失敗,HTTP 狀態碼:" + responseCode); @@ -444,6 +446,8 @@ public class HttpConnect { connection.disconnect(); } } + + return uploadSuccess; } public File getFileFromUrl(String urlString) throws LogsFileNullException, LogsEmptyException { diff --git a/app/src/main/java/com/unibuy/smartdevice/tools/TransactionFinalizeBuilder.java b/app/src/main/java/com/unibuy/smartdevice/tools/TransactionFinalizeBuilder.java index 79d8884..1a14406 100644 --- a/app/src/main/java/com/unibuy/smartdevice/tools/TransactionFinalizeBuilder.java +++ b/app/src/main/java/com/unibuy/smartdevice/tools/TransactionFinalizeBuilder.java @@ -34,7 +34,7 @@ public class TransactionFinalizeBuilder { private final String orderMachineTime; /** 機台本地流水號(格式:YYYYMMDDXXXX,例如 202605110001) */ - private final String flowId; + private String flowId; /** 累積的出貨結果清單 */ private final List dispenseRecords = new ArrayList<>(); @@ -48,6 +48,10 @@ public class TransactionFinalizeBuilder { Log.i(TAG, "TransactionFinalizeBuilder created, flow_id=" + this.flowId); } + public void setFlowId(String flowId) { + this.flowId = flowId; + } + public void setCodeId(String codeId) { this.codeId = codeId; } diff --git a/app/src/main/java/com/unibuy/smartdevice/ui/FontendActivity.java b/app/src/main/java/com/unibuy/smartdevice/ui/FontendActivity.java index c30b750..b45716e 100644 --- a/app/src/main/java/com/unibuy/smartdevice/ui/FontendActivity.java +++ b/app/src/main/java/com/unibuy/smartdevice/ui/FontendActivity.java @@ -463,6 +463,11 @@ public class FontendActivity extends AppCompatActivityAbstract implements SaleFl Process.killProcess(Process.myPid()); } + public SaleFlowHandler getSaleFlowHandler() { + return saleFlowHandler; + } + + public void startOnSwitchFragment() { try { stopOnSwitchFragment(); // ✅ 先安全釋放舊播放器 diff --git a/app/src/main/java/com/unibuy/smartdevice/ui/devs/vmc/VmcFragment.java b/app/src/main/java/com/unibuy/smartdevice/ui/devs/vmc/VmcFragment.java index a1a64d0..03fb8fe 100644 --- a/app/src/main/java/com/unibuy/smartdevice/ui/devs/vmc/VmcFragment.java +++ b/app/src/main/java/com/unibuy/smartdevice/ui/devs/vmc/VmcFragment.java @@ -24,6 +24,9 @@ import com.unibuy.smartdevice.structure.ProductStructure; import com.unibuy.smartdevice.structure.SlotStructure; import com.unibuy.smartdevice.tools.HandlerMain; import com.unibuy.smartdevice.tools.ToastHandlerMain; +import com.unibuy.smartdevice.ui.FontendActivity; +import com.unibuy.smartdevice.ui.SaleFlowHandler; + import java.util.ArrayList; import java.util.HashMap; @@ -231,7 +234,16 @@ public class VmcFragment extends FragmentAbstract { setUseStartOnSwitchFragment(false); } + // 解決生命週期時序競爭:VmcFragment 視圖加載完成後重新綁定大掃碼按鈕 + if (getActivity() instanceof FontendActivity) { + com.unibuy.smartdevice.ui.SaleFlowHandler handler = ((FontendActivity) getActivity()).getSaleFlowHandler(); + if (handler != null) { + handler.onSetupUI(root); + } + } + return root; + } /** diff --git a/app/src/main/java/com/unibuy/smartdevice/ui/devs/vmc/VmcSlotListActivity.java b/app/src/main/java/com/unibuy/smartdevice/ui/devs/vmc/VmcSlotListActivity.java index 4ed4c65..c144f4e 100644 --- a/app/src/main/java/com/unibuy/smartdevice/ui/devs/vmc/VmcSlotListActivity.java +++ b/app/src/main/java/com/unibuy/smartdevice/ui/devs/vmc/VmcSlotListActivity.java @@ -13,6 +13,7 @@ import androidx.recyclerview.widget.LinearLayoutManager; import com.unibuy.smartdevice.AppCompatActivityAbstract; import com.unibuy.smartdevice.MyApp; +import com.unibuy.smartdevice.R; import com.unibuy.smartdevice.databinding.ActivityVmcSlotListBinding; import com.unibuy.smartdevice.devices.SlotField; import com.unibuy.smartdevice.exception.ErrorCode; @@ -28,6 +29,9 @@ import com.unibuy.smartdevice.tools.HandlerMain; import com.unibuy.smartdevice.tools.ToastHandlerMain; import com.unibuy.smartdevice.ui.devs.electric.ElectricSlotListActivity; +import java.util.HashMap; +import java.util.Map; + public class VmcSlotListActivity extends AppCompatActivityAbstract { private ActivityVmcSlotListBinding binding; private ActivityResultLauncher resultLauncher; @@ -146,6 +150,11 @@ public class VmcSlotListActivity extends AppCompatActivityAbstract { if (currentFocus != null) { currentFocus.clearFocus(); } + String validationError = validateMaterialCodeConsistency(); + if (!validationError.isEmpty()) { + getHandlerMain().start(getClass().getSimpleName(), "@" + validationError); + return; + } // 1. 本地儲存 saveData(); @@ -270,4 +279,18 @@ public class VmcSlotListActivity extends AppCompatActivityAbstract { getLogs().error(ErrorCode.NETWORK_UNKNOWN_ERROR, "同步啟動失敗: " + e.getMessage()); } } -} \ No newline at end of file + + private String validateMaterialCodeConsistency() { + for (SlotStructure slot : MyApp.getInstance().getSlotList(SlotField.VMC.getField())) { + if (slot == null || slot.getProduct() == null) continue; + ProductStructure product = slot.getProduct(); + String productId = product.getProductID() == null ? "" : product.getProductID().trim(); + if (productId.isEmpty() || "?".equals(productId)) continue; + String materialCode = product.getMaterialCode() == null ? "" : product.getMaterialCode().trim(); + if (materialCode.isEmpty()) { + return getString(R.string.vmc_material_code_empty, slot.getSlot(), productId); + } + } + return ""; + } +} diff --git a/app/src/main/java/com/unibuy/smartdevice/ui/dialog/DispatchDialog.java b/app/src/main/java/com/unibuy/smartdevice/ui/dialog/DispatchDialog.java index d04ce0e..89f6650 100644 --- a/app/src/main/java/com/unibuy/smartdevice/ui/dialog/DispatchDialog.java +++ b/app/src/main/java/com/unibuy/smartdevice/ui/dialog/DispatchDialog.java @@ -23,6 +23,7 @@ import com.unibuy.smartdevice.controller.DevController; import com.unibuy.smartdevice.controller.DevDigitalDisplayController; import com.unibuy.smartdevice.controller.DevElectricController; import com.unibuy.smartdevice.database.SlotsDao; +import com.unibuy.smartdevice.database.MemoDao; import com.unibuy.smartdevice.databinding.DialogDispatchBinding; import com.unibuy.smartdevice.devices.ComPort; @@ -43,6 +44,7 @@ import com.unibuy.smartdevice.structure.ProductStructure; import com.unibuy.smartdevice.structure.ReportDispatchInfoStructure; import com.unibuy.smartdevice.structure.ReportFreeGiftCodeStructure; import com.unibuy.smartdevice.structure.SlotStructure; +import com.unibuy.smartdevice.structure.MemoStructure; import com.unibuy.smartdevice.tools.HandlerMainCountdown; import com.unibuy.smartdevice.tools.HandlerMain; import com.unibuy.smartdevice.tools.ToastHandlerMain; @@ -53,6 +55,7 @@ import com.unibuy.smartdevice.ui.tools.ImageGlide; import com.unibuy.smartdevice.ui.tools.StringRefactoring; import com.unibuy.smartdevice.worker.UploadLogOneTimeWorker; +import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -249,6 +252,9 @@ public class DispatchDialog extends DialogAbstract { httpAPI = new HttpAPI(getHandlerMain()); // 初始化 Finalize Builder(在支付完成、進入出貨流程時建立) finalizeBuilder = new TransactionFinalizeBuilder(); + if ("Cmuh".equalsIgnoreCase(com.unibuy.smartdevice.BuildConfig.FLAVOR_project)) { + MyApp.getInstance().getReportFlowInfoData().setFlowType(42); + } MyApp.getInstance().setReportFreeGiftCodeStructure(new ReportFreeGiftCodeStructure("", 0, "", 0, 0, "")); @@ -296,6 +302,56 @@ public class DispatchDialog extends DialogAbstract { getLogs().info("DispatchList size:" + this.dispatchList.size()); + if ("Cmuh".equalsIgnoreCase(com.unibuy.smartdevice.BuildConfig.FLAVOR_project)) { + try { + String patName = "未知患者"; + String sn = ""; + String drgNo = ""; + + // 優先從全域解密資料讀取(最完整,包含姓名與領藥號) + String decryptedStr = MyApp.getInstance().getDecryptedData(); + if (decryptedStr != null && !decryptedStr.isEmpty()) { + JSONObject fullJson = new JSONObject(decryptedStr); + patName = fullJson.optString("NAME", ""); + if (patName.isEmpty()) patName = fullJson.optString("PATNAME", ""); + if (patName.isEmpty()) patName = fullJson.optString("patName", ""); + if (patName.isEmpty()) patName = "未知患者"; + + sn = fullJson.optString("SN", ""); + drgNo = fullJson.optString("DRGNO", ""); + } + + // 如果全域資料讀不到,嘗試從商品行銷計劃 (marketingPlan) 讀取 (備用防呆) + if (sn.isEmpty() && this.dispatchList != null && !this.dispatchList.isEmpty()) { + String marketingPlan = this.dispatchList.get(0).getProduct().getMarketingPlan(); + if (marketingPlan != null && !marketingPlan.isEmpty()) { + JSONObject rxJson = new JSONObject(marketingPlan); + sn = rxJson.optString("SN", ""); + if (drgNo.isEmpty()) { + drgNo = rxJson.optString("DRGNO", ""); + } + } + } + + // 按照最新要求:[患者姓名]([藥單號]) 用括號 + String barcodeInfo = patName + "(" + drgNo + ")"; + getLogs().info("✅ 中國醫 QR Code 取物單資訊打包上報:姓名 " + patName + ", 藥單號 " + drgNo + " -> barcodeInfo: " + barcodeInfo); + + // 設定到 flowBarCode (會連動到後台 member_barcode 欄位) + MyApp.getInstance().getReportFlowInfoData().setFlowBarCode(barcodeInfo); + + // 序號是 flow_id,將交易流水號與本地 OrderId / ReportFlowId 覆寫為純藥單序號 SN + if (sn != null && !sn.isEmpty()) { + finalizeBuilder.setFlowId(sn); + MyApp.getInstance().getReportFlowInfoData().setOrderId(sn); + MyApp.getInstance().getReportFlowInfoData().setReportFlowId(sn); + getLogs().info("✅ 交易流水號已成功覆寫為純藥單序號 (SN):" + sn); + } + } catch (Exception e) { + getLogs().warning(e); + } + } + this.recyclerDialogDispatchListAdpter = new RecyclerDialogDispatchListAdpter(getCtx(), this.dispatchList, getHandlerMain()); this.binding.recyclerDialogDispatchList.setAdapter(recyclerDialogDispatchListAdpter); this.binding.recyclerDialogDispatchList.setLayoutManager(new LinearLayoutManager(context)); @@ -452,17 +508,31 @@ public class DispatchDialog extends DialogAbstract { getSrcHandlerMain().start(getClass().getSimpleName(), Option.ERROR_PROCESS_GOODS.getOption(), getCtx().getString(R.string.check_whether_goods_have_been_taken_out_before_confirming_collection));//請檢查商品有無取出再確認取貨 } } else { - if (checkSlotRunCount >= 3) { + boolean isCmuh = "Cmuh".equalsIgnoreCase(com.unibuy.smartdevice.BuildConfig.FLAVOR_project); + int maxRetries = isCmuh ? 10 : 3; + if (checkSlotRunCount >= maxRetries) { buttonControlCountdown.shutdown(); - getSrcHandlerMain().start(getClass().getSimpleName(), Option.ERROR_PROCESS_GOODS.getOption(), getCtx().getString(R.string.slave_computer_did_not_respond_wait_3_seconds_try_again));//下位機無回應 請等3秒後再重試 + if (isCmuh) { + getLogs().info("機台未回應,已達 Cmuh 最大重試次數 10 次,嘗試重新連線下位機"); + insertDrgnoToMemo(); // 領藥失敗,新增醫令至 Memo 防止雙重領取 + MyApp.getInstance().getDevXinYuanController().start(); + if (!MyApp.checkAndReconnectDev()) { + getLogs().info("無法連線到下位機,出貨作業中止"); + } + getSrcHandlerMain().start(getClass().getSimpleName(), Option.ERROR_PROCESS_GOODS.getOption(), "領藥有問題 請等3秒後再重掃"); + } else { + getSrcHandlerMain().start(getClass().getSimpleName(), Option.ERROR_PROCESS_GOODS.getOption(), getCtx().getString(R.string.slave_computer_did_not_respond_wait_3_seconds_try_again)); + MyApp.getInstance().getDevXinYuanController().start(); + } checkSlotRunCount = 0; - MyApp.getInstance().getDevXinYuanController().start(); } else { - getLogs().info("機台未回應,第 " + (checkSlotRunCount + 1) + " 次重試 checkSlot..."); + getLogs().info("機台未回應,第 " + (checkSlotRunCount + 1) + " 次重試 checkSlot..." + (isCmuh ? " (溫和模式,不發送指令)" : "")); isCheckSlotByVMC = false; // 重置旗標,允許下次回調進入 checkSlotRunCount++; MyApp.getInstance().getDevXinYuanController().getReadBufferByNow(new DevCheckSlotByVMC(handlerMain, slot)); - MyApp.getInstance().getDevXinYuanController().addSendBuffer(MyApp.getInstance().getDevXinYuanController().getDevXinYuan().checkSlot(slot)); + if (!isCmuh) { + MyApp.getInstance().getDevXinYuanController().addSendBuffer(MyApp.getInstance().getDevXinYuanController().getDevXinYuan().checkSlot(slot)); + } } } } @@ -825,10 +895,13 @@ public class DispatchDialog extends DialogAbstract { if (isFinalizing) return; // 防呆:如果已經在結案倒數了,直接跳出 isFinalizing = true; - getLogs().info("所有商品出貨完畢,發送 MQTT Finalize 結案訊息。"); - MqttManager.getInstance().publishTransactionFinalize(finalizeBuilder.build()); - getSrcHandlerMain().send(getClass().getSimpleName(), FontendActivity.Option.RESET_DATA.getOption(), "update data"); - saveData(); + getLogs().info("所有商品出貨完畢,發送 MQTT Finalize 結案訊息。"); + if ("Cmuh".equalsIgnoreCase(com.unibuy.smartdevice.BuildConfig.FLAVOR_project)) { + insertDrgnoToMemo(); + } + MqttManager.getInstance().publishTransactionFinalize(finalizeBuilder.build()); + getSrcHandlerMain().send(getClass().getSimpleName(), FontendActivity.Option.RESET_DATA.getOption(), "update data"); + saveData(); getLogs().info("📦 出貨狀況總結:"); for (String logItem : deliveryLogs) { @@ -1054,4 +1127,48 @@ public class DispatchDialog extends DialogAbstract { } } + public void insertDrgnoToMemo() { + try { + /*刷藥單解碼後進來的json資料*/ + JSONObject jsonObject = new JSONObject(dispatchList.get(0).getProduct().getMarketingPlan()); + // **要新增的 ITEM 資料** + JSONObject newItem = new JSONObject(); + newItem.put("SN", jsonObject.optString("SN")); // **領藥人藥單序號** + newItem.put("DRGNO", jsonObject.optString("DRGNO")); // **領藥人醫令** + + /*從Memo的JSON資料中,讀取SN及DRGNO的全部資料*/ + String jsonStr = MyApp.getInstance().getMemoMap().get("CMUH").get(0).getData().toString(); + JSONObject jsonObject2 = new JSONObject(jsonStr); + JSONArray itemArray = jsonObject2.getJSONArray("ITEM"); + + // **判斷是否已存在** + boolean exists = false; + for (int i = 0; i < itemArray.length(); i++) { + JSONObject item = itemArray.getJSONObject(i); + if (item.getString("SN").equals(newItem.getString("SN")) && item.getString("DRGNO").equals(newItem.getString("DRGNO"))) { + exists = true; + break; // **如果已存在,就結束迴圈** + } + } + + // **如果不存在,才加入** + if (!exists) { + itemArray.put(newItem); + getLogs().info("✅ 領藥人醫令新增到Memo成功:" + newItem.toString()); + } else { + getLogs().info("⚠️ 領藥人醫令已存在,不新增!"); + } + + // **輸出結果**並新增到Memo 的 SQLite資料庫 data欄位中 + MyApp.getInstance().getMemoMap().get("CMUH").get(0).setData(jsonObject2); + // ✅ 寫入 SQLite + MemoStructure updatedMemo = MyApp.getInstance().getMemoMap().get("CMUH").get(0); + MemoDao memoDao = new MemoDao(getCtx()); + memoDao.insertOnlyOne(updatedMemo); + memoDao.close(); + } catch (JSONException e) { + throw new RuntimeException(e); + } + } + } diff --git a/app/src/main/java/com/unibuy/smartdevice/worker/UploadLogOneTimeWorker.java b/app/src/main/java/com/unibuy/smartdevice/worker/UploadLogOneTimeWorker.java index 35276ad..c3e1608 100644 --- a/app/src/main/java/com/unibuy/smartdevice/worker/UploadLogOneTimeWorker.java +++ b/app/src/main/java/com/unibuy/smartdevice/worker/UploadLogOneTimeWorker.java @@ -9,6 +9,7 @@ import androidx.work.WorkerParameters; import com.unibuy.smartdevice.MyApp; import com.unibuy.smartdevice.exception.Logs; import com.unibuy.smartdevice.external.HttpAPI; +import com.unibuy.smartdevice.external.StarCloudAPI; import com.unibuy.smartdevice.tools.HttpConnect; import com.unibuy.smartdevice.tools.Tools; @@ -32,31 +33,60 @@ public class UploadLogOneTimeWorker extends Worker { if (MyApp.getInstance().getMachine().getMachineID().isEmpty()) { logs.debug("背景工作執行失敗:沒有機器序號,使用暫時序號 00000000"); - HttpAPI.updateOnDomainNameByNewHost = HttpAPI.domainNameByNewHost + "api/machine/00000000/log/update"; + StarCloudAPI.updateOnDomainNameByNewHost = StarCloudAPI.domainNameByNewHost + "api/machine/00000000/log/update"; } else { - HttpAPI.updateOnDomainNameByNewHost = HttpAPI.domainNameByNewHost + "api/machine/" + MyApp.getInstance().getMachine().getMachineID() + "/log/update"; + StarCloudAPI.updateOnDomainNameByNewHost = StarCloudAPI.domainNameByNewHost + "api/machine/" + MyApp.getInstance().getMachine().getMachineID() + "/log/update"; } - logs.debug("url:" + HttpAPI.updateOnDomainNameByNewHost); + logs.debug("url:" + StarCloudAPI.updateOnDomainNameByNewHost); File txtDebug = new File(Tools.getExternalFilesDir(), "debug.txt"); - String yyyyMMddHHmmByNow = Tools.getStringByNow("yyyyMMddHHmm"); - if (yyyyMMddHHmmByNow.length() == 12) { - yyyyMMddHHmmByNow = yyyyMMddHHmmByNow.substring(0, 11) + "0"; - } - File newFile = new File(Tools.getExternalFilesDir(), yyyyMMddHHmmByNow + ".txt"); + // 1. 旋轉目前的 debug.txt + if (txtDebug.exists() && txtDebug.length() > 0) { + String yyyyMMddHHmmByNow = Tools.getStringByNow("yyyyMMddHHmm"); + if (yyyyMMddHHmmByNow.length() == 12) { + yyyyMMddHHmmByNow = yyyyMMddHHmmByNow.substring(0, 11) + "0"; + } + // 加上毫秒時間戳記,確保檔名在任何情況下都唯一,防止 renameTo 失敗 + String uniqueFileName = yyyyMMddHHmmByNow + "_" + System.currentTimeMillis() + ".txt"; + File newFile = new File(Tools.getExternalFilesDir(), uniqueFileName); - if (txtDebug.exists()) { boolean renamed = txtDebug.renameTo(newFile); logs.debug("newFile:" + newFile.getAbsolutePath() + " renamed:" + renamed); - if (renamed) { - HttpConnect httpConnect = new HttpConnect(); - httpConnect.uploadFile(HttpAPI.updateOnDomainNameByNewHost, newFile); + if (!renamed) { + logs.debug("重新命名日誌檔失敗,將重試。"); + return Result.retry(); } } - return Result.success();// 工作成功 + // 2. 掃描 ExternalFilesDir 批次補上傳非 active 的所有 txt 日誌檔 + File dir = Tools.getExternalFilesDir(); + boolean anyUploadFailed = false; + if (dir != null && dir.exists()) { + File[] files = dir.listFiles((d, name) -> name.endsWith(".txt") + && !name.equals("debug.txt") + && !name.equals("crash_pending.txt")); + + if (files != null && files.length > 0) { + logs.debug("發現待上傳歷史日誌共 " + files.length + " 個,開始批次上傳。"); + HttpConnect httpConnect = new HttpConnect(); + for (File file : files) { + boolean success = httpConnect.uploadFile(StarCloudAPI.updateOnDomainNameByNewHost, file); + if (!success) { + logs.debug("檔案上傳失敗,保留至下次重試:" + file.getName()); + anyUploadFailed = true; + } + } + } + } + + if (anyUploadFailed) { + logs.debug("部分歷史日誌上傳失敗,排程重試中。"); + return Result.retry(); + } + + return Result.success(); } } \ No newline at end of file diff --git a/app/src/main/java/com/unibuy/smartdevice/worker/UploadLogPeriodicWorker.java b/app/src/main/java/com/unibuy/smartdevice/worker/UploadLogPeriodicWorker.java index 6722bcf..b0d05e5 100644 --- a/app/src/main/java/com/unibuy/smartdevice/worker/UploadLogPeriodicWorker.java +++ b/app/src/main/java/com/unibuy/smartdevice/worker/UploadLogPeriodicWorker.java @@ -9,6 +9,7 @@ import androidx.work.WorkerParameters; import com.unibuy.smartdevice.MyApp; import com.unibuy.smartdevice.exception.Logs; import com.unibuy.smartdevice.external.HttpAPI; +import com.unibuy.smartdevice.external.StarCloudAPI; import com.unibuy.smartdevice.tools.HttpConnect; import com.unibuy.smartdevice.tools.Tools; @@ -47,33 +48,60 @@ public class UploadLogPeriodicWorker extends Worker { if (MyApp.getInstance().getMachine().getMachineID().isEmpty()) { logs.debug("背景工作執行失敗:沒有機器序號,使用暫時序號 00000000"); - HttpAPI.updateOnDomainNameByNewHost = HttpAPI.domainNameByNewHost + "api/machine/00000000/log/update"; + StarCloudAPI.updateOnDomainNameByNewHost = StarCloudAPI.domainNameByNewHost + "api/machine/00000000/log/update"; } else { - HttpAPI.updateOnDomainNameByNewHost = HttpAPI.domainNameByNewHost + "api/machine/" + MyApp.getInstance().getMachine().getMachineID() + "/log/update"; + StarCloudAPI.updateOnDomainNameByNewHost = StarCloudAPI.domainNameByNewHost + "api/machine/" + MyApp.getInstance().getMachine().getMachineID() + "/log/update"; } - logs.debug("url:" + HttpAPI.updateOnDomainNameByNewHost); + logs.debug("url:" + StarCloudAPI.updateOnDomainNameByNewHost); File txtDebug = new File(Tools.getExternalFilesDir(), "debug.txt"); - String yyyyMMddHHmmByNow = Tools.getStringByNow("yyyyMMddHHmm"); - if (yyyyMMddHHmmByNow.length() == 12) { - yyyyMMddHHmmByNow = yyyyMMddHHmmByNow.substring(0, 11) + "0"; - } - File newFile = new File(Tools.getExternalFilesDir(), yyyyMMddHHmmByNow + ".txt"); + // 1. 旋轉目前的 debug.txt + if (txtDebug.exists() && txtDebug.length() > 0) { + String yyyyMMddHHmmByNow = Tools.getStringByNow("yyyyMMddHHmm"); + if (yyyyMMddHHmmByNow.length() == 12) { + yyyyMMddHHmmByNow = yyyyMMddHHmmByNow.substring(0, 11) + "0"; + } + // 加上毫秒時間戳記,確保檔名在任何情況下都唯一,防止 renameTo 失敗 + String uniqueFileName = yyyyMMddHHmmByNow + "_" + System.currentTimeMillis() + ".txt"; + File newFile = new File(Tools.getExternalFilesDir(), uniqueFileName); - if (txtDebug.exists()) { boolean renamed = txtDebug.renameTo(newFile); logs.debug("newFile:" + newFile.getAbsolutePath() + " renamed:" + renamed); - if (renamed) { - HttpConnect httpConnect = new HttpConnect(); - httpConnect.uploadFile(HttpAPI.updateOnDomainNameByNewHost, newFile); - } else { + if (!renamed) { + logs.debug("重新命名日誌檔失敗,將重試。"); return Result.retry(); } } + // 2. 掃描 ExternalFilesDir 批次補上傳非 active 的所有 txt 日誌檔 + File dir = Tools.getExternalFilesDir(); + boolean anyUploadFailed = false; + if (dir != null && dir.exists()) { + File[] files = dir.listFiles((d, name) -> name.endsWith(".txt") + && !name.equals("debug.txt") + && !name.equals("crash_pending.txt")); + + if (files != null && files.length > 0) { + logs.debug("發現待上傳歷史日誌共 " + files.length + " 個,開始批次上傳。"); + HttpConnect httpConnect = new HttpConnect(); + for (File file : files) { + boolean success = httpConnect.uploadFile(StarCloudAPI.updateOnDomainNameByNewHost, file); + if (!success) { + logs.debug("檔案上傳失敗,保留至下次重試:" + file.getName()); + anyUploadFailed = true; + } + } + } + } + + if (anyUploadFailed) { + logs.debug("部分歷史日誌上傳失敗,排程重試中。"); + return Result.retry(); + } + return Result.success(); } } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_fontend.xml b/app/src/main/res/layout/activity_fontend.xml index 4fde6e8..e728102 100644 --- a/app/src/main/res/layout/activity_fontend.xml +++ b/app/src/main/res/layout/activity_fontend.xml @@ -107,8 +107,8 @@ - \ No newline at end of file + diff --git a/app/src/main/res/values-en/strings.xml b/app/src/main/res/values-en/strings.xml index 54ebafa..606c525 100644 --- a/app/src/main/res/values-en/strings.xml +++ b/app/src/main/res/values-en/strings.xml @@ -393,4 +393,11 @@ Reload Products This will download all products from the cloud and overwrite any unsaved local inventory changes. Are you sure you want to continue? Downloading product data... - \ No newline at end of file + Missing ORDC in prescription data. Please scan again or contact pharmacy staff. + Item [%1$s] has no stock or no assigned slot. Please verify configuration. + Item [%1$s] has insufficient stock. Required: %2$d, Available: %3$d + MATERIAL_CODE_EMPTY Slot %1$d product %2$s is missing material code. Please fix product master data first. + Pickup failed\nPlease contact the counter + Close(40) + Close(%1$d) + diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index d7ffc21..c67fa0c 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -395,4 +395,11 @@ 商品データを同期中... 同期中... 商品データの同期が完了しました - \ No newline at end of file + 処方データに ORDC がありません。再度スキャンするか薬局窓口へお問い合わせください。 + 商品 [%1$s] は在庫切れ、またはスロット未設定です。設定を確認してください。 + 商品 [%1$s] の在庫が不足しています。必要数: %2$d、在庫: %3$d + MATERIAL_CODE_EMPTY スロット %1$d の商品 %2$s に物料コードがありません。商品マスタを修正してください。 + 受け取り失敗\nカウンターへお問い合わせください + 閉じる(40) + 閉じる(%1$d) + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 470811c..3b6894e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -312,4 +312,11 @@ 資料上傳成功 資料上傳失敗 上傳後台並返回 - \ No newline at end of file + 領藥單缺少 ORDC,請重新掃碼或洽藥局窗口。 + 商品 [%1$s] 無庫存或未設定貨道,請確認。 + 商品 [%1$s] 庫存不足,需求:%2$d,可用:%3$d + MATERIAL_CODE_EMPTY 貨道 %1$d 商品 %2$s 缺少物料編號,請先修正商品主檔。 + 取物失敗\n請洽櫃台 + 關閉(40) + 關閉(%1$d) +