MrShi
7 小时以前 59bfd0b8bbbf0ee94ec68e4a3a1a6e536d0ad8fd
server/services/src/main/java/com/doumee/service/business/impl/OrdersServiceImpl.java
@@ -133,6 +133,8 @@
    @Autowired
    private MemberCouponMapper memberCouponMapper;
    @Autowired
    private CouponMapper couponMapper;
    @Autowired
    private AreasBiz areasBiz;
@@ -662,7 +664,7 @@
                .le(MemberCoupon::getLimitPrice, totalPrice)
                .ge(MemberCoupon::getEndDate, now)
                .orderByDesc(MemberCoupon::getPrice)
                .orderByAsc(MemberCoupon::getEndDate));
                .orderByAsc(MemberCoupon::getCreateDate));
        result.setAvailableCoupons(availableCoupons);
        if (couponId == null) {
@@ -1151,6 +1153,11 @@
        if (Objects.isNull(order)) {
            throw new BusinessException(ResponseStatus.DATA_EMPTY);
        }
        // 实付金额 = 支付金额 - 退款金额 + 逾期费用
        long pay = order.getPayAmount() != null ? order.getPayAmount() : 0L;
        long refund = order.getRefundAmount() != null ? order.getRefundAmount() : 0L;
        long overdue = order.getOverdueAmount() != null ? order.getOverdueAmount() : 0L;
        order.setPayAmount(pay - refund + overdue);
        OrderDetailVO vo = new OrderDetailVO();
        vo.setOrder(order);
@@ -1217,6 +1224,25 @@
            for (OrderItemVO v:vo.getDetailList()) {
                v.setTypeName(category.getName());
            }
        }
        // 评价信息
        List<OrderComment> comments = orderCommentMapper.selectList(new QueryWrapper<OrderComment>().lambda()
                .eq(OrderComment::getOrderId, id)
                .eq(OrderComment::getDeleted, Constants.ZERO));
        if (CollectionUtils.isNotEmpty(comments)) {
            for (OrderComment c : comments) {
                if (Constants.equalsInteger(c.getTargetType(), Constants.ONE)) {
                    vo.setDepositScore(c.getScore());
                } else if (Constants.equalsInteger(c.getTargetType(), Constants.TWO)) {
                    vo.setTakeScore(c.getScore());
                } else if (Constants.equalsInteger(c.getTargetType(), Constants.THREE)) {
                    vo.setDriverScore(c.getScore());
                }
            }
            vo.setCommentContent(comments.get(0).getContent());
            vo.setCommentTime(comments.get(0).getCreateTime());
            vo.setCommentImages(getFileUrls(id, Constants.FileType.COMMENT_ATTACH.getKey(), imgPrefix));
        }
        // 取消/退款状态时查询退款记录
@@ -1655,7 +1681,8 @@
                cal.set(Calendar.MINUTE, 0);
                cal.set(Calendar.SECOND, 0);
                cal.set(Calendar.MILLISECOND, 0);
                wrapper.ge(Orders::getFinishTime, cal.getTime());
                wrapper.ge(Orders::getFinishTime, cal.getTime())
                        .eq(Orders::getStatus, Constants.OrderStatus.finished.getKey());
            }
        }
        // 关键词搜索:收件人/收件人电话模糊、订单号精准
