[FEAT] 一鍵補貨依貨道型式分流履帶/彈簧補貨上限

1. StarCloudAPI.saveProducts() 解析 B012 新欄位 spring_limit,設入 ProductStructure 並另存持久化 blob(履帶上限沿用 t060v11=track_limit,不動 products 表 schema 避免升 DB 版本洗掉貨道綁定)。
2. MyApp 新增 productSpringLimitBlob 之 get/set/saveProductSpringLimit 與離線重啟載入,供從 DB 重載商品(springLimit=-1)時 fallback。
3. ProductStructure 新增 springLimit 欄位與 getTrackLimit()/getSpringLimit();springLimit 缺時向 MyApp blob 取,再缺則退回履帶上限,維持舊行為不會把數量補成 0。
4. HardwareSetStructure 新增 isSpringSlot(slotNo),依 10 槽分組對齊後台 SPRING_SLOT_FLAGS,超出 1–60 視為履帶。
5. VmcSlotListActivity 一鍵補貨改依貨道型式取上限:彈簧用 getSpringLimit()、履帶用 getTrackLimit(),並於 log 標註(彈簧)/(履帶)。
6. build.gradle verPatch 5→6。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
sky121113 2026-06-17 13:22:27 +08:00
parent 258aa2f87b
commit 16420ae5a3
6 changed files with 95 additions and 4 deletions

View File

