From e50954f0708ecbbc672352102ae3b24279d40cc1 Mon Sep 17 00:00:00 2001
From: MrShi <1878285526@qq.com>
Date: 星期四, 16 四月 2026 20:12:50 +0800
Subject: [PATCH] Merge branch 'master' of http://139.186.142.91:10010/r/productDev/gtzxinglijicun

---
 server/services/src/main/java/com/doumee/service/business/impl/OrdersServiceImpl.java |  827 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 816 insertions(+), 11 deletions(-)

diff --git a/server/services/src/main/java/com/doumee/service/business/impl/OrdersServiceImpl.java b/server/services/src/main/java/com/doumee/service/business/impl/OrdersServiceImpl.java
index 566ad1d..5224b0f 100644
--- a/server/services/src/main/java/com/doumee/service/business/impl/OrdersServiceImpl.java
+++ b/server/services/src/main/java/com/doumee/service/business/impl/OrdersServiceImpl.java
@@ -20,9 +20,11 @@
 import com.doumee.dao.business.*;
 import com.doumee.dao.business.model.*;
 import com.doumee.dao.system.SystemUserMapper;
+import com.doumee.dao.system.model.SystemDictData;
 import com.doumee.dao.system.model.SystemUser;
 import com.doumee.dao.dto.CalculateLocalPriceDTO;
 import com.doumee.dao.dto.CalculateRemotePriceDTO;
+import com.doumee.dao.dto.CommentOrderDTO;
 import com.doumee.dao.dto.CreateOrderDTO;
 import com.doumee.dao.dto.DispatchDTO;
 import com.doumee.dao.dto.MyOrderDTO;
@@ -30,6 +32,7 @@
 import com.doumee.dao.vo.*;
 import com.doumee.service.business.OrderLogService;
 import com.doumee.service.business.OrdersService;
+import com.doumee.service.business.AreasService;
 import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest;
 import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
 import com.github.binarywang.wxpay.exception.WxPayException;
@@ -92,6 +95,15 @@
     private OrdersRefundMapper ordersRefundMapper;
 
     @Autowired
+    private OtherOrdersMapper otherOrdersMapper;
+
+    @Autowired
+    private OrderCommentMapper orderCommentMapper;
+
+    @Autowired
+    private RevenueMapper revenueMapper;
+
+    @Autowired
     private WxMiniUtilService wxMiniUtilService;
 
     @Autowired
@@ -107,6 +119,9 @@
 
     @Autowired
     private OperationConfigBiz operationConfigBiz;
