rk
12 小时以前 c74a6f59490cfb9a0ee37f70427739b74e7fbd58
server/services/src/main/java/com/doumee/service/business/impl/OrdersServiceImpl.java
@@ -36,6 +36,8 @@
import com.doumee.dao.dto.CommentOrderDTO;
import com.doumee.dao.dto.CreateOrderDTO;
import com.doumee.dao.dto.DispatchDTO;
import com.doumee.dao.dto.HandleOrderExceptionDTO;
import com.doumee.dao.dto.ManualRefundDTO;
import com.doumee.dao.dto.MyOrderDTO;
import com.doumee.dao.dto.OrderItemDTO;
import com.doumee.dao.vo.*;
@@ -112,6 +114,9 @@
    @Autowired
    private RevenueMapper revenueMapper;
    @Autowired
    private RewardRecordMapper rewardRecordMapper;
    @Autowired
@@ -125,6 +130,9 @@
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private MemberCouponMapper memberCouponMapper;
    @Autowired
    private AreasBiz areasBiz;
@@ -229,7 +237,7 @@
                .leftJoin(Category.class, Category::getId, Orders::getGoodType)
                .leftJoin(DriverInfo.class, DriverInfo::getId, Orders::getAcceptDriver)
                .leftJoin("shop_info s1 on s1.id = t.DEPOSIT_SHOP_ID")
                .leftJoin("shop_info s2 on s2.id = t.TAKE_SHOP_ID");
                .leftJoin("shop_info s2 on s2.id = t.TAKE_SHOP_ID") ;
                ;
        Utils.MP.blankToNull(pageWrap.getModel());
        queryWrapper.eq(pageWrap.getModel().getDeleted() != null, Orders::getDeleted, pageWrap.getModel().getDeleted());
@@ -259,6 +267,11 @@
            if(Constants.equalsInteger(o.getIsUrgent(),Constants.ZERO)){
                o.setUrgentAmount(Constants.ZERO.longValue());
            }
            // 实付金额 = 支付金额 - 退款金额 + 逾期费用
            long pay = o.getPayAmount() != null ? o.getPayAmount() : 0L;
            long refund = o.getRefundAmount() != null ? o.getRefundAmount() : 0L;
            long overdue = o.getOverdueAmount() != null ? o.getOverdueAmount() : 0L;
            o.setPayAmount(pay - refund + overdue);
        }
        return pageData;
    }
@@ -427,6 +440,7 @@
        result.setTotalPrice(totalPrice);
        result.setDays(days);
        result.setUrgentFee(0L);
        resolveCoupon(result, dto.getMemberId(), dto.getCouponId(), totalPrice);
        return result;
    }
@@ -630,7 +644,50 @@
            }
        }
        resolveCoupon(result, dto.getMemberId(), dto.getCouponId(), totalPrice);
        return result;
    }
    private void resolveCoupon(PriceCalculateVO result, Integer memberId, Integer couponId, long totalPrice) {
        if (memberId == null) {
            result.setDeductionAmount(0L);
            return;
        }
        // 查询可用优惠券:已领取、未过期、满足满额门槛
        Date now = new Date();
        List<MemberCoupon> availableCoupons = memberCouponMapper.selectList(new QueryWrapper<MemberCoupon>().lambda()
                .eq(MemberCoupon::getMemberId, memberId)
                .eq(MemberCoupon::getStatus, Constants.CouponStatus.claimed.getKey())
                .eq(MemberCoupon::getIsdeleted, Constants.ZERO)
                .le(MemberCoupon::getLimitPrice, totalPrice)
                .ge(MemberCoupon::getEndDate, now)
                .orderByDesc(MemberCoupon::getPrice)
                .orderByAsc(MemberCoupon::getEndDate));
        result.setAvailableCoupons(availableCoupons);
        if (couponId == null) {
            result.setDeductionAmount(0L);
            return;
        }
        MemberCoupon selected;
        if (couponId == -1) {
            selected = availableCoupons.isEmpty() ? null : availableCoupons.get(0);
        } else {
            selected = availableCoupons.stream()
                    .filter(mc -> mc.getId().equals(couponId))
                    .findFirst().orElse(null);
            if (selected == null) {
                throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "优惠券无效或不可用");
            }
        }
        if (selected != null) {
            result.setDeductionAmount(selected.getPrice());
            result.setSelectedCoupon(selected);
        } else {
            result.setDeductionAmount(0L);
        }
    }
    @Override
@@ -767,6 +824,8 @@
            priceDTO.setDepositEndTime(takeTime);
            priceDTO.setItems(dto.getItems());
            priceDTO.setDeclaredAmount(dto.getDeclaredAmount());
            priceDTO.setMemberId(memberId);
            priceDTO.setCouponId(dto.getCouponId());
            priceResult = calculateLocalPrice(priceDTO);
        } else {
            // 异地寄存
@@ -779,6 +838,8 @@
            priceDTO.setItems(dto.getItems());
            priceDTO.setDeclaredAmount(dto.getDeclaredAmount());
            priceDTO.setUrgent(Constants.ONE.equals(dto.getIsUrgent()));
            priceDTO.setMemberId(memberId);
            priceDTO.setCouponId(dto.getCouponId());
            priceResult = calculateRemotePrice(priceDTO);
        }