@ -10,7 +10,7 @@ plugins {
//
// =========================================================================
def verMinor = 2
def verPatch = 5
def verPatch = 6

View File

@ -124,6 +124,8 @@ public class MyApp extends Application {
// 商品名稱多語 mapB012 t060v01_i18nkey=商品IDvalue=底線代碼名稱 JSONObject
private JSONObject productNameI18nBlob = new JSONObject();
private JSONObject productSpecI18nBlob = new JSONObject();
// 商品彈簧補貨上限 mapB012 spring_limitkey=商品IDvalue=int履帶上限沿用 products slotUpperLimit
private JSONObject productSpringLimitBlob = new JSONObject();
private GreenInvoiceStructure greenInvoice;
private GreenpaySettingStructure greenpaySetting;
private GreenpayMerchantStructure greenpayMerchant;
@ -418,6 +420,11 @@ public class MyApp extends Application {
MyApp.getInstance().setProductSpecI18nBlob(memoDao.getOnlyOne("ProductSpecI18n").getData());
}
// 商品彈簧補貨上限 blobB012 spring_limit離線重啟時供一鍵補貨 fallback
if (memoDao.existOnlyOne("ProductSpringLimit")) {
MyApp.getInstance().setProductSpringLimitBlob(memoDao.getOnlyOne("ProductSpringLimit").getData());
}
if (memoDao.existOnlyOne(MyApp.getInstance().getCashSetStructure().getClass().getSimpleName())) {
JSONObject jsonObject = memoDao.getOnlyOne(MyApp.getInstance().getCashSetStructure().getClass().getSimpleName()).getData();
logs.debug("initialSystemSet:" + jsonObject.toString());
@ -560,6 +567,20 @@ public class MyApp extends Application {
}
}
// 持久化商品彈簧補貨上限 blob不動 products schema存於 MemoDao供離線重啟一鍵補貨 fallback
public static void saveProductSpringLimit(Context context) {
MemoDao memoDao = new MemoDao(context);
try {
memoDao.insertOnlyOne(new MemoStructure(
"ProductSpringLimit",
MyApp.getInstance().getProductSpringLimitBlob(),
new JSONObject()));
memoDao.mapUpdate();
} catch (Exception e) {
new Logs(MyApp.class).warning(e);
}
}
public static void updateLog(Context context) {
OneTimeWorkRequest oneTimeWorkRequest = new OneTimeWorkRequest.Builder(UploadLogOneTimeWorker.class)
.setInitialDelay(5, TimeUnit.SECONDS)
@ -1095,6 +1116,20 @@ public class MyApp extends Application {
return (obj == null) ? null : obj.toString();
}
public void setProductSpringLimitBlob(JSONObject blob) {
this.productSpringLimitBlob = (blob == null) ? new JSONObject() : blob;
}
public JSONObject getProductSpringLimitBlob() {
return productSpringLimitBlob;
}
// 取某商品的彈簧補貨上限blob 無此商品時回 -1 ProductStructure 退回履帶上限
public int getProductSpringLimit(String productId) {
if (productId == null || productSpringLimitBlob == null) return -1;
return productSpringLimitBlob.optInt(productId, -1);
}
public ReportAccessCodeStructure getReportAccessCodeStructure() {
return reportAccessCodeStructure;

View File

@ -1175,6 +1175,8 @@ public class StarCloudAPI {
JSONObject nameI18nBlob = new JSONObject();
// 商品規格多語 blob商品ID t060v03_i18n純文字含換行
JSONObject specI18nBlob = new JSONObject();
// 商品彈簧補貨上限 blob商品ID spring_limit履帶上限沿用 t060v11(=track_limit) products 故不另存
JSONObject springLimitBlob = new JSONObject();
for (int i = 0; i < products.length(); i++) {
JSONObject p = products.getJSONObject(i);
@ -1211,6 +1213,17 @@ public class StarCloudAPI {
try { specI18nBlob.put(pid, specI18n); } catch (JSONException ignore) {}
}
}
// 履帶/彈簧 補貨上限B012 spring_limit / track_limittrack 沿用 slotUpperLimit(t060v11)
// spring 另存物件欄位 + blob不動 products schema避免升 DB 版本洗掉貨道綁定
int springLimit = p.optInt("spring_limit", -1);
if (springLimit >= 0) {
product.setSpringLimit(springLimit);
String pid = p.optString("t060v00", "");
if (!pid.isEmpty()) {
try { springLimitBlob.put(pid, springLimit); } catch (JSONException ignore) {}
}
}
MyApp.getInstance().getProductList().add(product);
}
// 持久化商品多語 blob供離線重啟時 fallback
@ -1218,6 +1231,9 @@ public class StarCloudAPI {
MyApp.saveProductNameI18n(handlerMain.getContext());
MyApp.getInstance().setProductSpecI18nBlob(specI18nBlob);
MyApp.saveProductSpecI18n(handlerMain.getContext());
// 持久化彈簧補貨上限 blob供離線重啟時一鍵補貨 fallback
MyApp.getInstance().setProductSpringLimitBlob(springLimitBlob);
MyApp.saveProductSpringLimit(handlerMain.getContext());
// 將商品同步至資料庫
ProductsDao productsDao = new ProductsDao(handlerMain.getContext());

View File

@ -40,4 +40,18 @@ public class HardwareSetStructure {
public boolean isSpringSlot51_60() { return springSlot51_60; }
public void setSpringSlot51_60(boolean v) { springSlot51_60 = v; }
/**
* 依貨道號回傳是否為彈簧貨道對齊後台 SPRING_SLOT_FLAGS 10 槽分組
* 超出 160 範圍視為履帶false維持未知一律走履帶上限的安全預設
*/
public boolean isSpringSlot(int slotNo) {
if (slotNo >= 1 && slotNo <= 10) return springSlot1_10;
if (slotNo >= 11 && slotNo <= 20) return springSlot11_20;
if (slotNo >= 21 && slotNo <= 30) return springSlot21_30;
if (slotNo >= 31 && slotNo <= 40) return springSlot31_40;
if (slotNo >= 41 && slotNo <= 50) return springSlot41_50;
if (slotNo >= 51 && slotNo <= 60) return springSlot51_60;
return false;
}
}

View File

@ -212,6 +212,30 @@ public class ProductStructure {
}
}
// ===== 履帶/彈簧 補貨上限 =====
// 一鍵補貨依貨道型式取不同上限履帶用 trackLimit彈簧用 springLimit
// trackLimit = slotUpperLimitB012 t060v11本來就等於後台 track_limit沿用既有持久化
// springLimit = B012 spring_limit saveProducts 設入離線從 DB 重載商品時此欄為 -1
// 改向 MyApp 持久化 blob blob 也缺時退回履帶上限維持舊行為不會把數量補成 0
private int springLimit = -1;
public void setSpringLimit(int springLimit) {
this.springLimit = springLimit;
}
/** 履帶貨道補貨上限(= slotUpperLimit = 後台 track_limit。 */
public int getTrackLimit() {
return this.slotUpperLimit;
}
/** 彈簧貨道補貨上限。本物件欄位缺時向 MyApp 持久化 blob 取;再缺則退回履帶上限。 */
public int getSpringLimit() {
if (springLimit >= 0) return springLimit;
int fromBlob = com.unibuy.smartdevice.MyApp.getInstance().getProductSpringLimit(productID);
if (fromBlob >= 0) return fromBlob;
return this.slotUpperLimit;
}
private static boolean notBlank(String s) {
return s != null && !s.trim().isEmpty();
}

View File

@ -185,9 +185,11 @@ public class VmcSlotListActivity extends AppCompatActivityAbstract {
// 判斷有沒有設定商品
if (product != null && !product.getProductID().isEmpty() && !product.getProductID().equals("?")) {
int upperLimit = product.getSlotUpperLimit();
slot.setCount(upperLimit); // 設定數量 = 貨道上限
getLogs().info("補貨完成:貨道 " + slot.getSlot() + "" + upperLimit);
// 依貨道型式履帶/彈簧取對應補貨上限彈簧用 spring_limit履帶用 track_limit
boolean isSpring = MyApp.getInstance().getHardwareSetStructure().isSpringSlot(slot.getSlot());
int upperLimit = isSpring ? product.getSpringLimit() : product.getTrackLimit();
slot.setCount(upperLimit); // 設定數量 = 依型式取的貨道上限
getLogs().info("補貨完成:貨道 " + slot.getSlot() + (isSpring ? "(彈簧)" : "(履帶)") + "" + upperLimit);
recyclerVmcSlotListAdpter.notifyItemChanged(i); // 更新 UI
}
}