+
+    @Autowired
+    private AreasService areasService;
 
     @Override
     public Integer create(Orders orders) {
@@ -1135,8 +1150,8 @@
 
     private String getOrdersPrefix() {
         try {
-            return systemDictDataBiz.queryByCode(Constants.SYSTEM, Constants.RESOURCE_PATH).getCode()
-                    + systemDictDataBiz.queryByCode(Constants.SYSTEM, Constants.ORDERS_FILES).getCode();
+            return systemDictDataBiz.queryByCode(Constants.OSS, Constants.RESOURCE_PATH).getCode()
+                    + systemDictDataBiz.queryByCode(Constants.OSS, Constants.ORDERS_FILES).getCode();
         } catch (Exception e) {
             return "";
         }
@@ -1307,6 +1322,102 @@
                 vo.setDetailList(buildDetailList(details));
 
                 // 閫炬湡淇℃伅锛堜粎寰呭彇浠剁姸鎬佽绠楋級
+                if (Integer.valueOf(Constants.OrderStatus.arrived.getStatus()).equals(o.getStatus())) {
+                    OverdueFeeVO overdueInfo = calculateOverdueFeeInternal(o, details);
+                    vo.setOverdue(overdueInfo.getOverdue());
+                    vo.setOverdueDays(overdueInfo.getOverdueDays());
+                    vo.setOverdueFee(overdueInfo.getOverdueFee());
+                }
+                voList.add(vo);
+            }
+        }
+
+        IPage<MyOrderVO> vPage = new Page<>(pageWrap.getPage(), pageWrap.getCapacity());
+        PageData<MyOrderVO> pageData = PageData.from(vPage);
+        pageData.setRecords(voList);
+        pageData.setTotal(orderPage.getTotal());
+        pageData.setPage(orderPage.getCurrent());
+        pageData.setCapacity(orderPage.getSize());
+        return pageData;
+    }
+
+    @Override
+    public PageData<MyOrderVO> findShopOrderPage(PageWrap<MyOrderDTO> pageWrap, Integer shopId) {
+        MyOrderDTO model = pageWrap.getModel();
+        Integer status = model != null ? model.getStatus() : null;
+        Integer combinedStatus = model != null ? model.getCombinedStatus() : null;
+
+        // 瑙f瀽鍚堝苟鐘舵�佷负鍏蜂綋鐘舵�佸垪琛�
+        List<Integer> statusList = null;
+        if (combinedStatus != null) {
+            Constants.OrderCombinedStatus combined = Constants.OrderCombinedStatus.getByKey(combinedStatus);
+            if (combined != null) {
+                statusList = new ArrayList<>();
+                for (int s : combined.getStatuses()) {
+                    statusList.add(s);
+                }
+            }
+        }
+
+        IPage<Orders> p = new Page<>(pageWrap.getPage(), pageWrap.getCapacity());
+        MPJLambdaWrapper<Orders> wrapper = new MPJLambdaWrapper<Orders>()
+                .selectAll(Orders.class)
+                .select("s1.name", Orders::getDepositShopName)
+                .select("s1.link_name", Orders::getDepositShopLinkName)
+                .select("s1.link_phone", Orders::getDepositShopLinkPhone)
+                .select("s2.name", Orders::getTakeShopName)
+                .select("s2.address", Orders::getTakeShopAddress)
+                .leftJoin("shop_info s1 on s1.id = t.DEPOSIT_SHOP_ID")
+                .leftJoin("shop_info s2 on s2.id = t.TAKE_SHOP_ID")
+                .eq(Orders::getPayStatus, Constants.ONE)
+                .and(w -> w.eq(Orders::getDepositShopId, shopId).or().eq(Orders::getTakeShopId, shopId))
+                .eq(status != null, Orders::getStatus, status)
+                .in(statusList != null, Orders::getStatus, statusList)
+                .orderByDesc(Orders::getCreateTime);
+
+        IPage<Orders> orderPage = ordersMapper.selectJoinPage(p, Orders.class, wrapper);
+        List<MyOrderVO> voList = new ArrayList<>();
+        if (orderPage != null && orderPage.getRecords() != null) {
+            for (Orders o : orderPage.getRecords()) {
+                MyOrderVO vo = new MyOrderVO();
+                vo.setId(o.getId());
+                vo.setCode(o.getCode());
+                vo.setType(o.getType());
+                vo.setStatus(o.getStatus());
+                vo.setCreateTime(o.getCreateTime());
+                vo.setExpectedTakeTime(o.getExpectedTakeTime());
+
+                vo.setDepositShopName(o.getDepositShopName());
+                vo.setDepositShopLinkName(o.getDepositShopLinkName());
+                vo.setDepositShopPhone(o.getDepositShopLinkPhone());
+
+                // 闂ㄥ簵瑙掕壊锛氬瓨浠堕棬搴�=1锛屽彇浠堕棬搴�=2
+                if (Constants.equalsInteger(o.getDepositShopId(), shopId)) {
+                    vo.setShopRole(Constants.ONE);
+                } else if (Constants.equalsInteger(o.getTakeShopId(), shopId)) {
+                    vo.setShopRole(Constants.TWO);
+                }
+
+                if (o.getTakeShopId() != null) {
+                    vo.setTakeShopName(o.getTakeShopName());
+                    vo.setTakeShopAddress(o.getTakeShopAddress());
+                } else {
+                    vo.setTakeLocation(o.getTakeLocation());
+                    vo.setTakeLocationRemark(o.getTakeLocationRemark());
+                }
+
+                vo.setTakeUser(o.getTakeUser());
+                vo.setTakePhone(o.getTakePhone());
+                vo.setDeclaredFee(o.getDeclaredFee());
+                vo.setEstimatedAmount(o.getEstimatedAmount());
+
+                List<OrdersDetail> details = ordersDetailMapper.selectList(
+                        new QueryWrapper<OrdersDetail>().lambda()
+                                .eq(OrdersDetail::getOrderId, o.getId())
+                                .eq(OrdersDetail::getDeleted, Constants.ZERO));
+
+                vo.setDetailList(buildDetailList(details));
+
                 if (Integer.valueOf(Constants.OrderStatus.arrived.getStatus()).equals(o.getStatus())) {
                     OverdueFeeVO overdueInfo = calculateOverdueFeeInternal(o, details);
                     vo.setOverdue(overdueInfo.getOverdue());
@@ -1607,6 +1718,443 @@
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
+    public PayResponse payOverdueFee(Integer orderId, Integer memberId) {
+        // 1. 鏌ヨ瀵勫瓨璁㈠崟
+        Orders order = ordersMapper.selectOne(new QueryWrapper<Orders>().lambda()
+                .eq(Orders::getId, orderId)
+                .eq(Orders::getMemberId, memberId)
+                .eq(Orders::getDeleted, Constants.ZERO));
+        if (order == null) {
+            throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "璁㈠崟涓嶅瓨鍦�");
+        }
+        // 2. 鏍¢獙鐘舵�侊細寰呭彇浠�(5) + 閫炬湡(1)
+        if (!Constants.equalsInteger(order.getStatus(), Constants.OrderStatus.arrived.getStatus())) {
+            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "褰撳墠璁㈠崟鐘舵�佷笉鏀寔閫炬湡鏀粯");
+        }
+        if (!Constants.equalsInteger(order.getOverdueStatus(), Constants.ONE)) {
+            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "璇ヨ鍗曚笉瀛樺湪閫炬湡璐圭敤");
+        }
+        if (order.getOverdueAmount() == null || order.getOverdueAmount() <= 0) {
+            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "閫炬湡璐圭敤寮傚父锛屾棤娉曞彂璧锋敮浠�");
+        }
+        // 3. 鏌ヨ浼氬憳
+        Member member = memberMapper.selectById(memberId);
+        if (member == null || StringUtils.isBlank(member.getOpenid())) {
+            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "鐢ㄦ埛淇℃伅寮傚父锛屾棤娉曞彂璧锋敮浠�");
+        }
+        // 4. 鍒涘缓閫炬湡璐圭敤璁㈠崟
+        String outTradeNo = generateOrderTradeNo();
+        Date now = new Date();
+        OtherOrders otherOrders = new OtherOrders();
+        otherOrders.setType(Constants.TWO); // 2=閫炬湡璐圭敤璁㈠崟
+        otherOrders.setMemberId(memberId);
+        otherOrders.setOrderId(orderId);
+        otherOrders.setPayAccount(order.getOverdueAmount());
+        otherOrders.setPayStatus(Constants.ZERO);
+        otherOrders.setCode("OD" + new java.text.SimpleDateFormat("yyyyMMddHHmmss").format(now) + orderId);
+        otherOrders.setOutTradeNo(outTradeNo);
+        otherOrders.setDeleted(Constants.ZERO);
+        otherOrders.setCreateTime(now);
+        otherOrdersMapper.insert(otherOrders);
+
+        // 5. 鍞よ捣寰俊鏀粯
+        return wxPayForOtherOrder(otherOrders, member.getOpenid(), Constants.OrdersAttach.OVERDUE_FEE);
+    }
+
+    @Override
+    @Transactional(rollbackFor = {Exception.class, BusinessException.class})
+    public void handleOverdueFeePayNotify(String outTradeNo, String wxTradeNo) {
+        // 1. 鏌ユ壘閫炬湡璐圭敤璁㈠崟
+        OtherOrders otherOrders = otherOrdersMapper.selectOne(new QueryWrapper<OtherOrders>().lambda()
+                .eq(OtherOrders::getOutTradeNo, outTradeNo)
+                .eq(OtherOrders::getDeleted, Constants.ZERO)
+                .last("limit 1"));
+        if (otherOrders == null) {
+            throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "閫炬湡璐圭敤璁㈠崟涓嶅瓨鍦�: " + outTradeNo);
+        }
+        // 2. 骞傜瓑锛氬凡鏀粯鍒欒烦杩�
+        if (Constants.equalsInteger(otherOrders.getPayStatus(), Constants.ONE)) {
+            return;
+        }
+        Date now = new Date();
+        // 3. 鏇存柊閫炬湡璐圭敤璁㈠崟鐘舵��
+        otherOrders.setPayStatus(Constants.ONE);
+        otherOrders.setPayTime(now);
+        otherOrders.setWxExternalNo(wxTradeNo);
+        otherOrders.setUpdateTime(now);
+        otherOrdersMapper.updateById(otherOrders);
+
+        // 4. 鏇存柊瀵勫瓨璁㈠崟閫炬湡鐘舵�佷负宸叉敮浠�(2)锛屾洿鏂版�婚噾棰濓紝閲嶇畻涓夋柟鏀剁泭
+        if (otherOrders.getOrderId() != null) {
+            Orders order = ordersMapper.selectById(otherOrders.getOrderId());
+            if (order != null) {
+                order.setOverdueStatus(Constants.TWO); // 2=宸叉敮浠�
+                // 鎬婚噾棰� = 鍘熼噾棰� + 閫炬湡璐圭敤
+                Long overdueFee = otherOrders.getPayAccount() != null ? otherOrders.getPayAccount() : 0L;
+                long newTotal = (order.getTotalAmount() != null ? order.getTotalAmount() : 0L) + overdueFee;
+                order.setTotalAmount(newTotal);
+                order.setUpdateTime(now);
+                ordersMapper.updateById(order);
+                // 閲嶇畻涓夋柟鏀剁泭
+                calculateAndSaveOrderFees(order.getId());
+            }
+        }
+    }
+
+    @Override
+    public void deleteMyOrder(Integer orderId, Integer memberId) {
+        Orders order = ordersMapper.selectById(orderId);
+        if (order == null || !Constants.equalsInteger(order.getDeleted(), Constants.ZERO)) {
+            throw new BusinessException(ResponseStatus.DATA_EMPTY);
+        }
+        if (!Constants.equalsInteger(order.getMemberId(), memberId)) {
+            throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "鏃犳潈鎿嶄綔姝よ鍗�");
+        }
+        // 浠呭凡瀹屾垚(7)銆佸凡鍙栨秷(99)銆佸凡閫�娆�(96)鍙垹闄�
+        int status = Constants.formatIntegerNum(order.getStatus());
+        if (status != Constants.OrderStatus.finished.getStatus()
+                && status != Constants.OrderStatus.cancelled.getStatus()
+                && status != Constants.OrderStatus.closed.getStatus()) {
+            throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "褰撳墠璁㈠崟鐘舵�佷笉鍙垹闄�");
+        }
+        ordersMapper.update(new UpdateWrapper<Orders>().lambda()
+                .set(Orders::getDeleted, Constants.ONE)
+                .set(Orders::getUpdateTime, new Date())
+                .eq(Orders::getId, orderId));
+    }
+
+    @Override
+    @Transactional(rollbackFor = {Exception.class, BusinessException.class})
+    public PayResponse payShopDeposit(Integer shopId) {
+        // 1. 鏌ヨ闂ㄥ簵淇℃伅
+        ShopInfo shopInfo = shopInfoMapper.selectById(shopId);
+        if (shopInfo == null) {
+            throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "闂ㄥ簵涓嶅瓨鍦�");
+        }
+        // 2. 鏍¢獙鐘舵�侊細瀹℃壒閫氳繃(1)鎵嶈兘鏀粯鎶奸噾
+        if (!Constants.equalsInteger(shopInfo.getAuditStatus(), Constants.ONE)) {
+            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "褰撳墠闂ㄥ簵鐘舵�佷笉鏀寔鏀粯鎶奸噾");
+        }
+        if (shopInfo.getDepositAmount() == null || shopInfo.getDepositAmount() <= 0) {
+            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "鎶奸噾閲戦寮傚父锛屾棤娉曞彂璧锋敮浠�");
+        }
+        // 3. 鏌ヨ浼氬憳openid
+        Member member = memberMapper.selectById(shopInfo.getRegionMemberId());
+        if (member == null || StringUtils.isBlank(member.getOpenid())) {
+            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "鐢ㄦ埛淇℃伅寮傚父锛屾棤娉曞彂璧锋敮浠�");
+        }
+        // 4. 鍒涘缓鎶奸噾璁㈠崟
+        String outTradeNo = generateOrderTradeNo();
+        Date now = new Date();
+        OtherOrders otherOrders = new OtherOrders();
+        otherOrders.setType(Constants.ZERO); // 0=搴楅摵鎶奸噾璁㈠崟
+        otherOrders.setMemberId(shopInfo.getRegionMemberId());
+        otherOrders.setPayAccount(shopInfo.getDepositAmount());
+        otherOrders.setPayStatus(Constants.ZERO);
+        otherOrders.setCode("SD" + new java.text.SimpleDateFormat("yyyyMMddHHmmss").format(now) + shopId);
+        otherOrders.setOutTradeNo(outTradeNo);
+        otherOrders.setDeleted(Constants.ZERO);
+        otherOrders.setCreateTime(now);
+        otherOrdersMapper.insert(otherOrders);
+
+        // 5. 鍞よ捣寰俊鏀粯
+        return wxPayForOtherOrder(otherOrders, member.getOpenid(), Constants.OrdersAttach.SHOP_DEPOSIT);
+    }
+
+    @Override
+    @Transactional(rollbackFor = {Exception.class, BusinessException.class})
+    public void handleShopDepositPayNotify(String outTradeNo, String wxTradeNo) {
+        // 1. 鏌ユ壘鎶奸噾璁㈠崟
+        OtherOrders otherOrders = otherOrdersMapper.selectOne(new QueryWrapper<OtherOrders>().lambda()
+                .eq(OtherOrders::getOutTradeNo, outTradeNo)
+                .eq(OtherOrders::getDeleted, Constants.ZERO)
+                .last("limit 1"));
+        if (otherOrders == null) {
+            throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "鎶奸噾璁㈠崟涓嶅瓨鍦�: " + outTradeNo);
+        }
+        // 2. 骞傜瓑锛氬凡鏀粯鍒欒烦杩�
+        if (Constants.equalsInteger(otherOrders.getPayStatus(), Constants.ONE)) {
+            return;
+        }
+        Date now = new Date();
+        // 3. 鏇存柊鎶奸噾璁㈠崟鐘舵��
+        otherOrders.setPayStatus(Constants.ONE);
+        otherOrders.setPayTime(now);
+        otherOrders.setWxExternalNo(wxTradeNo);
+        otherOrders.setUpdateTime(now);
+        otherOrdersMapper.updateById(otherOrders);
+
+        // 4. 鏌ヨ闂ㄥ簵淇℃伅锛堥�氳繃娉ㄥ唽浼氬憳涓婚敭鍏宠仈锛�
+        ShopInfo shopInfo = shopInfoMapper.selectOne(new QueryWrapper<ShopInfo>().lambda()
+                .eq(ShopInfo::getRegionMemberId, otherOrders.getMemberId())
+                .eq(ShopInfo::getDeleted, Constants.ZERO)
+                .last("limit 1"));
+        if (shopInfo == null) {
+            throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "闂ㄥ簵涓嶅瓨鍦�");
+        }
+        // 5. 鏇存柊闂ㄥ簵鐘舵�侊細宸叉敮浠樻娂閲�
+        shopInfo.setAuditStatus(Constants.THREE); // 3=宸叉敮浠樻娂閲�
+        shopInfo.setPayStatus(Constants.ONE);
+        shopInfo.setPayTime(now);
+        shopInfo.setWxExternalNo(wxTradeNo);
+        shopInfo.setCode(otherOrders.getCode());
+        Member member = memberMapper.selectById(otherOrders.getMemberId());
+        if (member != null) {
+            shopInfo.setPayMemberOpenId(member.getOpenid());
+        }
+        shopInfo.setUpdateTime(now);
+        shopInfoMapper.updateById(shopInfo);
+
+        // 6. 鎶奸噾鏀粯瀹屾垚鍚庯紝鑻ュ煄甯傛湭寮�閫氬垯鑷姩寮�閫�
+        if (shopInfo.getAreaId() != null) {
+            Areas shopArea = areasBiz.resolveArea(shopInfo.getAreaId());
+            if (shopArea != null && shopArea.getParentId() != null) {
+                Areas cityArea = areasBiz.resolveArea(shopArea.getParentId());
+                if (cityArea != null && !Constants.equalsInteger(cityArea.getStatus(), Constants.ONE)) {
+                    cityArea.setStatus(Constants.ONE);
+                    cityArea.setEditDate(now);
+                    areasService.updateById(cityArea);
+                    areasService.cacheData();
+                }
+            }
+        }
+    }
+
+    @Override
+    @Transactional(rollbackFor = {Exception.class, BusinessException.class})
+    public void settleOrders() {
+        // 1. 璇诲彇缁撶畻澶╂暟閰嶇疆
+        SystemDictData settlementConfig = systemDictDataBiz.queryByCode(Constants.OPERATION_CONFIG, Constants.OP_SETTLEMENT_DATE);
+        if (settlementConfig == null || StringUtils.isBlank(settlementConfig.getCode())) {
+            return;
+        }
+        int days = Integer.parseInt(settlementConfig.getCode());
+        // 缁撶畻鎴鏃堕棿 = 褰撳墠鏃堕棿 - N澶�
+        Calendar cal = Calendar.getInstance();
+        cal.add(Calendar.DAY_OF_MONTH, -days);
+        Date deadline = cal.getTime();
+
+        // 2. 鏌ヨ宸插畬鎴愮殑寰呯粨绠楄鍗曪紙瀹屾垚鏃堕棿 <= 鎴鏃堕棿锛�
+        List<Orders> ordersList = ordersMapper.selectList(new QueryWrapper<Orders>().lambda()
+                .eq(Orders::getDeleted, Constants.ZERO)
+                .eq(Orders::getStatus, Constants.OrderStatus.finished.getStatus())
+                .eq(Orders::getSettlementStatus, Constants.ZERO)
+                .le(Orders::getFinishTime, deadline));
+        if (ordersList == null || ordersList.isEmpty()) {
+            return;
+        }
+
+        Date now = new Date();
+        for (Orders order : ordersList) {
+            // 3. 鏇存柊璁㈠崟缁撶畻鐘舵��
+            ordersMapper.update(new UpdateWrapper<Orders>().lambda()
+                    .set(Orders::getSettlementStatus, Constants.ONE)
+                    .set(Orders::getSettlementTime, now)
+                    .set(Orders::getUpdateTime, now)
+                    .eq(Orders::getId, order.getId()));
+
+            // 4. 鏌ヨ鍏宠仈鐨勫緟鍏ヨ处 Revenue 璁板綍
+            List<Revenue> revenues = revenueMapper.selectList(new QueryWrapper<Revenue>().lambda()
+                    .eq(Revenue::getObjId, order.getId())
+                    .eq(Revenue::getObjType, Constants.ZERO)
+                    .eq(Revenue::getVaildStatus, Constants.ZERO)
+                    .eq(Revenue::getDeleted, Constants.ZERO));
+
+            for (Revenue revenue : revenues) {
+                Long amount = revenue.getAmount() != null ? revenue.getAmount() : 0L;
+                // 鏇存柊 Revenue 涓哄凡鍏ヨ处
+                revenueMapper.update(new UpdateWrapper<Revenue>().lambda()
+                        .set(Revenue::getVaildStatus, Constants.ONE)
+                        .set(Revenue::getUpdateTime, now)
+                        .eq(Revenue::getId, revenue.getId()));
+
+                // 鏍规嵁 memberType 鏇存柊浣欓
+                if (Constants.equalsInteger(revenue.getMemberType(), Constants.ONE)) {
+                    // 鍙告満锛氶�氳繃 memberId 鏌� DriverInfo锛屾洿鏂� balance / totalBalance
+                    DriverInfo driver = driverInfoMapper.selectOne(new QueryWrapper<DriverInfo>().lambda()
+                            .eq(DriverInfo::getMemberId, revenue.getMemberId())
+                            .eq(DriverInfo::getDeleted, Constants.ZERO)
+                            .last("limit 1"));
+                    if (driver != null) {
+                        driverInfoMapper.update(new UpdateWrapper<DriverInfo>().lambda()
+                                .setSql(" BALANCE = IFNULL(BALANCE, 0) + " + amount)
+                                .setSql(" TOTAL_BALANCE = IFNULL(TOTAL_BALANCE, 0) + " + amount)
+                                .eq(DriverInfo::getId, driver.getId()));
+                    }
+                } else if (Constants.equalsInteger(revenue.getMemberType(), Constants.TWO)) {
+                    // 闂ㄥ簵锛氶�氳繃 memberId 鏌� ShopInfo(regionMemberId)锛屾洿鏂� balance / totalBalance
+                    ShopInfo shop = shopInfoMapper.selectOne(new QueryWrapper<ShopInfo>().lambda()
+                            .eq(ShopInfo::getRegionMemberId, revenue.getMemberId())
+                            .eq(ShopInfo::getDeleted, Constants.ZERO)
+                            .last("limit 1"));
+                    if (shop != null) {
+                        shopInfoMapper.update(new UpdateWrapper<ShopInfo>().lambda()
+                                .setSql(" BALANCE = IFNULL(BALANCE, 0) + " + amount)
+                                .setSql(" TOTAL_BALANCE = IFNULL(TOTAL_BALANCE, 0) + " + amount)
+                                .eq(ShopInfo::getId, shop.getId()));
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    @Transactional(rollbackFor = {Exception.class, BusinessException.class})
+    public void commentOrder(CommentOrderDTO dto, Integer memberId) {
+        // 1. 鏍¢獙璁㈠崟
+        Orders order = ordersMapper.selectById(dto.getOrderId());
+        if (order == null || Constants.equalsInteger(order.getDeleted(), Constants.ONE)) {
+            throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "璁㈠崟涓嶅瓨鍦�");
+        }
+        if (!Constants.equalsInteger(order.getMemberId(), memberId)) {
+            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "鏃犳潈璇勪环璇ヨ鍗�");
+        }
+        if (!Constants.equalsInteger(order.getStatus(), Constants.OrderStatus.finished.getStatus())) {
+            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "褰撳墠璁㈠崟鐘舵�佷笉鏀寔璇勪环");
+        }
+        if (Constants.equalsInteger(order.getCommentStatus(), Constants.ONE)) {
+            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "璇ヨ鍗曞凡璇勪环");
+        }
+
+        // 2. 寮傚湴瀵勫瓨璁㈠崟锛氬彇浠堕棬搴楀拰鍙告満璇勫垎鏍¢獙
+        boolean isRemote = Constants.equalsInteger(order.getType(), Constants.ONE);
+        if (isRemote) {
+            if (dto.getDriverScore() == null) {
+                throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "寮傚湴瀵勫瓨璁㈠崟蹇呴』璇勪环鍙告満");
+            }
+            if (order.getTakeShopId() != null && dto.getTakeScore() == null) {
+                throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "璇疯瘎浠峰彇浠堕棬搴�");
+            }
+        }
+
+        Date now = new Date();
+
+        // 3. 鏇存柊璁㈠崟璇勪环鐘舵��
+        order.setCommentStatus(Constants.ONE);
+        order.setCommentInfo(dto.getContent());
+        order.setCommentDepositLevel(dto.getDepositScore());
+        order.setCommentTakeLevel(dto.getTakeScore());
+        order.setCommentDriverLevel(dto.getDriverScore());
+        order.setCommentTime(now);
+        order.setUpdateTime(now);
+        ordersMapper.updateById(order);
+
+        // 4. 鍒涘缓璇勪环璁板綍
+        // 4.1 瀛樹欢闂ㄥ簵
+        OrderComment depositComment = new OrderComment();
+        depositComment.setOrderId(order.getId());
+        depositComment.setOrderCode(order.getCode());
+        depositComment.setMemberId(memberId);
+        depositComment.setTargetType(Constants.ONE); // 1=瀛樹欢闂ㄥ簵
+        depositComment.setTargetId(order.getDepositShopId());
+        depositComment.setScore(dto.getDepositScore());
+        depositComment.setContent(dto.getContent());
+        depositComment.setDeleted(Constants.ZERO);
+        depositComment.setCreateTime(now);
+        orderCommentMapper.insert(depositComment);
+
+        // 4.2 鍙栦欢闂ㄥ簵锛堝紓鍦板瘎瀛樹笖鏈夊彇浠堕棬搴楋級
+        if (isRemote && order.getTakeShopId() != null && dto.getTakeScore() != null) {
+            OrderComment takeComment = new OrderComment();
+            takeComment.setOrderId(order.getId());
+            takeComment.setOrderCode(order.getCode());
+            takeComment.setMemberId(memberId);
+            takeComment.setTargetType(Constants.TWO); // 2=鍙栦欢闂ㄥ簵
+            takeComment.setTargetId(order.getTakeShopId());
+            takeComment.setScore(dto.getTakeScore());
+            takeComment.setContent(dto.getContent());
+            takeComment.setDeleted(Constants.ZERO);
+            takeComment.setCreateTime(now);
+            orderCommentMapper.insert(takeComment);
+        }
+
+        // 4.3 鍙告満锛堝紓鍦板瘎瀛橈級
+        if (isRemote && order.getAcceptDriver() != null && dto.getDriverScore() != null) {
+            OrderComment driverComment = new OrderComment();
+            driverComment.setOrderId(order.getId());
+            driverComment.setOrderCode(order.getCode());
+            driverComment.setMemberId(memberId);
+            driverComment.setTargetType(Constants.THREE); // 3=鍙告満
+            driverComment.setTargetId(order.getAcceptDriver());
+            driverComment.setScore(dto.getDriverScore());
+            driverComment.setContent(dto.getContent());
+            driverComment.setDeleted(Constants.ZERO);
+            driverComment.setCreateTime(now);
+            orderCommentMapper.insert(driverComment);
+        }
+
+        // 5. 鏇存柊闂ㄥ簵/鍙告満骞冲潎璇勫垎
+        updateTargetScore(Constants.ONE, order.getDepositShopId());
+        if (isRemote && order.getTakeShopId() != null) {
+            updateTargetScore(Constants.TWO, order.getTakeShopId());
+        }
+        if (isRemote && order.getAcceptDriver() != null) {
+            updateTargetScore(Constants.THREE, order.getAcceptDriver());
+        }
+    }
+
+    /**
+     * 鏇存柊璇勪环瀵硅薄锛堥棬搴�/鍙告満锛夌殑骞冲潎璇勫垎
+     */
+    private void updateTargetScore(Integer targetType, Integer targetId) {
+        List<OrderComment> comments = orderCommentMapper.selectList(new QueryWrapper<OrderComment>().lambda()
+                .eq(OrderComment::getDeleted, Constants.ZERO)
+                .eq(OrderComment::getTargetType, targetType)
+                .eq(OrderComment::getTargetId, targetId));
+        if (comments.isEmpty()) {
+            return;
+        }
+        double avg = comments.stream()
+                .mapToInt(OrderComment::getScore)
+                .average()
+                .orElse(0.0);
+        BigDecimal score = BigDecimal.valueOf(avg).setScale(1, BigDecimal.ROUND_HALF_UP);
+        Date now = new Date();
+        if (Constants.equalsInteger(targetType, Constants.ONE) || Constants.equalsInteger(targetType, Constants.TWO)) {
+            ShopInfo shopInfo = shopInfoMapper.selectById(targetId);
+            if (shopInfo != null) {
+                shopInfo.setScore(score);
+                shopInfo.setUpdateTime(now);
+                shopInfoMapper.updateById(shopInfo);
+            }
+        } else if (Constants.equalsInteger(targetType, Constants.THREE)) {
+            DriverInfo driverInfo = driverInfoMapper.selectById(targetId);
+            if (driverInfo != null) {
+                driverInfo.setScore(score);
+                driverInfo.setUpdateTime(now);
+                driverInfoMapper.updateById(driverInfo);
+            }
+        }
+    }
+
+    /**
+     * 鍞よ捣寰俊鏀粯锛堝叾浠栬鍗曪級
+     */
+    private PayResponse wxPayForOtherOrder(OtherOrders otherOrders, String openid, Constants.OrdersAttach ordersAttach) {
+        try {
+            WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
+            request.setBody(ordersAttach.getName());
+            request.setAttach(ordersAttach.getKey());
+            request.setOutTradeNo(otherOrders.getOutTradeNo());
+            long totalFee = otherOrders.getPayAccount() != null ? otherOrders.getPayAccount() : 0L;
+            request.setTotalFee((int) totalFee);
+            request.setTimeStart(DateUtil.DateToString(new Date(), "yyyyMMddHHmmss"));
+            request.setSpbillCreateIp(Constants.getIpAddr());
+            request.setOpenid(openid);
+
+            Object response = WxMiniConfig.wxPayService.createOrder(request);
+
+            PayResponse payResponse = new PayResponse();
+            payResponse.setResponse(response);
+            payResponse.setOrderId(otherOrders.getId());
+            return payResponse;
+        } catch (WxPayException e) {
+            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "鏀粯璋冭捣澶辫触锛�" + e.getMessage());
+        }
+    }
+
+    @Override
     @Transactional(rollbackFor = {Exception.class, BusinessException.class})
     public void shopVerifyOrder(String verifyCode, Integer shopId, List<String> images, String remark) {
         if (StringUtils.isBlank(verifyCode)) {
@@ -1663,11 +2211,217 @@
             releaseVerifyCode(verifyCode);
             // 淇濆瓨鍑哄簱鍥剧墖锛坥bj_type=13 闂ㄥ簵鍑哄簱鍥剧墖锛屾渶澶�3寮狅級
             saveVerifyImages(order.getId(), images, Constants.FileType.STORE_OUT.getKey(), shopId);
+            // 鐢熸垚鏀剁泭璁板綍
+            calculateAndSaveOrderFees(order.getId());
+            generateRevenueRecords(order.getId());
             // 璁板綍璁㈠崟鏃ュ織
             saveShopVerifyLog(order, "闂ㄥ簵纭鍙栦欢", "闂ㄥ簵銆�" + shopName + "銆戠‘璁ゅ彇浠讹紝璁㈠崟瀹屾垚", remark, shopId);
         } else {
             throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "褰撳墠璁㈠崟鐘舵�佷笉鍏佽鏍搁攢");
         }