@@ -1737,6 +1764,8 @@
                fillOverdueStatus(vo, o, details);
                // 优惠券抵扣金额
                vo.setDeductionAmount(o.getDeductionAmount());
                // 异常订单标识
                vo.setAbnormalOrder(o.getExceptionStatus());
                // 可开票金额(支付金额 - 退款金额)
                if (model != null && model.getInvoiceStatus() != null && Constants.equalsInteger(model.getInvoiceStatus(), Constants.ONE)) {
                    long payAmt = o.getPayAmount() != null ? o.getPayAmount() : 0L;
@@ -1815,7 +1844,7 @@
                    .or(w3-> w3.eq(Orders::getType, Constants.ONE).eq(Orders::getDepositShopId, shopId)
                            .eq(Orders::getStatus, Constants.OrderStatus.waitDeposit.getStatus()))
                    .or(w2 -> w2.eq(Orders::getType, Constants.ONE).eq(Orders::getTakeShopId, shopId)
                            .eq(Orders::getStatus, Constants.OrderStatus.arrived.getStatus())))
                            .in(Orders::getStatus, Constants.OrderStatus.arrived.getStatus(),Constants.OrderStatus.delivering.getStatus())))
            );
        } else {
            wrapper.and(w -> w.eq(Orders::getDepositShopId, shopId).or().eq(Orders::getTakeShopId, shopId));
@@ -1975,6 +2004,7 @@
        vo.setUrgentAmount(order.getUrgentAmount());
        vo.setIsUrgent(order.getIsUrgent());
        vo.setActualPayAmount(Constants.equalsInteger(order.getPayStatus(), Constants.ONE)?order.getPayAmount():order.getEstimatedAmount());
        vo.setDeductionAmount(order.getDeductionAmount());
        // 标记
        vo.setExceptionStatus(order.getExceptionStatus());
@@ -1988,13 +2018,12 @@
            vo.setPayCountdownMs(calcPayCountdownMs(order));
        }
        //序号
        vo.setSortnum(Constants.formatIntegerNum(order.getDepositShopId())+"-"+order.getId());
        if(order.getTakeShopId()!=null){
            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);
        }
//        vo.setSortnum(Constants.formatIntegerNum(order.getDepositShopId())+"-"+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.getDepositShopId() + "-" + dateStr + "-" + autoNumStr;
        vo.setSortnum(sort);
        vo.setDepositShopId(order.getDepositShopId());
        // 存件门店
        if (order.getDepositShopId() != null) {
            ShopInfo depositShop = shopInfoMapper.selectById(order.getDepositShopId());
@@ -2282,16 +2311,71 @@
     * 保存取消订单操作日志
     */
    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()));
        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 giftOrderCoupon(Integer memberId) {
        String orderCountStr = operationConfigBiz.getConfig().getOrderCouponOrderCount();
        String giftCountStr = operationConfigBiz.getConfig().getOrderCouponGiftCount();
        String couponIdsStr = operationConfigBiz.getConfig().getOrderCouponId();
        if (StringUtils.isAnyBlank(orderCountStr, giftCountStr, couponIdsStr)) return;
        int orderCount = Integer.parseInt(orderCountStr);
        int maxGift = Integer.parseInt(giftCountStr);
        Member member = memberMapper.selectById(memberId);
        if (member == null) return;
        int gifted = member.getOrderCouponGiftCount() != null ? member.getOrderCouponGiftCount() : 0;
        if (gifted >= maxGift) return;
        long completedCount = ordersMapper.selectCount(new QueryWrapper<Orders>().lambda()
                .eq(Orders::getMemberId, memberId)
                .eq(Orders::getDeleted, Constants.ZERO)
                .notIn(Orders::getStatus,
                        Constants.OrderStatus.waitPay.getKey(),
                        Constants.OrderStatus.waitDeposit.getKey()));
        if (completedCount < orderCount || completedCount % orderCount != 0) return;
        String[] idArr = couponIdsStr.split(",");
        Date now = new Date();
        for (String idStr : idArr) {
            String trimmed = idStr.trim();
            if (StringUtils.isBlank(trimmed)) continue;
            Coupon coupon = couponMapper.selectById(Integer.valueOf(trimmed));
            if (coupon == null || Constants.equalsInteger(coupon.getIsdeleted(), Constants.ONE)) continue;
            MemberCoupon mc = new MemberCoupon();
            mc.setCouponId(coupon.getId());
            mc.setMemberId(memberId);
            mc.setStatus(Constants.CouponStatus.waitClaim.getKey());
            Calendar validCal = Calendar.getInstance();
            validCal.add(Calendar.DAY_OF_MONTH, coupon.getPushDays() != null ? coupon.getPushDays() : 7);
            mc.setValidDate(validCal.getTime());
            mc.setName(coupon.getName());
            mc.setInfo(coupon.getInfo());
            mc.setType(coupon.getType());
            mc.setLimitPrice(coupon.getLimitPrice());
            mc.setPrice(coupon.getPrice());
            mc.setGetMethod(coupon.getGetMethod());
            mc.setCouponType(coupon.getCouponType());
            mc.setPushDays(coupon.getPushDays());
            mc.setValidDays(coupon.getValidDays());
            mc.setIsdeleted(Constants.ZERO);
            mc.setCreateDate(now);
            mc.setEditDate(now);
            memberCouponMapper.insert(mc);
        }
        member.setOrderCouponGiftCount(gifted + 1);
        memberMapper.updateById(member);
    }
    private void saveCancelLog(Orders order, Constants.OrderLogType logType, String reason, Integer memberId) {
@@ -2406,7 +2490,7 @@
                refund.setRefundTime(now);
                ordersRefundMapper.updateById(refund);
                // 退款成功,执行扣款
                processManualRefundDeduction(order, depositShopDeduct, takeShopDeduct, driverDeduct);
                //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);
@@ -2428,7 +2512,6 @@
        // 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()));
    }