@@ -867,8 +928,12 @@
        // 费用信息(分)
        orders.setBasicAmount(priceResult.getItemPrice());
        orders.setEstimatedAmount(priceResult.getTotalPrice());
        orders.setTotalAmount(priceResult.getTotalPrice());
        long deductionAmount = priceResult.getDeductionAmount() != null ? priceResult.getDeductionAmount() : 0L;
        orders.setTotalAmount(priceResult.getTotalPrice() - deductionAmount);
        orders.setUrgentAmount(priceResult.getUrgentFee());
        orders.setCouponId(dto.getCouponId());
        orders.setDeductionAmount(deductionAmount);
        orders.setManualRefund(Constants.ZERO);
        // 存储加急系数
        if (Constants.ONE.equals(dto.getType()) && Constants.ONE.equals(dto.getIsUrgent())) {
            String urgentRateStr = systemDictDataBiz.queryByCode(
@@ -891,6 +956,16 @@
        ordersMapper.insert(orders);
        Integer orderId = orders.getId();
        // 标记优惠券已使用
        MemberCoupon selectedCoupon = priceResult.getSelectedCoupon();
        if (selectedCoupon != null) {
            memberCouponMapper.update(new UpdateWrapper<MemberCoupon>().lambda()
                    .set(MemberCoupon::getStatus, Constants.CouponStatus.used.getKey())
                    .set(MemberCoupon::getUseDate, new Date())
                    .set(MemberCoupon::getOrderId, orderId)
                    .eq(MemberCoupon::getId, selectedCoupon.getId()));
        }
        // 创建订单日志
        OrderLog createLog = new OrderLog();
@@ -1079,6 +1154,7 @@
        OrderDetailVO vo = new OrderDetailVO();
        vo.setOrder(order);
        vo.setDeductionAmount(order.getDeductionAmount());
        // 订单状态描述
        if (order.getStatus() != null) {
@@ -1553,6 +1629,7 @@
                .select("s1.name", Orders::getDepositShopName)
                .select("s1.link_name", Orders::getDepositShopLinkName)
                .select("s1.link_phone", Orders::getDepositShopLinkPhone)
                .select("s1.address", Orders::getDepositShopAddress)
                .select("s2.name", Orders::getTakeShopName)
                .select("s2.address", Orders::getTakeShopAddress)
                .select("s2.link_phone", Orders::getTakeShopLinkPhone)
@@ -1566,6 +1643,21 @@
                .eq(status != null, Orders::getStatus, status)
                .in(statusList != null, Orders::getStatus, statusList)
                .orderByDesc(Orders::getCreateTime);
        // 可开票订单:增加月份限制
        if (model != null && model.getInvoiceStatus() != null && Constants.equalsInteger(model.getInvoiceStatus(), Constants.ONE)) {
            wrapper.in(Orders::getInvoiceStatus, Arrays.asList(Constants.ONE, 99));
            String monthLimitStr = operationConfigBiz.getConfig().getInvoiceMonthLimit();
            if (StringUtils.isNotBlank(monthLimitStr)) {
                int monthLimit = Integer.parseInt(monthLimitStr);
                Calendar cal = Calendar.getInstance();
                cal.add(Calendar.MONTH, -monthLimit);
                cal.set(Calendar.HOUR_OF_DAY, 0);
                cal.set(Calendar.MINUTE, 0);
                cal.set(Calendar.SECOND, 0);
                cal.set(Calendar.MILLISECOND, 0);
                wrapper.ge(Orders::getFinishTime, cal.getTime());
            }
        }
        // 关键词搜索:收件人/收件人电话模糊、订单号精准
        if (model != null && StringUtils.isNotBlank(model.getKeyword())) {
            String kw = model.getKeyword().trim();
@@ -1601,7 +1693,7 @@
                vo.setDepositShopName(o.getDepositShopName());
                vo.setDepositShopLinkName(o.getDepositShopLinkName());
                vo.setDepositShopPhone(o.getDepositShopLinkPhone());
                vo.setDepositShopAddress(o.getDepositShopAddress());
                // 取件信息:有取件门店取门店,无则取用户自选取件点
                if (o.getTakeShopId() != null) {
                    vo.setTakeShopId(o.getTakeShopId());
@@ -1643,6 +1735,14 @@
                vo.setOrderImages(getFileUrlsFromList(o.getId(),files));
                // 逾期状态
                fillOverdueStatus(vo, o, details);
                // 优惠券抵扣金额
                vo.setDeductionAmount(o.getDeductionAmount());
                // 可开票金额(支付金额 - 退款金额)
                if (model != null && model.getInvoiceStatus() != null && Constants.equalsInteger(model.getInvoiceStatus(), Constants.ONE)) {
                    long payAmt = o.getPayAmount() != null ? o.getPayAmount() : 0L;
                    long refundAmt = o.getRefundAmount() != null ? o.getRefundAmount() : 0L;
                    vo.setInvoiceAmount(payAmt - refundAmt);
                }
                voList.add(vo);
            }
        }
@@ -1890,7 +1990,10 @@
        //序号
        vo.setSortnum(Constants.formatIntegerNum(order.getDepositShopId())+"-"+order.getId());
        if(order.getTakeShopId()!=null){
            vo.setSortnumTake(Constants.formatIntegerNum(order.getTakeShopId())+"-"+order.getId());
            String dateStr = new SimpleDateFormat("dd").format(order.getPayTime() != null ? order.getPayTime() : new Date());
            String autoNumStr = String.format("%03d", order.getAutoNum() != null ? order.getAutoNum() : 0);
            String sort = order.getTakeShopId() + "-" + dateStr + "-" + autoNumStr;
            vo.setSortnumTake(sort);
        }
        // 存件门店
        if (order.getDepositShopId() != null) {
@@ -2044,6 +2147,7 @@
            order.setStatus(Constants.OrderStatus.cancelled.getStatus());
            order.setCancelTime(now);
            ordersMapper.updateById(order);
            restoreCoupon(order);
            saveCancelLog(order, Constants.OrderLogType.memberCancel, "会员取消订单(待支付)", memberId);
            // 短信通知会员:订单已取消
            Member cancelMember1 = memberMapper.selectById(memberId);
@@ -2105,6 +2209,7 @@
                throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "退款失败,请联系客服处理");
            }
            ordersRefundMapper.insert(refund);
            restoreCoupon(order);
            return;
        }
@@ -2176,6 +2281,19 @@
    /**
     * 保存取消订单操作日志
     */
    private void restoreCoupon(Orders order) {
//        if (order.getCouponId() == null || order.getDeductionAmount() == null || order.getDeductionAmount() <= 0) {
//            return;
//        }
//        memberCouponMapper.update(new UpdateWrapper<MemberCoupon>().lambda()
//                .set(MemberCoupon::getStatus, Constants.CouponStatus.claimed.getKey())
//                .set(MemberCoupon::getUseDate, null)
//                .set(MemberCoupon::getOrderId, null)
//                .eq(MemberCoupon::getId, order.getCouponId())
//                .eq(MemberCoupon::getOrderId, order.getId())
//                .eq(MemberCoupon::getStatus, Constants.CouponStatus.used.getKey()));
    }
    private void saveCancelLog(Orders order, Constants.OrderLogType logType, String reason, Integer memberId) {
        OrderLog log = new OrderLog();
        log.setOrderId(order.getId());
@@ -2188,6 +2306,217 @@
        log.setCreateTime(new Date());
        log.setDeleted(Constants.ZERO);
        orderLogService.create(log);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void manualRefund(ManualRefundDTO dto, Integer userId) {
        // 1. 校验订单
        Orders order = ordersMapper.selectById(dto.getOrderId());
        if (order == null || Constants.equalsInteger(order.getDeleted(), Constants.ONE)) {
            throw new BusinessException(ResponseStatus.DATA_EMPTY);
        }
        if (!Constants.equalsInteger(order.getStatus(), Constants.OrderStatus.finished.getStatus())) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "仅已完成订单可手动退款");
        }
        if (Constants.equalsInteger(order.getManualRefund(), Constants.ONE)) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "该订单已手动退款");
        }
        // 异常订单不允许手动退款
        if (Constants.equalsInteger(order.getExceptionStatus(), Constants.ONE)) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "异常订单不支持手动退款");
        }
        // 2. 校验退款金额
        long payAmount = order.getPayAmount() != null ? order.getPayAmount() : 0L;
        long existingRefund = order.getRefundAmount() != null ? order.getRefundAmount() : 0L;
        long maxRefund = payAmount - existingRefund;
        if (dto.getRefundAmount() <= 0) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "退款金额必须大于0");
        }
        if (dto.getRefundAmount() > maxRefund) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "退款金额不能超过可退金额(" + maxRefund + "分)");
        }
        // 3. 校验并清理扣款金额(根据订单类型)
        boolean isRemote = Constants.equalsInteger(order.getType(), Constants.ONE);
        Long depositShopDeduct = dto.getDepositShopDeduct();
        Long takeShopDeduct = dto.getTakeShopDeduct();
        Long driverDeduct = dto.getDriverDeduct();
        if (!isRemote) {
            takeShopDeduct = null;
            driverDeduct = null;
        } else {
            if (order.getTakeShopId() == null) {
                takeShopDeduct = null;
            }
        }
        if (depositShopDeduct != null && depositShopDeduct < 0) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "存件门店扣款金额不能为负");
        }
        if (takeShopDeduct != null && takeShopDeduct < 0) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "取件门店扣款金额不能为负");
        }
        if (driverDeduct != null && driverDeduct < 0) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "司机扣款金额不能为负");
        }
        // 4. 构建 deductInfo JSON
        String deductInfo = null;
        JSONObject deductJson = new JSONObject();
        if (depositShopDeduct != null) {
            deductJson.put("depositShopDeduct", depositShopDeduct);
        }
        if (takeShopDeduct != null) {
            deductJson.put("takeShopDeduct", takeShopDeduct);
        }
        if (driverDeduct != null) {
            deductJson.put("driverDeduct", driverDeduct);
        }
        if (deductJson.size() > 0) {
            deductInfo = deductJson.toJSONString();
        }
        // 5. 创建退款记录
        Date now = new Date();
        String outRefundNo = ID.nextGUID();
        OrdersRefund refund = new OrdersRefund();
        refund.setOrderId(order.getId());
        refund.setType(Constants.FOUR); // 手动退款
        refund.setRefundAmount(dto.getRefundAmount());
        refund.setDeductInfo(deductInfo);
        refund.setRefundRemark(dto.getRemark());
        refund.setUserId(userId);
        refund.setBeforeStatus(order.getStatus());
        refund.setRefundCode(outRefundNo);
        refund.setCreateTime(now);
        refund.setDeleted(Constants.ZERO);
        ordersRefundMapper.insert(refund);
        // 6. 调用微信退款
        try {
            Refund refundResult = wxPayV3Service.refund(
                    outRefundNo, order.getOutTradeNo(), payAmount, dto.getRefundAmount(),
                    "手动退款", wxPayProperties.getV3RefundNotifyUrl());
            com.wechat.pay.java.service.refund.model.Status refundStatus = refundResult.getStatus();
            if (com.wechat.pay.java.service.refund.model.Status.SUCCESS.equals(refundStatus)) {
                refund.setStatus(Constants.ONE);
                refund.setRefundTime(now);
                ordersRefundMapper.updateById(refund);
                // 退款成功,执行扣款
                processManualRefundDeduction(order, depositShopDeduct, takeShopDeduct, driverDeduct);
            } else if (com.wechat.pay.java.service.refund.model.Status.PROCESSING.equals(refundStatus)) {
                refund.setStatus(Constants.ZERO); // 退款中,等回调
                ordersRefundMapper.updateById(refund);
            } else {
                refund.setStatus(Constants.TWO);
                refund.setRefundRemark("微信退款失败: " + refundStatus.name());
                ordersRefundMapper.updateById(refund);
                throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "退款失败,请联系客服处理");
            }
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("手动退款调用微信退款异常, orderId={}", order.getId(), e);
            refund.setStatus(Constants.TWO);
            ordersRefundMapper.updateById(refund);
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "退款调用异常,请稍后重试");
        }
        // 7. 更新订单:标记已手动退款,累加退款金额
        ordersMapper.update(new UpdateWrapper<Orders>().lambda()
                .set(Orders::getManualRefund, Constants.ONE)
                .setSql(" REFUND_AMOUNT = IFNULL(REFUND_AMOUNT, 0) + " + dto.getRefundAmount())
                .set(Orders::getUpdateTime, now)
                .eq(Orders::getId, order.getId()));
    }
    /**
     * 手动退款成功后,根据扣款信息扣除对应方余额并生成收支记录
     */
    private void processManualRefundDeduction(Orders order, Long depositShopDeduct, Long takeShopDeduct, Long driverDeduct) {
        Date now = new Date();
        // 存件门店扣款
        if (depositShopDeduct != null && depositShopDeduct > 0 && order.getDepositShopId() != null) {
            ShopInfo depositShop = shopInfoMapper.selectById(order.getDepositShopId());
            if (depositShop != null) {
                shopInfoMapper.update(new UpdateWrapper<ShopInfo>().lambda()
                        .setSql(" BALANCE = IFNULL(BALANCE, 0) - " + depositShopDeduct)
                        .eq(ShopInfo::getId, depositShop.getId()));
                revenueMapper.insert(buildDeductRevenue(depositShop.getId(), Constants.TWO,
                        depositShopDeduct, order.getId(), order.getCode(), now));
            }
        }
        // 取件门店扣款
        if (takeShopDeduct != null && takeShopDeduct > 0 && order.getTakeShopId() != null) {
            ShopInfo takeShop = shopInfoMapper.selectById(order.getTakeShopId());
            if (takeShop != null) {
                shopInfoMapper.update(new UpdateWrapper<ShopInfo>().lambda()
                        .setSql(" BALANCE = IFNULL(BALANCE, 0) - " + takeShopDeduct)
                        .eq(ShopInfo::getId, takeShop.getId()));
                revenueMapper.insert(buildDeductRevenue(takeShop.getId(), Constants.TWO,
                        takeShopDeduct, order.getId(), order.getCode(), now));
            }
        }
        // 司机扣款
        if (driverDeduct != null && driverDeduct > 0 && order.getAcceptDriver() != null) {
            DriverInfo driver = driverInfoMapper.selectById(order.getAcceptDriver());
            if (driver != null && driver.getMemberId() != null) {
                driverInfoMapper.update(new UpdateWrapper<DriverInfo>().lambda()
                        .setSql(" BALANCE = IFNULL(BALANCE, 0) - " + driverDeduct)
                        .eq(DriverInfo::getId, driver.getId()));
                revenueMapper.insert(buildDeductRevenue(driver.getMemberId(), Constants.ONE,
                        driverDeduct, order.getId(), order.getCode(), now));
            }
        }
    }
    private Revenue buildDeductRevenue(Integer memberId, Integer memberType, Long amount, Integer orderId, String orderNo, Date now) {
        Revenue revenue = new Revenue();
        revenue.setMemberId(memberId);
        revenue.setMemberType(memberType);
        revenue.setType(Constants.FOUR); // 责任扣款
        revenue.setOptType(-Constants.ONE); // 支出
        revenue.setAmount(amount);
        revenue.setVaildStatus(Constants.ONE); // 已入账
        revenue.setObjId(orderId);
        revenue.setObjType(Constants.ZERO); // 订单业务
        revenue.setOrderNo(orderNo);
        revenue.setStatus(Constants.ZERO); // 成功
        revenue.setDeleted(Constants.ZERO);
        revenue.setCreateTime(now);
        return revenue;
    }
    @Override
    public void processManualRefundCallback(OrdersRefund refundRecord) {
        if (!Constants.equalsInteger(refundRecord.getType(), Constants.FOUR)) {
            return;
        }
        if (StringUtils.isBlank(refundRecord.getDeductInfo())) {
            return;
        }
        Orders order = ordersMapper.selectById(refundRecord.getOrderId());
        if (order == null) {
            return;
        }
        JSONObject deductJson = JSONObject.parseObject(refundRecord.getDeductInfo());
        Long depositShopDeduct = deductJson.getLong("depositShopDeduct");
        Long takeShopDeduct = deductJson.getLong("takeShopDeduct");
        Long driverDeduct = deductJson.getLong("driverDeduct");
        processManualRefundDeduction(order, depositShopDeduct, takeShopDeduct, driverDeduct);
        // 标记订单已手动退款,累加退款金额
        ordersMapper.update(new UpdateWrapper<Orders>().lambda()
                .set(Orders::getManualRefund, Constants.ONE)
                .setSql(" REFUND_AMOUNT = IFNULL(REFUND_AMOUNT, 0) + " + refundRecord.getRefundAmount())
                .set(Orders::getUpdateTime, new Date())
                .eq(Orders::getId, order.getId()));
    }
    /**
@@ -2258,6 +2587,10 @@
     * 发送司机站内信通知
     */
    private void sendDriverNotice(Integer driverId, Constants.DriverOrderNotify notify, Integer orderId, String... params) {
        sendDriverNotice(driverId, notify, orderId, 0, params);
    }
    private void sendDriverNotice(Integer driverId, Constants.DriverOrderNotify notify, Integer objId, Integer objType, String... params) {
        DriverInfo driver = driverInfoMapper.selectById(driverId);
        if (driver == null || driver.getMemberId() == null) {
            return;
@@ -2267,8 +2600,8 @@
        notice.setUserId(driver.getMemberId());
        notice.setTitle(notify.getTitle());
        notice.setContent(notify.format(params));
        notice.setObjId(orderId);
        notice.setObjType(0); // 0=订单
        notice.setObjId(objId);
        notice.setObjType(objType);
        notice.setStatus(0);  // 0=未读
        notice.setIsdeleted(Constants.ZERO);
        notice.setCreateDate(new Date());
@@ -2910,9 +3243,9 @@
            order.setMemberVerifyCode(generateVerifyCode());
            ordersMapper.updateById(order);
            // 寄存时图片必填
            if (images == null || images.isEmpty()) {
                throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "请上传寄存图片");
            }
//            if (images == null || images.isEmpty()) {
//                throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "请上传寄存图片");
//            }
            // 保存寄存图片(obj_type=2 订单寄存图片,最多3张)
            saveVerifyImages(order.getId(), images, Constants.FileType.ORDER_DEPOSIT.getKey(), shopId);
            // 记录订单日志
@@ -2948,7 +3281,8 @@
            }
            // 待取件(5) → 已完成(7)
            order.setStatus(Constants.OrderStatus.finished.getStatus());
            order.setConfirmArriveTime(now);
            order.setFinishTime(now);
            order.setInvoiceStatus(Constants.ONE);
            ordersMapper.updateById(order);
            // 就地寄存(type=0)取件时图片不必填,其他类型取件必填
            if (!Constants.equalsInteger(order.getType(), Constants.ZERO)) {
@@ -3096,6 +3430,30 @@
                sendOrderNotice(order.getMemberId(), Constants.MemberOrderNotify.WAIT_PICKUP_REMIND, order.getId(),
                        "orderNo", order.getCode(), "shopName", shopName);
            }
            // 异常订单寄存核销:标记原订单完成
            if (Constants.equalsInteger(order.getExceptionStatus(), Constants.ONE) && order.getRelationOrderId() != null) {
                Orders originalOrder = ordersMapper.selectById(order.getRelationOrderId());
                if (originalOrder != null) {
                    originalOrder.setStatus(Constants.OrderStatus.finished.getStatus());
                    originalOrder.setInvoiceStatus(Constants.ONE);
                    originalOrder.setFinishTime(now);
                    originalOrder.setUpdateTime(now);
                    ordersMapper.updateById(originalOrder);
                    // 触发原订单收益计算
                    calculateAndSaveOrderFees(originalOrder.getId());
                    generateRevenueRecords(originalOrder.getId());
                    // 通知会员:订单已完成
                    sendOrderNotice(originalOrder.getMemberId(), Constants.MemberOrderNotify.FINISHED, originalOrder.getId(),
                            "orderNo", originalOrder.getCode());
                    // 通知司机:订单已完成
                    if (originalOrder.getAcceptDriver() != null) {
                        String settleDays = operationConfigBiz.getConfig().getSettlementDate();
                        sendDriverNotice(originalOrder.getAcceptDriver(), Constants.DriverOrderNotify.FINISHED, originalOrder.getId(),
                                "orderNo", originalOrder.getCode(),
                                "settleDays", settleDays != null ? settleDays : "7");
                    }
                }
            }
        } else if (Constants.equalsInteger(status, Constants.OrderStatus.arrived.getStatus())) {
            // 异地寄存 + 无取件门店 → 无法核销(客户自取,无门店操作)
            if (Constants.equalsInteger(order.getType(), Constants.ONE) && order.getTakeShopId() == null) {
@@ -3115,6 +3473,7 @@
            }
            // 待取件(5) → 已完成(7)
            order.setStatus(Constants.OrderStatus.finished.getStatus());
            order.setInvoiceStatus(Constants.ONE);
            order.setConfirmArriveTime(now);
            ordersMapper.updateById(order);
            // 订单完成,释放核销码
@@ -3191,6 +3550,7 @@
        // 7. 更新订单状态为已完成
        Date now = new Date();
        order.setStatus(Constants.OrderStatus.finished.getStatus());
        order.setInvoiceStatus(Constants.ONE);
        order.setFinishTime(now);
        order.setUpdateTime(now);
        ordersMapper.updateById(order);
@@ -3280,10 +3640,15 @@
        if (!Constants.equalsInteger(order.getStatus(), Constants.OrderStatus.arrived.getStatus())) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "当前订单状态不允许确认收货");
        }
        // 5.1 校验异常状态
        if (Constants.equalsInteger(order.getExceptionStatus(), Constants.ONE)) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "订单异常,已被转存,请联系管理员或查看短信");
        }
        // 6. 更新订单状态为已完成
        Date now = new Date();
        order.setStatus(Constants.OrderStatus.finished.getStatus());
        order.setInvoiceStatus(Constants.ONE);
        order.setFinishTime(now);
        order.setUpdateTime(now);
        ordersMapper.updateById(order);