+    }
+
+    @Override
+    @Transactional(rollbackFor = {Exception.class, BusinessException.class})
+    public void confirmStoreOut(Integer orderId, Integer shopId, List<String> images, String remark) {
+        // 1. 鏌ヨ璁㈠崟
+        Orders order = ordersMapper.selectById(orderId);
+        if (order == null || Constants.equalsInteger(order.getDeleted(), Constants.ONE)) {
+            throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "璁㈠崟涓嶅瓨鍦�");
+        }
+        // 2. 鏍¢獙鐘舵�侊細寰呭彇浠�(5)
+        if (!Constants.equalsInteger(order.getStatus(), Constants.OrderStatus.arrived.getStatus())) {
+            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "褰撳墠璁㈠崟鐘舵�佷笉鍏佽鍑哄簱");
+        }
+        // 3. 鏍¢獙閫炬湡鐘舵�侊細0=鏈�炬湡 鎴� 2=宸叉敮浠�
+        if (order.getOverdueStatus() != null && Constants.equalsInteger(order.getOverdueStatus(), Constants.ONE)) {
+            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "璁㈠崟瀛樺湪閫炬湡鏈敮浠樿垂鐢紝璇峰厛瀹屾垚閫炬湡璐圭敤鏀粯");
+        }
+        // 4. 鏍¢獙纭鍒板簵鏃堕棿涓嶄负绌�
+        if (order.getConfirmArriveTime() == null) {
+            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "璁㈠崟灏氭湭纭鍒板簵锛屾棤娉曞嚭搴�");
+        }
+        // 5. 鏍¢獙闂ㄥ簵涓庤鍗曞叧绯�
+        if (Constants.equalsInteger(order.getType(), Constants.ZERO)) {
+            // 灏卞湴瀵勫瓨锛氬彇浠堕棬搴楀嵆瀛樹欢闂ㄥ簵
+            if (!shopId.equals(order.getDepositShopId())) {
+                throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "璇ヨ鍗曚笉灞炰簬褰撳墠闂ㄥ簵");
+            }
+        } else {
+            // 寮傚湴瀵勫瓨锛氭牎楠屽彇浠堕棬搴�
+            if (order.getTakeShopId() == null) {
+                throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "璇ヨ鍗曟棤鍙栦欢闂ㄥ簵锛屾棤娉曞嚭搴�");
+            }
+            if (!shopId.equals(order.getTakeShopId())) {
+                throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "璇ヨ鍗曚笉灞炰簬褰撳墠闂ㄥ簵");
+            }
+        }
+
+        // 6. 鏌ヨ闂ㄥ簵鍚嶇О
+        String shopName = "";
+        ShopInfo shopInfo = shopInfoMapper.selectById(shopId);
+        if (shopInfo != null) {
+            shopName = shopInfo.getName() != null ? shopInfo.getName() : "";
+        }
+
+        // 7. 鏇存柊璁㈠崟鐘舵�佷负宸插畬鎴�
+        Date now = new Date();
+        order.setStatus(Constants.OrderStatus.finished.getStatus());
+        order.setFinishTime(now);
+        order.setUpdateTime(now);
+        ordersMapper.updateById(order);
+
+        // 8. 閲婃斁鏍搁攢鐮�
+        if (StringUtils.isNotBlank(order.getMemberVerifyCode())) {
+            releaseVerifyCode(order.getMemberVerifyCode());
+        }
+
+        // 9. 淇濆瓨鍑哄簱鍥剧墖锛坥bj_type=13 闂ㄥ簵鍑哄簱鍥剧墖锛屾渶澶�3寮狅級
+        saveVerifyImages(order.getId(), images, Constants.FileType.STORE_OUT.getKey(), shopId);
+
+        // 10. 濡傛灉瀛樺湪閫�娆鹃噾棰濓紝鍏堜繚瀛橀��娆捐褰曞啀璋冪敤寰俊閫�娆�
+        //    閫�娆捐褰曞湪閫�娆捐皟鐢ㄥ墠钀藉簱锛岄伩鍏嶉��娆炬垚鍔熶絾鏈湴寮傚父瀵艰嚧鏃犺褰�
+        if (order.getRefundAmount() != null && order.getRefundAmount() > 0
+                && StringUtils.isNotBlank(order.getOutTradeNo())
+                && order.getPayAmount() != null && order.getPayAmount() > 0) {
+            OrdersRefund refundRecord = new OrdersRefund();
+            refundRecord.setOrderId(orderId);
+            refundRecord.setType(3); // 鍑哄簱閫�娆�
+            refundRecord.setCreateTime(now);
+            refundRecord.setRefundRemark(remark);
+            refundRecord.setDeleted(Constants.ZERO);
+            ordersRefundMapper.insert(refundRecord);
+
+            // 璋冪敤寰俊閫�娆撅紙鏀惧湪鏈�鍚庯紝纭繚鍓嶇疆鎿嶄綔鍏ㄩ儴鎴愬姛锛�
+            String refundCode = wxMiniUtilService.wxRefund(
+                    order.getOutTradeNo(), order.getPayAmount(), order.getRefundAmount());
+
+            // 閫�娆炬垚鍔熷悗鍥炲~閫�娆惧崟鍙峰拰鏃堕棿
+            refundRecord.setRefundCode(refundCode);
+            refundRecord.setRefundTime(new Date());
+            ordersRefundMapper.updateById(refundRecord);
+        }
+
+        // 11. 鐢熸垚鏀剁泭璁板綍
+        calculateAndSaveOrderFees(orderId);
+        generateRevenueRecords(orderId);
+
+        // 12. 璁板綍璁㈠崟鏃ュ織
+        String logInfo = "闂ㄥ簵銆�" + shopName + "銆戠‘璁ゅ嚭搴擄紝璁㈠崟瀹屾垚";
+        if (order.getRefundAmount() != null && order.getRefundAmount() > 0) {
+            logInfo += "锛岄��娆�" + Constants.getFormatMoney(order.getRefundAmount()) + "鍏�";
+        }
+        saveShopVerifyLog(order, "闂ㄥ簵纭鍑哄簱", logInfo, remark, shopId);
+    }
+
+    @Override
+    public void calculateAndSaveOrderFees(Integer orderId) {
+        Orders order = ordersMapper.selectById(orderId);
+        if (order == null || Constants.equalsInteger(order.getDeleted(), Constants.ONE)) {
+            throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "璁㈠崟涓嶅瓨鍦�");
+        }
+
+        Long totalAmount = order.getTotalAmount() != null ? order.getTotalAmount() : 0L;
+        // 璐圭巼锛堜负绌烘椂榛樿0锛�
+        BigDecimal depositRate = order.getDepositShopFeeRata() != null ? order.getDepositShopFeeRata() : BigDecimal.ZERO;
+        BigDecimal takeRate = order.getTakeShopFeeRata() != null ? order.getTakeShopFeeRata() : BigDecimal.ZERO;
+        BigDecimal driverRate = order.getDriverFeeRata() != null ? order.getDriverFeeRata() : BigDecimal.ZERO;
+        Long exceptionFeeVal = order.getExceptionFee() != null ? order.getExceptionFee() : 0L;
+
+        //瀛樹欢闂ㄥ簵鏀剁泭
+        Long depositShopFee = new BigDecimal(totalAmount)
+                .multiply(depositRate)
+                .setScale(0, RoundingMode.HALF_UP)
+                .longValue();
+
+        Long takeShopFee = 0L;
+        Long driverFee = 0L;
+
+        if (Constants.equalsInteger(order.getType(), Constants.TWO)) {
+            // 寮傚湴瀵勫瓨锛氬瓨浠堕棬搴� + 鍙告満
+            driverFee = new BigDecimal(totalAmount)
+                    .multiply(driverRate)
+                    .setScale(0, RoundingMode.HALF_UP)
+                    .longValue()
+                    + exceptionFeeVal;
+
+            // 寮傚湴瀵勫瓨涓旀湁鍙栦欢闂ㄥ簵锛氬姞涓婂彇浠堕棬搴楁敹鐩�
+            if (order.getTakeShopId() != null) {
+                takeShopFee = new BigDecimal(totalAmount)
+                        .multiply(takeRate)
+                        .setScale(0, RoundingMode.HALF_UP)
+                        .longValue();
+            }
+        }
+
+        ordersMapper.update(new UpdateWrapper<Orders>().lambda()
+                .eq(Orders::getId, orderId)
+                .set(Orders::getDepositShopFee, depositShopFee)
+                .set(Orders::getTakeShopFee, takeShopFee)
+                .set(Orders::getDriverFee, driverFee)
+                .set(Orders::getUpdateTime, new Date()));
+    }
+
+    /**
+     * 鐢熸垚闂ㄥ簵/鍙告満鏀剁泭璁板綍锛堟湭缁撶畻锛�
+     * 璁㈠崟瀹屾垚鏃惰皟鐢紝璇诲彇璁㈠崟涓婂凡璁$畻濂界殑璐圭敤瀛楁
+     */
+    private void generateRevenueRecords(Integer orderId) {
+        Orders order = ordersMapper.selectById(orderId);
+        if (order == null) {
+            return;
+        }
+        Date now = new Date();
+        Long depositShopFee = order.getDepositShopFee() != null ? order.getDepositShopFee() : 0L;
+        Long takeShopFee = order.getTakeShopFee() != null ? order.getTakeShopFee() : 0L;
+        Long driverFee = order.getDriverFee() != null ? order.getDriverFee() : 0L;
+
+        // 瀛樹欢闂ㄥ簵鏀剁泭
+        if (depositShopFee > 0 && order.getDepositShopId() != null) {
+            ShopInfo depositShop = shopInfoMapper.selectById(order.getDepositShopId());
+            if (depositShop != null && depositShop.getRegionMemberId() != null) {
+                revenueMapper.insert(buildRevenue(depositShop.getRegionMemberId(), Constants.TWO,
+                        depositShopFee, orderId, order.getCode()));
+            }
+        }
+
+        // 鍙栦欢闂ㄥ簵鏀剁泭锛堝紓鍦板瘎瀛樹笖鏈夊彇浠堕棬搴楋級
+        if (takeShopFee > 0 && order.getTakeShopId() != null) {
+            ShopInfo takeShop = shopInfoMapper.selectById(order.getTakeShopId());
+            if (takeShop != null && takeShop.getRegionMemberId() != null) {
+                revenueMapper.insert(buildRevenue(takeShop.getRegionMemberId(), Constants.TWO,
+                        takeShopFee, orderId, order.getCode()));
+            }
+        }
+
+        // 鍙告満鏀剁泭锛堝紓鍦板瘎瀛橈級
+        if (driverFee > 0 && order.getAcceptDriver() != null) {
+            DriverInfo driver = driverInfoMapper.selectById(order.getAcceptDriver());
+            if (driver != null && driver.getMemberId() != null) {
+                revenueMapper.insert(buildRevenue(driver.getMemberId(), Constants.ONE,
+                        driverFee, orderId, order.getCode()));
+            }
+        }
+    }
+
+    /**
+     * 鏋勫缓鏀剁泭璁板綍
+     */
+    private Revenue buildRevenue(Integer memberId, Integer memberType, Long amount, Integer orderId, String orderNo) {
+        Revenue revenue = new Revenue();
+        revenue.setMemberId(memberId);
+        revenue.setMemberType(memberType); // 1=鍙告満, 2=闂ㄥ簵
+        revenue.setType(Constants.ZERO); // 0=瀹屾垚璁㈠崟
+        revenue.setOptType(Constants.ONE); // 1=鏀跺叆
+        revenue.setAmount(amount);
+        revenue.setVaildStatus(Constants.ZERO); // 0=鍏ヨ处涓紙鏈粨绠楋級
+        revenue.setObjId(orderId);
+        revenue.setObjType(Constants.ZERO); // 0=璁㈠崟涓氬姟
+        revenue.setStatus(Constants.ZERO); // 0=鎴愬姛
+        revenue.setOrderNo(orderNo);
+        revenue.setDeleted(Constants.ZERO);
+        revenue.setCreateTime(new Date());
+        return revenue;
     }
 
     @Override