@@ -2511,10 +2594,11 @@
        Long driverDeduct = deductJson.getLong("driverDeduct");
        processManualRefundDeduction(order, depositShopDeduct, takeShopDeduct, driverDeduct);
        // 标记订单已手动退款,累加退款金额
        // 标记订单已手动退款,累加退款金额,同步更新totalAmount
        ordersMapper.update(new UpdateWrapper<Orders>().lambda()
                .set(Orders::getManualRefund, Constants.ONE)
                .setSql(" REFUND_AMOUNT = IFNULL(REFUND_AMOUNT, 0) + " + refundRecord.getRefundAmount())
                .setSql(" TOTAL_AMOUNT = IFNULL(TOTAL_AMOUNT, 0) - " + refundRecord.getRefundAmount())
                .set(Orders::getUpdateTime, new Date())
                .eq(Orders::getId, order.getId()));
    }
@@ -3262,6 +3346,8 @@
                sendOrderNotice(order.getMemberId(), Constants.MemberOrderNotify.WAIT_PICKUP_REMIND, order.getId(),
                        "orderNo", order.getCode(), "shopName", shopName);
            }
            // 寄存成功赠送优惠券
            giftOrderCoupon(order.getMemberId());
        } else if (Constants.equalsInteger(status, Constants.OrderStatus.arrived.getStatus())) {
            // 异地寄存 + 无取件门店 → 无法核销(客户自取,无门店操作)
            if (Constants.equalsInteger(order.getType(), Constants.ONE) && order.getTakeShopId() == null) {
@@ -3881,14 +3967,16 @@
            throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "核销码无效");
        }
        // 仅异地寄存 + 有取件门店 + 派送中(4) 可核销
        if (!Constants.equalsInteger(order.getType(), Constants.ONE)) {
        // 仅异地寄存 + 有取件门店 + 派送中(4) 可核销(异常订单允许)
        if (!Constants.equalsInteger(order.getType(), Constants.ONE)
                && !Constants.equalsInteger(order.getExceptionStatus(), Constants.ONE)) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "仅异地寄存订单支持司机核销");
        }
        if (order.getTakeShopId() == null) {
        if (order.getTakeShopId() == null && !Constants.equalsInteger(order.getExceptionStatus(), Constants.ONE)) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "该订单无取件门店,无需司机核销");
        }
        if (!Constants.equalsInteger(order.getStatus(), Constants.OrderStatus.delivering.getStatus())) {
        if (!Constants.equalsInteger(order.getStatus(), Constants.OrderStatus.delivering.getStatus())
                && !Constants.equalsInteger(order.getStatus(), Constants.OrderStatus.deposited.getStatus())) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "当前订单状态不允许核销");
        }