@@ -3320,7 +3685,6 @@
        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)
@@ -3336,8 +3700,7 @@
            driverFee = new BigDecimal(totalAmount)
                    .multiply(driverRate)
                    .setScale(0, RoundingMode.HALF_UP)
                    .longValue()
                    + exceptionFeeVal;
                    .longValue();
            // 异地寄存且有取件门店:加上取件门店收益
            if (order.getTakeShopId() != null) {
@@ -3396,6 +3759,91 @@
                        driverFee, orderId, order.getCode()));
            }
        }
        // 异常订单:司机异常补偿(异地 + 异常标记 + 有异常补偿金额)
        if (Constants.equalsInteger(order.getType(), Constants.ONE)
                && Constants.equalsInteger(order.getExceptionStatus(), Constants.ONE)
                && order.getExceptionFee() != null && order.getExceptionFee() > 0
                && order.getAcceptDriver() != null) {
            DriverInfo driver = driverInfoMapper.selectById(order.getAcceptDriver());
            if (driver != null && driver.getMemberId() != null) {
                Revenue exRevenue = new Revenue();
                exRevenue.setMemberId(driver.getMemberId());
                exRevenue.setMemberType(Constants.ONE); // 1=司机
                exRevenue.setType(5); // 5=异常金额
                exRevenue.setOptType(Constants.ONE); // 1=收入
                exRevenue.setAmount(order.getExceptionFee());
                exRevenue.setVaildStatus(Constants.ZERO);
                exRevenue.setObjId(orderId);
                exRevenue.setObjType(Constants.ZERO);
                exRevenue.setStatus(Constants.ZERO);
                exRevenue.setOrderNo(order.getCode());
                exRevenue.setDeleted(Constants.ZERO);
                exRevenue.setCreateTime(now);
                revenueMapper.insert(exRevenue);
            }
        }
        // 司机奖励金(仅生成奖励记录,不直接入账)
        generateDriverReward(order);
    }
    /**
     * 生成司机奖励记录
     * 规则:
     *   已奖励次数 < registerRewardOrderCount → 注册奖励(type=0, amount=registerRewardAmount)
     *   registerRewardOrderCount <= 已奖励次数 < (registerRewardOrderCount + platformRewardOrderCount) → 平台奖励(type=1, amount=platformRewardAmount)
     *   超出总名额不奖励
     */
    private void generateDriverReward(Orders order) {
        if (order.getAcceptDriver() == null) return;
        DriverInfo driver = driverInfoMapper.selectById(order.getAcceptDriver());
        if (driver == null || driver.getId() == null) return;
        // 读取奖励配置
        String registerCountStr = operationConfigBiz.getConfig().getRegisterRewardOrderCount();
        String registerAmountStr = operationConfigBiz.getConfig().getRegisterRewardAmount();
        String platformCountStr = operationConfigBiz.getConfig().getPlatformRewardOrderCount();
        String platformAmountStr = operationConfigBiz.getConfig().getPlatformRewardAmount();
        if (StringUtils.isAnyBlank(registerCountStr, registerAmountStr, platformCountStr, platformAmountStr)) return;
        int registerCount = Integer.parseInt(registerCountStr);
        long registerAmount = new BigDecimal(registerAmountStr).multiply(BigDecimal.valueOf(100)).longValue();
        int platformCount = Integer.parseInt(platformCountStr);
        long platformAmount = new BigDecimal(platformAmountStr).multiply(BigDecimal.valueOf(100)).longValue();
        int totalRewardSlots = registerCount + platformCount; // 总奖励名额
        // 查询司机已奖励次数
        Long rewarded = rewardRecordMapper.selectCount(new QueryWrapper<RewardRecord>().lambda()
                .eq(RewardRecord::getDriverId, driver.getId())
                .eq(RewardRecord::getDeleted, Constants.ZERO));
        int count = rewarded.intValue();
        if (count >= totalRewardSlots) return; // 已超出奖励名额
        // 判断本次奖励类型和金额
        int rewardType;
        long rewardAmount;
        if (count < registerCount) {
            // 注册奖励阶段
            rewardType = Constants.ZERO;
            rewardAmount = registerAmount;
        } else {
            // 平台奖励阶段
            rewardType = Constants.ONE;
            rewardAmount = platformAmount;
        }
        if (rewardAmount <= 0) return;
        // 创建奖励记录(状态=0待领取,后续由司机领取时入账)
        RewardRecord record = new RewardRecord();
        record.setOrderId(order.getId());
        record.setDriverId(driver.getId());
        record.setStatus(Constants.ZERO); // 0=待领取
        record.setType(rewardType);       // 0=注册奖励, 1=平台奖励
        record.setAmount(rewardAmount);
        record.setDeleted(Constants.ZERO);
        record.setCreateTime(new Date());
        rewardRecordMapper.insert(record);
    }
    /**
@@ -3558,9 +4006,57 @@
                        .eq(OrdersDetail::getOrderId, orderId)
                        .eq(OrdersDetail::getDeleted, Constants.ZERO));
        OverdueFeeVO overdueInfo = calculateOverdueFeeInternal(order, details);
        Date now = new Date();
        // 异常订单逾期逻辑
        if (Constants.equalsInteger(order.getExceptionStatus(), Constants.ONE)
                && order.getRelationOrderId() != null) {
            Orders originalOrder = ordersMapper.selectById(order.getRelationOrderId());
            long driverExceptionFee = (originalOrder != null && originalOrder.getExceptionFee() != null)
                    ? originalOrder.getExceptionFee() : 0L;
            long shopExceptionFee = order.getShopCompensationAmount() != null ? order.getShopCompensationAmount() : 0L;
            long totalExceptionFee = driverExceptionFee + shopExceptionFee;
            // 判断是否当天取件(按 expectedTakeTime 日期)
            boolean sameDay = isSameDay(now, order.getExpectedTakeTime());
            long overdueFee;
            int overdueDays;
            if (sameDay) {
                // 当天取件:逾期费用 = 异常费用总和
                overdueFee = totalExceptionFee;
                overdueDays = totalExceptionFee > 0 ? 1 : 0;
            } else {
                // 非当天取件:正常逾期计算 + 司机异常费用(不含门店异常费用)
                OverdueFeeVO normalOverdue = calculateOverdueFeeInternal(order, details);
                long normalFee = (normalOverdue != null && normalOverdue.getOverdueFee() != null)
                        ? normalOverdue.getOverdueFee() : 0L;
                overdueFee = normalFee + driverExceptionFee;
                overdueDays = (normalOverdue != null && normalOverdue.getOverdueDays() != null)
                        ? normalOverdue.getOverdueDays() : 0;
            }
            order.setConfirmArriveTime(now);
            order.setUpdateTime(now);
            if (overdueFee > 0) {
                order.setOverdueStatus(Constants.ONE);
                order.setOverdueDays(overdueDays);
                order.setOverdueAmount(overdueFee);
                ordersMapper.updateById(order);
                String overdueLogInfo = "门店【" + shopName + "】确认顾客到店,逾期" + overdueDays
                        + "天,逾期费用" + Constants.getFormatMoney(overdueFee) + "元";
                saveShopVerifyLog(order, Constants.OrderLogType.shopConfirmArriveOverdue, overdueLogInfo, null, shopId);
            } else {
                order.setOverdueStatus(Constants.ZERO);
                ordersMapper.updateById(order);
                saveShopVerifyLog(order, Constants.OrderLogType.shopConfirmArrive,
                        "门店【" + shopName + "】确认顾客到店,未逾期", null, shopId);
            }
            return;
        }
        // 普通订单逾期计算
        OverdueFeeVO overdueInfo = calculateOverdueFeeInternal(order, details);
        if (overdueInfo.getOverdue() && overdueInfo.getOverdueDays() > 0) {
            // 存在逾期:标记逾期状态,订单保持当前状态
@@ -3890,6 +4386,16 @@
        long diffMs = nowCal.getTimeInMillis() - depositCal.getTimeInMillis();
        int days = (int) (diffMs / (1000 * 60 * 60 * 24));
        return Math.max(days, 1);
    }
    private boolean isSameDay(Date d1, Date d2) {
        if (d1 == null || d2 == null) return false;
        Calendar c1 = Calendar.getInstance();
        c1.setTime(d1);
        Calendar c2 = Calendar.getInstance();
        c2.setTime(d2);
        return c1.get(Calendar.YEAR) == c2.get(Calendar.YEAR)
                && c1.get(Calendar.DAY_OF_YEAR) == c2.get(Calendar.DAY_OF_YEAR);
    }
    /**
@@ -4229,6 +4735,7 @@
                // 更新订单状态为已完成
                order.setStatus(Constants.OrderStatus.finished.getStatus());
                order.setInvoiceStatus(Constants.ONE);
                order.setFinishTime(now);
                order.setUpdateTime(now);
                ordersMapper.updateById(order);
@@ -4450,6 +4957,9 @@
        Date now = new Date();
        Date threshold = new Date(now.getTime() + (long) minutes * 60 * 1000);
        // 查询:status=5、未通知、就地寄存 or 异地(有取件门店)、预计取件时间在 now~threshold 之间
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String nowStr = sdf.format(now);
        String thresholdStr = sdf.format(threshold);
        List<Orders> orders = ordersMapper.selectList(new QueryWrapper<Orders>().lambda()
                .eq(Orders::getStatus, Constants.OrderStatus.arrived.getStatus())
                .eq(Orders::getPayStatus, Constants.ONE)
@@ -4460,8 +4970,8 @@
                )
                .ne(Orders::getPickUpNotifyStatus, Constants.ONE)
                .isNotNull(Orders::getExpectedTakeTime)
                .ge(Orders::getExpectedTakeTime, now)
                .le(Orders::getExpectedTakeTime, threshold));
                .apply("DATE_FORMAT(EXPECTED_TAKE_TIME, '%Y-%m-%d %H:%i:%s') >= {0}", nowStr)
                .apply("DATE_FORMAT(EXPECTED_TAKE_TIME, '%Y-%m-%d %H:%i:%s') <= {0}", thresholdStr));
        if (orders == null || orders.isEmpty()) {
            return 0;
        }
@@ -4558,4 +5068,235 @@
        return distanceKm * 1000 <= radiusM;
    }
    @Override
    @Transactional(rollbackFor = {Exception.class, BusinessException.class})
    public void handleOrderException(HandleOrderExceptionDTO dto) {
        // ========== A. 校验 ==========
        Orders original = ordersMapper.selectById(dto.getOrderId());
        if (original == null || Constants.equalsInteger(original.getDeleted(), Constants.ONE)) {
            throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "订单不存在");
        }
        if (!Constants.equalsInteger(original.getType(), Constants.ONE)) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "仅支持异地订单异常处理");
        }
        if (original.getTakeShopId() != null) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "该订单已关联取件门店,不支持异常处理");
        }
        if (!Constants.equalsInteger(original.getStatus(), Constants.FIVE)) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "仅支持已送达状态的订单");
        }
        if (Constants.equalsInteger(original.getExceptionStatus(), Constants.ONE)) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "该订单已处理过异常,请勿重复操作");
        }
        ShopInfo newShop = shopInfoMapper.selectById(dto.getDepositShopId());
        if (newShop == null || Constants.equalsInteger(newShop.getStatus(), Constants.ONE)) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "存放门店不存在或已禁用");
        }
        Date now = new Date();
        // ========== B. 创建新订单(就地存取) ==========
        String orderCode = "JC" + new java.text.SimpleDateFormat("yyyyMMddHHmmss").format(now)
                + String.format("%04d", new java.util.Random().nextInt(10000));
        String orderTradeNo = generateOrderTradeNo();
        // 当天23:30
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 30);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        Date expectedTakeTime = cal.getTime();
        // 计算基础单价
        Long price = 0L;
        Long basicAmount = 0L;
        // 查询原订单明细获取物品列表
        List<OrdersDetail> originalDetails = ordersDetailMapper.selectList(
                new QueryWrapper<OrdersDetail>().lambda()
                        .eq(OrdersDetail::getOrderId, original.getId())
                        .eq(OrdersDetail::getDeleted, Constants.ZERO));
        if (!CollectionUtils.isEmpty(originalDetails)) {
            CalculateLocalPriceDTO priceDTO = new CalculateLocalPriceDTO();
            priceDTO.setCityId(Integer.valueOf(original.getCityId()));
            priceDTO.setDepositStartTime(now);
            priceDTO.setDepositEndTime(expectedTakeTime);
            List<OrderItemDTO> items = new ArrayList<>();
            for (OrdersDetail d : originalDetails) {
                OrderItemDTO item = new OrderItemDTO();
                item.setCategoryId(d.getLuggageId());
                item.setQuantity(d.getNum());
                items.add(item);
            }
            priceDTO.setItems(items);
            PriceCalculateVO priceResult = calculateLocalPrice(priceDTO);
            if (priceResult != null) {
                price = priceResult.getItemPrice();
                basicAmount = priceResult.getItemPrice();
            }
        }
        // 存件门店分成占比(就地存取)
        Integer cityId = Integer.valueOf(original.getCityId());
        boolean isCompany = Constants.equalsInteger(newShop.getCompanyType(), Constants.ONE);
        int fallbackFieldA = isCompany ? Constants.FIVE : Constants.SIX;
        BigDecimal depositShopFeeRate = getShopRevenueShare(newShop, "localDeposit", cityId, fallbackFieldA);
        Orders newOrder = new Orders();
        newOrder.setCode(orderCode);
        newOrder.setOutTradeNo(orderTradeNo);
        newOrder.setMemberId(original.getMemberId());
        newOrder.setType(Constants.ZERO); // 就地存取
        newOrder.setCityId(original.getCityId());
        newOrder.setStatus(Constants.ONE); // 待寄存
        newOrder.setPayStatus(Constants.ONE); // 已支付
        newOrder.setPayTime(now);
        newOrder.setCommentStatus(Constants.ZERO);
        newOrder.setSettlementStatus(Constants.ZERO);
        newOrder.setDeleted(Constants.ZERO);
        newOrder.setCreateTime(now);
        newOrder.setUpdateTime(now);
        newOrder.setIsConverted(Constants.ZERO);
        // 存件信息(入参门店)
        newOrder.setDepositShopId(dto.getDepositShopId());
        newOrder.setDepositLocation(newShop.getAddress());
        newOrder.setDepositLocationRemark(newShop.getAddress());
        newOrder.setDepositLat(BigDecimal.valueOf(newShop.getLatitude()));
        newOrder.setDepositLgt(BigDecimal.valueOf(newShop.getLongitude()));
        // 取件信息(就地=存件门店)
        newOrder.setTakeShopId(dto.getDepositShopId());
        newOrder.setTakeLocation(newShop.getAddress());
        newOrder.setTakeLocationRemark(newShop.getAddress());
        newOrder.setTakeLat(BigDecimal.valueOf(newShop.getLatitude()));
        newOrder.setTakeLgt(BigDecimal.valueOf(newShop.getLongitude()));
        // 时间
        newOrder.setExpectedDepositTime(now);
        newOrder.setExpectedTakeTime(expectedTakeTime);
        newOrder.setEstimatedDepositDays(1);
        // 物品信息
        newOrder.setGoodType(original.getGoodType());
        newOrder.setGoodLevel(original.getGoodLevel());
        newOrder.setGoodsInfo(original.getGoodsInfo());
        newOrder.setSupplement(original.getSupplement());
        newOrder.setSelfTake(original.getSelfTake());
        newOrder.setTakeUser(original.getTakeUser());
        newOrder.setTakePhone(original.getTakePhone());
        // 异常标记
        newOrder.setExceptionStatus(Constants.ONE);
        newOrder.setRelationOrderId(original.getId());
        newOrder.setExceptionInfo(dto.getRemark());
        // 费用
        newOrder.setIsUrgent(Constants.ZERO);
        newOrder.setUrgentRata(BigDecimal.ONE);
        newOrder.setUrgentAmount(0L);
        newOrder.setDeclaredAmount(0L);
        newOrder.setDeclaredFee(0L);
        newOrder.setPrice(price);
        newOrder.setBasicAmount(basicAmount);
        newOrder.setEstimatedAmount(basicAmount);
        newOrder.setTotalAmount(0L);
        newOrder.setPayAmount(0L);
        newOrder.setManualRefund(Constants.ZERO);
        // 费用分配
        newOrder.setDriverFee(0L);
        newOrder.setDriverFeeRata(BigDecimal.ZERO);
        newOrder.setDepositShopFee(0L);
        newOrder.setDepositShopFeeRata(depositShopFeeRate);
        newOrder.setTakeShopFee(0L);
        newOrder.setTakeShopFeeRata(BigDecimal.ZERO);
        // 门店补偿金额
        newOrder.setShopCompensationAmount(dto.getShopCompensation());
        newOrder.setRemark(dto.getRemark());
        newOrder.setPlatformSmsNotified(Constants.ZERO);
        newOrder.setMemberVerifyCode(generateVerifyCode());
        newOrder.setDriverVerifyCode(generateVerifyCode());
        // 计算店铺订单序号
        Date todayStart = DateUtil.getStartOfDay(now);
        Long currentCount = ordersMapper.selectCount(new QueryWrapper<Orders>().lambda()
                .eq(Orders::getDepositShopId, dto.getDepositShopId())
                .eq(Orders::getPayStatus, Constants.ONE)
                .ge(Orders::getPayTime, todayStart)
                .eq(Orders::getDeleted, Constants.ZERO));
        newOrder.setAutoNum(currentCount + 1);
        ordersMapper.insert(newOrder);
        // ========== C. 创建新订单明细 ==========
        if (!CollectionUtils.isEmpty(originalDetails)) {
            for (OrdersDetail od : originalDetails) {
                OrdersDetail detail = new OrdersDetail();
                detail.setOrderId(newOrder.getId());
                detail.setLuggageId(od.getLuggageId());
                detail.setLuggageName(od.getLuggageName());
                detail.setLuggageDetail(od.getLuggageDetail());
                detail.setNum(od.getNum());
                detail.setUnitPrice(od.getLocallyPrice());
                detail.setLocallyPrice(od.getLocallyPrice());
                detail.setDeleted(Constants.ZERO);
                detail.setCreateTime(now);
                ordersDetailMapper.insert(detail);
            }
        }
        // ========== D. 拷贝附件 ==========
        List<Multifile> originalFiles = multifileMapper.selectList(
                new QueryWrapper<Multifile>().lambda()
                        .eq(Multifile::getObjId, original.getId())
                        .eq(Multifile::getObjType, Constants.FileType.ORDER_FILE.getKey())
                        .eq(Multifile::getIsdeleted, Constants.ZERO));
        if (!CollectionUtils.isEmpty(originalFiles)) {
            int sortNum = 1;
            for (Multifile mf : originalFiles) {
                Multifile newFile = new Multifile();
                newFile.setObjId(newOrder.getId());
                newFile.setObjType(Constants.FileType.ORDER_FILE.getKey());
                newFile.setType(mf.getType());
                newFile.setFileurl(mf.getFileurl());
                newFile.setIsdeleted(Constants.ZERO);
                newFile.setCreateDate(now);
                newFile.setSortnum(sortNum++);
                multifileMapper.insert(newFile);
            }
        }
        // ========== E. 更新原订单 ==========
        ordersMapper.update(new UpdateWrapper<Orders>().lambda()
                .set(Orders::getExceptionStatus, Constants.ONE)
                .set(Orders::getExceptionFee, dto.getDriverCompensation())
                .set(Orders::getUpdateTime, now)
                .eq(Orders::getId, original.getId()));
        // ========== F. 发送短信通知 ==========
        // 司机端-异常派单
        if (original.getAcceptDriver() != null) {
            DriverInfo driver = driverInfoMapper.selectById(original.getAcceptDriver());
            if (driver != null && StringUtils.isNotBlank(driver.getTelephone())) {
                sendSmsNotify(driver.getTelephone(), Constants.SmsNotify.EXCEPTION_DISPATCH,
                        "orderNo", original.getCode(),
                        "address", newShop.getAddress(),
                        "code", newOrder.getMemberVerifyCode());
            }
        }
        // 会员端-异常派单
        String memberPhone = StringUtils.isNotBlank(original.getTakePhone()) ? original.getTakePhone() : null;
        if (memberPhone == null) {
            Member member = memberMapper.selectById(original.getMemberId());
            if (member != null) {
                memberPhone = member.getTelephone();
            }
        }
        if (StringUtils.isNotBlank(memberPhone)) {
            sendSmsNotify(memberPhone, Constants.SmsNotify.MEMBER_EXCEPTION_DISPATCH,
                    "address", newShop.getAddress());
        }
    }
}