@@ -1799,23 +2553,48 @@
                             + "澶╋紝閫炬湡璐圭敤" + Constants.getFormatMoney(overdueInfo.getOverdueFee()) + "鍏�",
                     null, shopId);
         } else {
-            // 鏈�炬湡锛氬畬鎴愯鍗�
-            order.setStatus(Constants.OrderStatus.finished.getStatus());
+            // 鏈�炬湡锛氭爣璁伴�炬湡鐘舵�佷负0锛岃鍗曚繚鎸佸綋鍓嶇姸鎬�
             order.setConfirmArriveTime(now);
-            order.setFinishTime(now);
             order.setOverdueStatus(Constants.ZERO);
+
+            // 灏卞湴瀵勫瓨锛氳绠楁槸鍚﹂渶瑕侀��娆�
+            if (Constants.equalsInteger(order.getType(), Constants.ZERO) && !CollectionUtils.isEmpty(details)) {
+                int actualDays = calcActualDepositDays(now, order.getDepositTime());
+                order.setDepositDays(actualDays);
+
+                int estimatedDays = order.getEstimatedDepositDays() != null ? order.getEstimatedDepositDays() : 1;
+                int refundDays = estimatedDays - actualDays;
+                if (refundDays > 0) {
+                    // 閫�娆鹃噾棰� = 閫�娆惧ぉ鏁� 脳 危(鐗╁搧鍗曚环 脳 鏁伴噺)
+                    long dailyBaseFee = 0L;
+                    for (OrdersDetail d : details) {
+                        dailyBaseFee += (d.getUnitPrice() != null ? d.getUnitPrice() : 0L)
+                                * (d.getNum() != null ? d.getNum() : 0);
+                    }
+                    long refundAmount = (long) refundDays * dailyBaseFee;
+                    order.setRefundAmount(refundAmount);
+                }
+            }
+
             order.setUpdateTime(now);
             ordersMapper.updateById(order);
 
-            // 閲婃斁鏍搁攢鐮�
-            if (StringUtils.isNotBlank(order.getMemberVerifyCode())) {
-                releaseVerifyCode(order.getMemberVerifyCode());
+            // 閫�娆惧鑷存�婚噾棰濆彉鍖栵紝閲嶇畻涓夋柟鏀剁泭
+            if (order.getRefundAmount() != null && order.getRefundAmount() > 0) {
+                long newTotal = (order.getTotalAmount() != null ? order.getTotalAmount() : 0L) - order.getRefundAmount();
+                order.setTotalAmount(newTotal);
+                ordersMapper.update(new UpdateWrapper<Orders>().lambda()
+                        .eq(Orders::getId, orderId)
+                        .set(Orders::getTotalAmount, newTotal));
+                calculateAndSaveOrderFees(orderId);
             }
 
             // 璁板綍璁㈠崟鏃ュ織
-            saveShopVerifyLog(order, "纭椤惧鍒板簵",
-                    "闂ㄥ簵銆�" + shopName + "銆戠‘璁ら【瀹㈠埌搴楋紝璁㈠崟瀹屾垚",
-                    null, shopId);
+            String logInfo = "闂ㄥ簵銆�" + shopName + "銆戠‘璁ら【瀹㈠埌搴楋紝鏈�炬湡";
+            if (order.getRefundAmount() != null && order.getRefundAmount() > 0) {
+                logInfo += "锛岄渶閫�娆�" + Constants.getFormatMoney(order.getRefundAmount()) + "鍏�";
+            }
+            saveShopVerifyLog(order, "纭椤惧鍒板簵", logInfo, null, shopId);
         }
     }
 
