From 0201c32312f6478b2bde706607c8c6338e9e1d06 Mon Sep 17 00:00:00 2001
From: doum <doum>
Date: 星期三, 27 五月 2026 17:05:29 +0800
Subject: [PATCH] 新增智能电表、空调管理

---
 server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/YwElectricalBizServiceImpl.java |  373 ++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 351 insertions(+), 22 deletions(-)

diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/YwElectricalBizServiceImpl.java b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/YwElectricalBizServiceImpl.java
index c873faf..c9911dd 100644
--- a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/YwElectricalBizServiceImpl.java
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/YwElectricalBizServiceImpl.java
@@ -12,6 +12,7 @@
 import com.doumee.core.device.model.request.*;
 import com.doumee.core.device.model.response.ElectronicBaseResponse;
 import com.doumee.core.device.model.response.ElectronicDataResponse;
+import com.doumee.core.device.model.response.MeterDealResponse;
 import com.doumee.core.device.model.response.QueryDataInfoResponse;
 import com.doumee.core.device.model.response.QueryDataV2Response;
 import com.doumee.core.exception.BusinessException;
@@ -51,6 +52,11 @@
     public static final int ACTION_OPEN = 6;
     public static final int ACTION_RECHARGE = 7;
     public static final int ACTION_READ = 8;
+
+    private static final long FIRST_STATUS_QUERY_DELAY_MS = 30_000L;
+    private static final long STATUS_QUERY_MIN_INTERVAL_MS = 3_600_000L;
+    private static final int STATUS_QUERY_BATCH_SIZE = 50;
+    private static final int STATUS_QUERY_MAX_PENDING = 100;
 
     /** ele_read 鎶勭數琛ㄦ暟鎹搷浣滅被鍨嬶紙涓� queryData functionids=253 涓嶅悓锛� */
     private static final int ELE_READ_TYPE_METER = 3;
@@ -170,6 +176,7 @@
     }
 
     private String doSecurityReset(YwElectrical e, String paymentMode, int actionType, LoginUserInfo user) {
+        assertNoPendingAsyncAction(e.getId(), actionType);
         String oprId = newOprId();
         SecurityResetRequest req = new SecurityResetRequest();
         req.setOpr_id(oprId);
@@ -188,6 +195,7 @@
     }
 
     private String doEleControl(YwElectrical e, int type, int actionType, LoginUserInfo user) {
+        assertNoPendingAsyncAction(e.getId(), actionType);
         String oprId = newOprId();
         EleControlApiRequest req = new EleControlApiRequest();
         req.setOpr_id(oprId);
@@ -205,6 +213,7 @@
     }
 
     private String doOpenAccount(YwElectrical e, YwElectricalOperateDTO dto, LoginUserInfo user) {
+        assertNoPendingAsyncAction(e.getId(), ACTION_OPEN);
         String oprId = newOprId();
         OpenAccountRequest req = buildOpenAccountRequest(e, oprId, dto.getMoney(), dto.getRemark());
         String reqJson = JSON.toJSONString(Collections.singletonList(req));
@@ -216,6 +225,7 @@
         if (!Objects.equals(e.getAccountStatus(), Constants.ONE)) {
             throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "鐢佃〃鏈紑鎴凤紝璇峰厛寮�鎴�");
         }
+        assertNoPendingAsyncAction(e.getId(), ACTION_RECHARGE);
         String oprId = newOprId();
         OpenAccountRequest req = buildOpenAccountRequest(e, oprId, dto.getMoney(), dto.getRemark());
         String reqJson = JSON.toJSONString(Collections.singletonList(req));
@@ -228,6 +238,7 @@
     }
 
     private String doReadMeter(YwElectrical e, LoginUserInfo user) {
+        assertNoPendingAsyncAction(e.getId(), ACTION_READ);
         String oprId = newOprId();
         EleReadRequest req = new EleReadRequest();
         req.setOpr_id(oprId);
@@ -244,7 +255,7 @@
             throw new BusinessException(ResponseStatus.SERVER_ERROR.getCode(), msg);
         }
         boolean synced = syncMeterDataForElectrical(e);
-        refreshBalanceFromData(e);
+        refreshBalanceFromData(e, null, true);
         return synced ? "鎶勮〃鎴愬姛锛岀敤閲忎綑棰濆凡鏇存柊" : "鎶勮〃璇锋眰宸叉彁浜わ紝鏆傛棤鏂版妱琛ㄦ暟鎹紝璇风◢鍚庡埛鏂版煡鐪�";
     }
 