@@ -4601,7 +4689,7 @@
                    sendSmsNotify(member != null ? member.getTelephone() : null,
                            Constants.SmsNotify.MEMBER_CANCELLED, "orderNo", order.getCode());
                }
                restoreCoupon(order);
                count++;
            } catch (Exception e) {
                log.error("取消超时订单异常, orderId={}, error={}", order.getId(), e.getMessage());
@@ -5019,29 +5107,26 @@
                }
                targetLat = order.getDepositLat();
                targetLgt = order.getDepositLgt();
            } else if (Constants.equalsInteger(order.getStatus(), Constants.OrderStatus.arrived.getStatus())) {
                // status=5 门店完成核销
                if (Constants.equalsInteger(order.getType(), Constants.ZERO)) {
                    // 就地存取 → 对比存件门店
                    if (!Constants.equalsInteger(order.getDepositShopId(), userId)) {
                        throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "无权操作该订单");
                    }
                    targetLat = order.getDepositLat();
                    targetLgt = order.getDepositLgt();
                } else {
                    // 异地存取 → 对比取件门店
                    if (!Constants.equalsInteger(order.getTakeShopId(), userId)) {
                        throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "无权操作该订单");
                    }
                    targetLat = order.getTakeLat();
                    targetLgt = order.getTakeLgt();
            } else if (Constants.equalsInteger(order.getStatus(), Constants.OrderStatus.arrived.getStatus())&&Constants.equalsInteger(order.getType(), Constants.ZERO)) {
                // 就地存取 → 对比存件门店
                if (!Constants.equalsInteger(order.getDepositShopId(), userId)) {
                    throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "无权操作该订单");
                }
                targetLat = order.getDepositLat();
                targetLgt = order.getDepositLgt();
            } else if ((Constants.equalsInteger(order.getStatus(), Constants.OrderStatus.delivering.getStatus())||Constants.equalsInteger(order.getStatus(), Constants.OrderStatus.arrived.getStatus()))&&Constants.equalsInteger(order.getType(), Constants.ONE)) {
                // 异地存取 → 对比取件门店
                if (!Constants.equalsInteger(order.getTakeShopId(), userId)) {
                    throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "无权操作该订单");
                }
                targetLat = order.getTakeLat();
                targetLgt = order.getTakeLgt();
            } else {
                throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "订单状态不允许此操作");
            }
        } else if (Constants.equalsInteger(userType, Constants.ONE)) {
            // 司机操作
            if (Constants.equalsInteger(order.getStatus(), Constants.OrderStatus.deposited.getStatus())) {
            if (Constants.equalsInteger(order.getStatus(), Constants.OrderStatus.accepted.getStatus())) {
                // status=2 司机取件
                if (!Constants.equalsInteger(order.getAcceptDriver(), userId)) {
                    throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "无权操作该订单");
@@ -5082,8 +5167,8 @@
        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.getStatus(), Constants.OrderStatus.delivering.getKey())) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "仅支持配送中的订单进行异常处理");
        }
        if (Constants.equalsInteger(original.getExceptionStatus(), Constants.ONE)) {
            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "该订单已处理过异常,请勿重复操作");
@@ -5299,4 +5384,27 @@
        }
    }
    @Override
    public ManualRefundDetailVO getManualRefundDetail(Integer orderId) {
        OrdersRefund refundRecord = ordersRefundMapper.selectOne(new QueryWrapper<OrdersRefund>().lambda()
                .eq(OrdersRefund::getOrderId, orderId)
                .eq(OrdersRefund::getType, Constants.FOUR)
                .eq(OrdersRefund::getDeleted, Constants.ZERO)
                .orderByDesc(OrdersRefund::getCreateTime)
                .last("limit 1"));
        if (refundRecord == null) {
            throw new BusinessException(ResponseStatus.DATA_EMPTY);
        }
        ManualRefundDetailVO vo = new ManualRefundDetailVO();
        vo.setRefundAmount(refundRecord.getRefundAmount());
        if (StringUtils.isNotBlank(refundRecord.getDeductInfo())) {
            JSONObject json = JSONObject.parseObject(refundRecord.getDeductInfo());
            vo.setDepositShopDeduct(json.getLong("depositShopDeduct"));
            vo.setTakeShopDeduct(json.getLong("takeShopDeduct"));
            vo.setDriverDeduct(json.getLong("driverDeduct"));
        }
        vo.setRefundRemark(refundRecord.getRefundRemark());
        return vo;
    }
}