@@ -1972,6 +2751,32 @@
     }
 
     /**
+     * 璁$畻瀹為檯瀵勫瓨澶╂暟锛坉epositTime 鍒� now 鐨勫ぉ鏁板樊锛屾渶灏�1澶╋級
+     */
+    private int calcActualDepositDays(Date now, Date depositTime) {
+        if (depositTime == null || now == null) {
+            return 1;
+        }
+        Calendar depositCal = Calendar.getInstance();
+        depositCal.setTime(depositTime);
+        depositCal.set(Calendar.HOUR_OF_DAY, 0);
+        depositCal.set(Calendar.MINUTE, 0);
+        depositCal.set(Calendar.SECOND, 0);
+        depositCal.set(Calendar.MILLISECOND, 0);
+
+        Calendar nowCal = Calendar.getInstance();
+        nowCal.setTime(now);
+        nowCal.set(Calendar.HOUR_OF_DAY, 0);
+        nowCal.set(Calendar.MINUTE, 0);
+        nowCal.set(Calendar.SECOND, 0);
+        nowCal.set(Calendar.MILLISECOND, 0);
+
+        long diffMs = nowCal.getTimeInMillis() - depositCal.getTimeInMillis();
+        int days = (int) (diffMs / (1000 * 60 * 60 * 24));
+        return Math.max(days, 1);
+    }
+
+    /**
      * 灏卞湴瀵勫瓨閫炬湡澶╂暟璁$畻
      * 杩囦簡棰勮鍙栦欢鏃堕棿褰撳ぉ鐨�12鐐瑰悗鎵嶇畻涓�澶�
      */

--
Gitblit v1.9.3