@@ -288,6 +299,21 @@
         }
         ywElectricalActionsMapper.insert(act);
         return isSuccess(resp) ? "鎻愪氦鎴愬姛锛岃绋嶅悗鍦ㄦ搷浣滆褰曟垨鍏呭�艰褰曚腑鏌ョ湅缁撴灉" : act.getResultMsg();
+    }
+
+    /** 鍚屼竴鐢佃〃銆佺浉鍚屾搷浣滅被鍨嬪瓨鍦ㄥ鐞嗕腑璁板綍鏃讹紝绂佹閲嶅鎻愪氦寮傛浠诲姟 */
+    private void assertNoPendingAsyncAction(Integer electricalId, int actionType) {
+        if (electricalId == null) {
+            return;
+        }
+        Long pending = ywElectricalActionsMapper.selectCount(new QueryWrapper<YwElectricalActions>().lambda()
+                .eq(YwElectricalActions::getElectricalId, electricalId)
+                .eq(YwElectricalActions::getActionType, actionType)
+                .eq(YwElectricalActions::getStatus, Constants.ZERO)
+                .eq(YwElectricalActions::getIsdeleted, Constants.ZERO));
+        if (pending != null && pending > 0) {
+            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "闇�瑕佺瓑寰呬笂涓�娆℃搷浣滅粨鏋滄墽琛岀粨鏉�");
+        }
     }
 
     private void saveLog(YwElectrical e, String apiName, String reqJson, ElectronicBaseResponse resp, LoginUserInfo user) {
@@ -336,26 +362,32 @@
     }
 
     private void applyNotifyItem(JSONObject item) {
-        if (item == null) return;
-        String oprId = item.getString("opr_id");
-        if (StringUtils.isBlank(oprId)) return;
-        YwElectricalActions act = ywElectricalActionsMapper.selectOne(new QueryWrapper<YwElectricalActions>().lambda()
-                .eq(YwElectricalActions::getOprId, oprId)
-                .eq(YwElectricalActions::getIsdeleted, Constants.ZERO)
-                .orderByDesc(YwElectricalActions::getCreateDate)
-                .last("limit 1"));
-        if (act == null) {
-            log.info("electricalNotify no action for opr_id={}", oprId);
+        if (item == null) {
             return;
         }
-        ElectronicNotifyStatus ns = ElectronicNotifyStatus.fromCode(item.getString("status"));
+        String oprId = item.getString("opr_id");
+        String status = item.getString("status");
         String errMsg = item.get("error_msg") != null ? String.valueOf(item.get("error_msg")) : null;
+        applyActionStatusItem(oprId, status, errMsg, item.toJSONString(), true);
+    }
+
+    private void applyActionStatusItem(String oprId, String platformStatus, String errMsg, String responseBody,
+                                       boolean fromNotify) {
+        if (StringUtils.isBlank(oprId)) {
+            return;
+        }
+        YwElectricalActions act = findActionByOprId(oprId);
+        if (act == null) {
+            log.info("electrical action not found for opr_id={}", oprId);
+            return;
+        }
+        ElectronicNotifyStatus ns = ElectronicNotifyStatus.fromCode(platformStatus);
         String resultMsg = ns.getLabel() + (StringUtils.isNotBlank(errMsg) ? "锛�" + errMsg : "");
 
         YwElectricalActions upd = new YwElectricalActions();
         upd.setId(act.getId());
         upd.setEditDate(new Date());
-        upd.setResponseBody(item.toJSONString());
+        upd.setResponseBody(responseBody);
         upd.setResultMsg(resultMsg);
         if (ns.isTerminalSuccess()) {
             upd.setStatus(Constants.ONE);
@@ -367,8 +399,12 @@
         ywElectricalActionsMapper.updateById(upd);
 
         YwElectrical e = ywElectricalMapper.selectById(act.getElectricalId());
-        if (e == null) return;
-        saveNotifyLog(e, item, ns);
+        if (e == null) {
+            return;
+        }
+        if (fromNotify) {
+            saveNotifyLog(e, JSON.parseObject(responseBody), ns);
+        }
         if (ns.isTerminalSuccess()) {
             applyNotifySideEffect(e, act.getActionType());
             if (Objects.equals(act.getActionType(), ACTION_RECHARGE)) {
@@ -377,6 +413,183 @@
         } else if (ns.isTerminalFail() && Objects.equals(act.getActionType(), ACTION_RECHARGE)) {
             updateChargeByNotify(oprId, Constants.TWO, resultMsg);
         }
+    }
+
+    private YwElectricalActions findActionByOprId(String oprId) {
+        return ywElectricalActionsMapper.selectOne(new QueryWrapper<YwElectricalActions>().lambda()
+                .eq(YwElectricalActions::getOprId, oprId)
+                .eq(YwElectricalActions::getIsdeleted, Constants.ZERO)
+                .orderByDesc(YwElectricalActions::getCreateDate)
+                .last("limit 1"));
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public String syncAsyncActionStatus(String oprId) {
+        if (StringUtils.isBlank(oprId)) {
+            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "缂哄皯浠诲姟 ID");
+        }
+        String trimmed = oprId.trim();
+        if (findActionByOprId(trimmed) == null) {
+            throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "鏈壘鍒板搴旀搷浣滆褰�");
+        }
+        ElectronicBaseResponse resp = ElectronicToolUtil.requestStatus(trimmed);
+        return handleStatusQueryResponse(resp, trimmed);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public String syncChargeStatusById(Integer chargeId) {
+        if (chargeId == null) {
+            throw new BusinessException(ResponseStatus.BAD_REQUEST);
+        }
+        YwElectricalCharge charge = ywElectricalChargeMapper.selectById(chargeId);
+        if (charge == null || !Objects.equals(charge.getIsdeleted(), Constants.ZERO)) {
+            throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "鍏呭�艰褰曚笉瀛樺湪");
+        }
+        if (!Objects.equals(charge.getStatus(), Constants.ZERO)) {
+            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "浠呭厖鍊间腑璁板綍鍙悓姝�");
+        }
+        if (!Objects.equals(charge.getType(), Constants.ZERO)) {
+            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "浠呯數琛ㄥ厖鍊艰褰曞彲鍚屾");
+        }
+        return syncAsyncActionStatus(charge.getOprId());
+    }
+
+    @Override
+    public void syncPendingAsyncActionsScheduled() {
+        try {
+            Date minCreateTime = new Date(System.currentTimeMillis() - FIRST_STATUS_QUERY_DELAY_MS);
+            List<YwElectricalActions> pending = ywElectricalActionsMapper.selectList(
+                    new QueryWrapper<YwElectricalActions>().lambda()
+                            .eq(YwElectricalActions::getStatus, Constants.ZERO)
+                            .eq(YwElectricalActions::getIsdeleted, Constants.ZERO)
+                            .isNotNull(YwElectricalActions::getOprId)
+                            .le(YwElectricalActions::getCreateDate, minCreateTime)
+                            .orderByAsc(YwElectricalActions::getCreateDate)
+                            .last("limit " + STATUS_QUERY_MAX_PENDING));
+            if (CollectionUtils.isEmpty(pending)) {
+                return;
+            }
+            long nowMs = System.currentTimeMillis();
+            List<String> oprIds = pending.stream()
+                    .filter(act -> shouldPollAction(act, nowMs))
+                    .map(YwElectricalActions::getOprId)
+                    .filter(StringUtils::isNotBlank)
+                    .distinct()
+                    .collect(Collectors.toList());
+            if (oprIds.isEmpty()) {
+                return;
+            }
+            int updated = 0;
+            for (int i = 0; i < oprIds.size(); i += STATUS_QUERY_BATCH_SIZE) {
+                List<String> batch = oprIds.subList(i, Math.min(i + STATUS_QUERY_BATCH_SIZE, oprIds.size()));
+                ElectronicBaseResponse resp = ElectronicToolUtil.requestStatusByOprIds(batch);
+                updated += applyStatusQueryBatch(resp);
+            }
+            log.info("syncPendingAsyncActionsScheduled queried={}, updated={}", oprIds.size(), updated);
+        } catch (Exception e) {
+            log.warn("syncPendingAsyncActionsScheduled failed", e);
+        }
+    }
+
+    private int applyStatusQueryBatch(ElectronicBaseResponse resp) {
+        if (resp == null || !"SUCCESS".equalsIgnoreCase(resp.getStatus())) {
+            return 0;
+        }
+        List<MeterDealResponse> items = extractMeterDealList(resp);
+        if (CollectionUtils.isEmpty(items)) {
+            return 0;
+        }
+        int updated = 0;
+        for (MeterDealResponse item : items) {
+            if (item == null || StringUtils.isBlank(item.getOpr_id())) {
+                continue;
+            }
+            YwElectricalActions before = findActionByOprId(item.getOpr_id());
+            if (before == null || !Objects.equals(before.getStatus(), Constants.ZERO)) {
+                continue;
+            }
+            applyActionStatusItem(item.getOpr_id(), item.getStatus(), item.getError_msg(),
+                    JSON.toJSONString(item), false);
+            YwElectricalActions after = findActionByOprId(item.getOpr_id());
+            if (after != null && !Objects.equals(before.getStatus(), after.getStatus())) {
+                updated++;
+            }
+        }
+        return updated;
+    }
+
+    private String handleStatusQueryResponse(ElectronicBaseResponse resp, String oprId) {
+        if (resp == null) {
+            return "骞冲彴鏃犲搷搴旓紝璇风◢鍚庨噸璇�";
+        }
+        if (!"SUCCESS".equalsIgnoreCase(resp.getStatus())) {
+            return "鏌ヨ澶辫触锛�" + StringUtils.defaultIfBlank(resp.getError_msg(), resp.getStatus());
+        }
+        List<MeterDealResponse> items = extractMeterDealList(resp);
+        MeterDealResponse item = items.stream()
+                .filter(i -> i != null && oprId.equals(i.getOpr_id()))
+                .findFirst()
+                .orElse(CollectionUtils.isEmpty(items) ? null : items.get(0));
+        if (item == null) {
+            return "鏈煡璇㈠埌浠诲姟缁撴灉锛岃绋嶅悗閲嶈瘯";
+        }
+        applyActionStatusItem(oprId, item.getStatus(), item.getError_msg(), JSON.toJSONString(item), false);
+
+        YwElectricalActions act = findActionByOprId(oprId);
+        if (act == null) {
+            return "鏈壘鍒板搴旀搷浣滆褰�";
+        }
+        if (Objects.equals(act.getStatus(), Constants.ONE)) {
+            return Objects.equals(act.getActionType(), ACTION_RECHARGE) ? "宸插悓姝ヤ负鍏呭�兼垚鍔�" : "鎿嶄綔宸叉垚鍔�";
+        }
+        if (Objects.equals(act.getStatus(), Constants.TWO)) {
+            return Objects.equals(act.getActionType(), ACTION_RECHARGE)
+                    ? "宸插悓姝ヤ负鍏呭�煎け璐ワ細" + StringUtils.defaultString(act.getResultMsg())
+                    : "鎿嶄綔宸插け璐ワ細" + StringUtils.defaultString(act.getResultMsg());
+        }
+        if (ElectronicToolUtil.isAsyncStatusFinal(item.getStatus())) {
+            return "骞冲彴鐘舵�侊細" + item.getStatus();
+        }
+        return "浠诲姟澶勭悊涓紝璇风◢鍚庨噸璇�";
+    }
+
+    @SuppressWarnings("unchecked")
+    private List<MeterDealResponse> extractMeterDealList(ElectronicBaseResponse resp) {
+        Object content = resp.getResponse_content();
+        if (content == null) {
+            return Collections.emptyList();
+        }
+        if (content instanceof List) {
+            List<?> list = (List<?>) content;
+            List<MeterDealResponse> result = new ArrayList<>();
+            for (Object o : list) {
+                if (o instanceof MeterDealResponse) {
+                    result.add((MeterDealResponse) o);
+                } else {
+                    result.add(JSON.parseObject(JSON.toJSONString(o), MeterDealResponse.class));
+                }
+            }
+            return result;
+        }
+        return JSON.parseArray(JSON.toJSONString(content), MeterDealResponse.class);
+    }
+
+    private boolean shouldPollAction(YwElectricalActions act, long nowMs) {
+        Date create = act.getCreateDate();
+        if (create == null || StringUtils.isBlank(act.getOprId())) {
+            return false;
+        }
+        long createMs = create.getTime();
+        if (nowMs - createMs < FIRST_STATUS_QUERY_DELAY_MS) {
+            return false;
+        }
+        long editMs = act.getEditDate() != null ? act.getEditDate().getTime() : createMs;
+        if (editMs - createMs < 5_000L) {
+            return true;
+        }
+        return nowMs - editMs >= STATUS_QUERY_MIN_INTERVAL_MS;
     }
 
     private void saveChargeRecord(YwElectrical e, String oprId, YwElectricalOperateDTO dto, LoginUserInfo user) {
@@ -400,6 +613,12 @@
         charge.setStatusInfo("鍏呭�间腑");
         charge.setBanlance(e.getBalance());
         charge.setRoomNames(e.getRoomNames());
+        if (dto.getCustomerId() != null) {
+            charge.setCustomerId(dto.getCustomerId());
+        }
+        if (StringUtils.isNotBlank(e.getAddress()) || StringUtils.isNotBlank(e.getName())) {
+            charge.setDeviceInfo(StringUtils.defaultString(e.getAddress()) + " " + StringUtils.defaultString(e.getName()));
+        }
         if (StringUtils.isNotBlank(e.getParamId())) {
             try {
                 charge.setParamId(Integer.parseInt(e.getParamId()));
@@ -410,13 +629,29 @@
     }
 
     private void updateChargeByNotify(String oprId, int status, String statusInfo) {
-        ywElectricalChargeMapper.update(null, new UpdateWrapper<YwElectricalCharge>().lambda()
+        YwElectricalCharge charge = ywElectricalChargeMapper.selectOne(new QueryWrapper<YwElectricalCharge>().lambda()
+                .eq(YwElectricalCharge::getOprId, oprId)
+                .eq(YwElectricalCharge::getIsdeleted, Constants.ZERO)
+                .last("limit 1"));
+        BigDecimal balanceAfter = null;
+        if (charge != null && status == Constants.ONE) {
+            balanceAfter = calcBalanceAfterRecharge(charge);
+            if (charge.getObjId() != null) {
+                updateElectricalBalance(charge.getObjId(), balanceAfter);
+            }
+        }
+        UpdateWrapper<YwElectricalCharge> uw = new UpdateWrapper<>();
+        uw.lambda()
                 .set(YwElectricalCharge::getStatus, status)
                 .set(YwElectricalCharge::getStatusTime, new Date())
                 .set(YwElectricalCharge::getStatusInfo, statusInfo)
                 .set(YwElectricalCharge::getEditDate, new Date())
                 .eq(YwElectricalCharge::getOprId, oprId)
-                .eq(YwElectricalCharge::getIsdeleted, Constants.ZERO));
+                .eq(YwElectricalCharge::getIsdeleted, Constants.ZERO);
+        if (balanceAfter != null) {
+            uw.lambda().set(YwElectricalCharge::getBalanceAfter, balanceAfter);
+        }
+        ywElectricalChargeMapper.update(null, uw);
     }
 
     private void saveNotifyLog(YwElectrical e, JSONObject item, ElectronicNotifyStatus ns) {
@@ -454,34 +689,128 @@
                 ywElectricalMapper.update(null, uw);
                 break;
             case ACTION_RECHARGE:
+                // 鍏呭�兼垚鍔熷悗浣欓鐢� updateChargeByNotify 鎸夈�屽厖鍊煎墠+鍏呭�奸噾棰濄�嶇疮璁★紝寰呭畾鏃舵妱琛ㄥ悗鍐嶅垏鍥炴妱琛ㄤ綑棰�
+                break;
             case ACTION_READ:
                 syncMeterDataForElectrical(e);
-                refreshBalanceFromData(e);
+                refreshBalanceFromData(e, null, true);
                 break;
             default:
                 break;
         }
     }
 
+    /** 鍏呭�煎悗绱浣欓 = 鍏呭�煎墠浣欓 + 鍏呭�奸噾棰� */
+    private BigDecimal calcBalanceAfterRecharge(YwElectricalCharge charge) {
+        BigDecimal before = charge.getBanlance() != null ? charge.getBanlance() : BigDecimal.ZERO;
+        BigDecimal money = charge.getMoney() != null ? charge.getMoney() : BigDecimal.ZERO;
+        return before.add(money);
+    }
+
+    private void updateElectricalBalance(Integer electricalId, BigDecimal balance) {
+        if (electricalId == null || balance == null) {
+            return;
+        }
+        UpdateWrapper<YwElectrical> uw = new UpdateWrapper<>();
+        uw.lambda()
+                .eq(YwElectrical::getId, electricalId)
+                .set(YwElectrical::getBalance, balance)
+                .set(YwElectrical::getBalanceTime, new Date())
+                .set(YwElectrical::getEditDate, new Date());
+        ywElectricalMapper.update(null, uw);
+    }
+
+    private YwElectricalCharge findLastSuccessfulRecharge(Integer electricalId) {
+        if (electricalId == null) {
+            return null;
+        }
+        return ywElectricalChargeMapper.selectOne(new QueryWrapper<YwElectricalCharge>().lambda()
+                .eq(YwElectricalCharge::getObjId, electricalId)
+                .eq(YwElectricalCharge::getType, Constants.ZERO)
+                .eq(YwElectricalCharge::getStatus, Constants.ONE)
+                .eq(YwElectricalCharge::getIsdeleted, Constants.ZERO)
+                .orderByDesc(YwElectricalCharge::getStatusTime)
+                .orderByDesc(YwElectricalCharge::getId)
+                .last("limit 1"));
+    }
+
+    private Date parseDataTime(YwElectricalData data) {
+        if (data == null) {
+            return null;
+        }
+        if (StringUtils.isNotBlank(data.getAddTime())) {
+            try {
+                return new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(data.getAddTime().trim());
+            } catch (Exception ignored) {
+            }
+        }
+        return data.getCreateDate();
+    }
+
+    /**
+     * 鏈�杩戜竴娆″厖鍊兼垚鍔熷悗锛岃嫢鎶勮〃鏃堕棿浠嶆棭浜庡厖鍊兼垚鍔熸椂闂达紝鍒欐殏涓嶄互鎶勮〃浣欓瑕嗙洊绱浣欓銆�
+     */
+    private boolean shouldUseMeterBalance(Integer electricalId, YwElectricalData data) {
+        YwElectricalCharge lastRecharge = findLastSuccessfulRecharge(electricalId);
+        if (lastRecharge == null || lastRecharge.getStatusTime() == null) {
+            return true;
+        }
+        Date dataTime = parseDataTime(data);
+        if (dataTime == null) {
+            return true;
+        }
+        return !dataTime.before(lastRecharge.getStatusTime());
+    }
+
     private void refreshBalanceFromData(YwElectrical e) {
-        YwElectricalData data = findLatestData(e.getId(), e.getAddress());
-        if (data == null) return;
+        refreshBalanceFromData(e, null, false);
+    }
+
+    private void refreshBalanceFromData(YwElectrical e, YwElectricalData data, boolean forceFromMeter) {
+        if (e == null) {
+            return;
+        }
+        if (data == null) {
+            data = findLatestData(e.getId(), e.getAddress());
+        }
+        if (data == null) {
+            return;
+        }
         UpdateWrapper<YwElectrical> uw = new UpdateWrapper<>();
         uw.lambda().eq(YwElectrical::getId, e.getId());
         if (StringUtils.isNotBlank(data.getZhygzdl())) {
             uw.lambda().set(YwElectrical::getBalanceBattery, data.getZhygzdl());
         }
-        if (StringUtils.isNotBlank(data.getYe())) {
+        boolean useMeterBalance = forceFromMeter || shouldUseMeterBalance(e.getId(), data);
+        if (useMeterBalance && StringUtils.isNotBlank(data.getYe())) {
             try {
                 uw.lambda().set(YwElectrical::getBalance, new BigDecimal(data.getYe()));
             } catch (Exception ignored) {
             }
         }
-        uw.lambda().set(YwElectrical::getBalanceTime, new Date());
+        if (isPurchaseCountPositive(data.getCountnum())) {
+            uw.lambda().set(YwElectrical::getAccountStatus, Constants.ONE);
+        }
+        if (useMeterBalance) {
+            Date dataTime = parseDataTime(data);
+            uw.lambda().set(YwElectrical::getBalanceTime, dataTime != null ? dataTime : new Date());
+        }
         uw.lambda().set(YwElectrical::getEditDate, new Date());
         ywElectricalMapper.update(null, uw);
     }
 
+    /** 璐拱娆℃暟澶т簬 0 瑙嗕负宸插紑鎴� */
+    private static boolean isPurchaseCountPositive(String purchaseCount) {
+        if (StringUtils.isBlank(purchaseCount)) {
+            return false;
+        }
+        try {
+            return new BigDecimal(purchaseCount.trim()).compareTo(BigDecimal.ZERO) > 0;
+        } catch (NumberFormatException e) {
+            return false;
+        }
+    }
+
     private YwElectricalData findLatestData(Integer electricalId, String address) {
         QueryWrapper<YwElectricalData> q = new QueryWrapper<>();
         q.lambda().eq(YwElectricalData::getIsdeleted, Constants.ZERO)

--
Gitblit v1.9.3