| | |
| | | |
| | | @Autowired |
| | | private MemberCouponMapper memberCouponMapper; |
| | | @Autowired |
| | | private CouponMapper couponMapper; |
| | | |
| | | @Autowired |
| | | private AreasBiz areasBiz; |
| | |
| | | .selectAll(Orders.class) |
| | | .selectAs(Category::getDetail, Orders::getOrderLevel) |
| | | .select("s1.name", Orders::getDepositShopName) |
| | | .leftJoin(Category.class, Category::getId, Orders::getGoodType) |
| | | .select("o2.code", Orders::getRelationOrderCode) |
| | | .leftJoin(Category.class, Category::getId, Orders::getGoodLevel) |
| | | .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") |
| | | .leftJoin("orders o2 on o2.id = t.RELATION_ORDER_ID") |
| | | ; |
| | | Utils.MP.blankToNull(pageWrap.getModel()); |
| | | queryWrapper.eq(pageWrap.getModel().getDeleted() != null, Orders::getDeleted, pageWrap.getModel().getDeleted()); |
| | |
| | | } |
| | | |
| | | /** |
| | | * 计算就地存取预估费用 |
| | | * 计算就地寄存预估费用 |
| | | * |
| | | * 计算规则: |
| | | * 1. 根据城市+物品类型 查询 pricing_rule(type=0),fieldA=categoryId, fieldB=单价(分/天) |
| | |
| | | * 4. 保价费用 = 报价金额 × 保价费率(字典 INSURANCE_RATE),元转分 |
| | | * 5. 总价格 = 物品价格 + 保价费用 |
| | | * |
| | | * @param dto 就地存取计价请求参数 |
| | | * @param dto 就地寄存计价请求参数 |
| | | * @return 价格计算结果 |
| | | */ |
| | | @Override |
| | |
| | | } |
| | | |
| | | /** |
| | | * 计算异地存取预估费用 |
| | | * 计算同城寄送预估费用 |
| | | * |
| | | * 计算规则: |
| | | * 1. 调用腾讯地图API计算寄件点与取件点的驾车距离(米→公里) |
| | |
| | | * 7. 加急费用 = 物品价格 × 加急系数(字典 URGENT_COEFFICIENT) |
| | | * 8. 总价格 = 物品价格 + 保价费用 + 加急费用 |
| | | * |
| | | * @param dto 异地存取计价请求参数 |
| | | * @param dto 同城寄送计价请求参数 |
| | | * @return 价格计算结果 |
| | | */ |
| | | @Override |
| | |
| | | ruleMap.put(r.getFieldA(), r); |
| | | } |
| | | |
| | | // 查询就地存取计价规则 pricing_rule type=0,用于获取 locallyPrice |
| | | // 查询就地寄存计价规则 pricing_rule type=0,用于获取 locallyPrice |
| | | List<PricingRule> localRules = pricingRuleMapper.selectList(new QueryWrapper<PricingRule>().lambda() |
| | | .eq(PricingRule::getDeleted, Constants.ZERO) |
| | | .eq(PricingRule::getType, Constants.ZERO) |
| | |
| | | |
| | | long subtotal = unitPrice * item.getQuantity(); |
| | | |
| | | // 就地存取单价 |
| | | // 就地寄存单价 |
| | | PricingRule localRule = localRuleMap.get(String.valueOf(item.getCategoryId())); |
| | | Long locallyPrice = localRule != null ? Long.parseLong(localRule.getFieldB()) : null; |
| | | |
| | |
| | | .le(MemberCoupon::getLimitPrice, totalPrice) |
| | | .ge(MemberCoupon::getEndDate, now) |
| | | .orderByDesc(MemberCoupon::getPrice) |
| | | .orderByAsc(MemberCoupon::getEndDate)); |
| | | .orderByAsc(MemberCoupon::getCreateDate)); |
| | | result.setAvailableCoupons(availableCoupons); |
| | | |
| | | if (couponId == null) { |
| | |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "请选择取件店铺或输入自选取件地址"); |
| | | } |
| | | } else { |
| | | // 就地存取:取件门店同寄件门店 |
| | | // 就地寄存:取件门店同寄件门店 |
| | | takeShop = depositShop; |
| | | } |
| | | |
| | |
| | | orders.setPayStatus(Constants.ZERO); // 未支付 |
| | | orders.setCommentStatus(Constants.ZERO); // 未评价 |
| | | orders.setSettlementStatus(Constants.ZERO); // 未结算 |
| | | orders.setExceptionStatus(Constants.ZERO); // 非异常 |
| | | orders.setDeleted(Constants.ZERO); |
| | | orders.setCreateTime(now); |
| | | orders.setUpdateTime(now); |
| | |
| | | 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); |
| | |
| | | } |
| | | } |
| | | |
| | | // 评价信息 |
| | | 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)); |
| | | } |
| | | |
| | | // 取消/退款状态时查询退款记录 |
| | | Integer status = order.getStatus(); |
| | | if (status != null && (status == Constants.OrderStatus.overdue.getStatus() |
| | |
| | | vo.setCode(order.getCode()); |
| | | vo.setPayAmountYuan(order.getPayAmount() != null ? Constants.getFormatMoney(order.getPayAmount()) : 0); |
| | | vo.setType(order.getType()); |
| | | vo.setTypeDesc(order.getType() != null && order.getType() == Constants.ONE ? "异地存取" : "就地存取"); |
| | | vo.setTypeDesc(order.getType() != null && order.getType() == Constants.ONE ? "同城寄送" : "就地寄存"); |
| | | vo.setDetailList(buildDetailList(id)); |
| | | |
| | | return vo; |
| | |
| | | throw new BusinessException(ResponseStatus.DATA_EMPTY); |
| | | } |
| | | |
| | | // 前置条件校验:异地存取 + 已寄存 |
| | | // 前置条件校验:同城寄送 + 已寄存 |
| | | if (!Constants.ONE.equals(order.getType())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "仅支持异地存取订单派单"); |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "仅支持同城寄送订单派单"); |
| | | } |
| | | if (!Integer.valueOf(Constants.OrderStatus.deposited.getStatus()).equals(order.getStatus())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "仅已寄存状态订单可派单"); |
| | |
| | | * |
| | | * @param orders 订单实体(需要 totalAmount、cityId 已设置) |
| | | * @param depositShop 寄件门店(需要 companyType) |
| | | * @param takeShop 取件门店(需要 companyType,就地存取时与 depositShop 相同) |
| | | * @param takeShop 取件门店(需要 companyType,就地寄存时与 depositShop 相同) |
| | | */ |
| | | private void calculateAndSetFeeAllocation(Orders orders, ShopInfo depositShop, ShopInfo takeShop) { |
| | | Long totalAmount = orders.getTotalAmount() != null ? orders.getTotalAmount() : 0L; |
| | |
| | | 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()); |
| | | } |
| | | } |
| | | // 关键词搜索:收件人/收件人电话模糊、订单号精准 |
| | |
| | | |
| | | // 评价状态 |
| | | vo.setCommentStatus(o.getCommentStatus()); |
| | | |
| | | String dateStr = new SimpleDateFormat("dd").format(o.getPayTime() != null ? o.getPayTime() : new Date()); |
| | | String autoNumStr = String.format("%03d", o.getAutoNum() != null ? o.getAutoNum() : 0); |
| | | String sort = o.getDepositShopId() + "-" + dateStr + "-" + autoNumStr; |
| | | //序号 |
| | | vo.setSortnum(Constants.formatIntegerNum(o.getDepositShopId())+"-"+o.getId()); |
| | | vo.setSortnum(sort); |
| | | |
| | | if(o.getTakeShopId()!=null){ |
| | | vo.setSortnumTake(Constants.formatIntegerNum(o.getTakeShopId())+"-"+o.getId()); |
| | | } |
| | |
| | | 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; |
| | |
| | | .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)); |
| | |
| | | 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()); |
| | |
| | | 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()); |
| | |
| | | throw new BusinessException(ResponseStatus.DATA_EMPTY); |
| | | } |
| | | |
| | | if (Constants.equalsInteger(order.getExceptionStatus(), Constants.ONE)) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "异常订单无法取消"); |
| | | } |
| | | |
| | | Integer status = order.getStatus(); |
| | | if (status == null) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "订单状态异常"); |
| | |
| | | "orderNo", order.getCode()); |
| | | // 短信通知会员:订单已取消 |
| | | Member cancelMember2 = memberMapper.selectById(memberId); |
| | | sendSmsNotify(cancelMember2 != null ? cancelMember2.getTelephone() : null, |
| | | Constants.SmsNotify.MEMBER_CANCELLED, "orderNo", order.getCode()); |
| | | |
| | | // 调用微信退款V3,全额退款 |
| | | String outRefundNo = ID.nextGUID(); |
| | |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "退款失败,请联系客服处理"); |
| | | } |
| | | ordersRefundMapper.insert(refund); |
| | | sendSmsNotify(cancelMember2 != null ? cancelMember2.getTelephone() : null, |
| | | Constants.SmsNotify.MEMBER_CANCELLED, "orderNo", order.getCode()); |
| | | restoreCoupon(order); |
| | | return; |
| | | } |
| | |
| | | * 保存取消订单操作日志 |
| | | */ |
| | | 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) { |
| | |
| | | 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(), "异常订单不支持手动退款"); |
| | | // 就地寄存异常订单不允许手动退款 |
| | | if (Constants.equalsInteger(order.getExceptionStatus(), Constants.ONE) |
| | | && Constants.equalsInteger(order.getType(), Constants.ZERO)) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "就地寄存异常订单不支持手动退款"); |
| | | } |
| | | |
| | | // 2. 校验退款金额 |
| | |
| | | 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); |
| | |
| | | // 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())); |
| | | } |
| | |
| | | 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())); |
| | | } |
| | |
| | | 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; |
| | | |
| | | // 异常就地寄存订单:同时更新主订单实际逾期费用 |
| | | boolean isAbnormal = Constants.equalsInteger(order.getExceptionStatus(), Constants.ONE) |
| | | && Constants.equalsInteger(order.getType(), Constants.ZERO); |
| | | if(isAbnormal){ |
| | | long shopException = isAbnormal ? (order.getShopCompensationAmount() != null ? order.getShopCompensationAmount() : 0L) : 0L; |
| | | long driverException = isAbnormal ? (order.getExceptionFee() != null ? order.getExceptionFee() : 0L) : 0L; |
| | | long actualOverdueFee = isAbnormal ? (overdueFee - shopException - driverException) : 0L; |
| | | if(actualOverdueFee!=order.getOverdueAmount()){ |
| | | order.setOverdueAmount(actualOverdueFee); |
| | | } |
| | | } |
| | | |
| | | order.setOverdueStatus(Constants.TWO); // 2=已支付 |
| | | order.setTotalAmount(newTotal); |
| | | order.setUpdateTime(now); |
| | | ordersMapper.updateById(order); |
| | | |
| | | |
| | | // 重算三方收益 |
| | | calculateAndSaveOrderFees(order.getId()); |
| | | } |
| | |
| | | sendOrderNotice(order.getMemberId(), Constants.MemberOrderNotify.WAIT_PICKUP_REMIND, order.getId(), |
| | | "orderNo", order.getCode(), "shopName", shopName); |
| | | } |
| | | // 寄存成功赠送优惠券 |
| | | giftOrderCoupon(order.getMemberId()); |
| | | // 异常订单寄存核销:标记原订单完成 |
| | | 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.setSettlementStatus(Constants.ZERO); |
| | | originalOrder.setFinishTime(now); |
| | | originalOrder.setUpdateTime(now); |
| | | ordersMapper.updateById(originalOrder); |
| | | // 触发原订单收益计算 |
| | | calculateAndSaveOrderFees(originalOrder.getId()); |
| | | generateRevenueRecords(originalOrder.getId()); |
| | | // 记录原订单日志 |
| | | saveShopVerifyLog(originalOrder, Constants.OrderLogType.shopTake, "异常订单核销,原订单完成", remark, shopId); |
| | | // 通知会员:订单已完成 |
| | | sendOrderNotice(originalOrder.getMemberId(), Constants.MemberOrderNotify.FINISHED, originalOrder.getId(), |
| | | "orderNo", originalOrder.getCode()); |
| | | // 通知存件门店和取件门店 |
| | | String settleDays = operationConfigBiz.getConfig().getSettlementDate(); |
| | | notifyBothShops(originalOrder, Constants.ShopOrderNotify.FINISHED, |
| | | "orderNo", originalOrder.getCode(), |
| | | "settleDays", settleDays != null ? settleDays : "7"); |
| | | // 通知司机:订单已完成 |
| | | if (originalOrder.getAcceptDriver() != null) { |
| | | 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) { |
| | |
| | | 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) { |
| | |
| | | } |
| | | |
| | | Long totalAmount = order.getTotalAmount() != null ? order.getTotalAmount() : 0L; |
| | | Long shopCompensationAmount = order.getShopCompensationAmount() != null ? order.getShopCompensationAmount() : 0L; |
| | | Long exceptionFee = order.getExceptionFee() != null ? order.getExceptionFee() : 0L; |
| | | // 分成基数 = 总金额 - 门店异常金额 - 司机异常金额 |
| | | Long feeBase = totalAmount - shopCompensationAmount - exceptionFee; |
| | | // 费率(为空时默认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 depositShopFee = new BigDecimal(totalAmount) |
| | | Long depositShopFee = new BigDecimal(feeBase) |
| | | .multiply(depositRate) |
| | | .setScale(0, RoundingMode.HALF_UP) |
| | | .longValue(); |
| | |
| | | |
| | | if (Constants.equalsInteger(order.getType(), Constants.ONE)) { |
| | | // 异地寄存:存件门店 + 司机 |
| | | driverFee = new BigDecimal(totalAmount) |
| | | driverFee = new BigDecimal(feeBase) |
| | | .multiply(driverRate) |
| | | .setScale(0, RoundingMode.HALF_UP) |
| | | .longValue(); |
| | | |
| | | // 异地寄存且有取件门店:加上取件门店收益 |
| | | if (order.getTakeShopId() != null) { |
| | | takeShopFee = new BigDecimal(totalAmount) |
| | | takeShopFee = new BigDecimal(feeBase) |
| | | .multiply(takeRate) |
| | | .setScale(0, RoundingMode.HALF_UP) |
| | | .longValue(); |
| | |
| | | } |
| | | } |
| | | |
| | | // 异常订单:存件门店异常补偿收益(单独一条记录,type=5) |
| | | if (Constants.equalsInteger(order.getExceptionStatus(), Constants.ONE) |
| | | && order.getShopCompensationAmount() != null && order.getShopCompensationAmount() > 0 |
| | | && order.getDepositShopId() != null) { |
| | | ShopInfo depositShop = shopInfoMapper.selectById(order.getDepositShopId()); |
| | | if (depositShop != null && depositShop.getId() != null) { |
| | | Revenue shopExRevenue = new Revenue(); |
| | | shopExRevenue.setMemberId(depositShop.getId()); |
| | | shopExRevenue.setMemberType(Constants.TWO); // 2=门店 |
| | | shopExRevenue.setType(5); // 5=异常金额 |
| | | shopExRevenue.setOptType(Constants.ONE); // 1=收入 |
| | | shopExRevenue.setAmount(order.getShopCompensationAmount()); |
| | | shopExRevenue.setVaildStatus(Constants.ZERO); |
| | | shopExRevenue.setObjId(orderId); |
| | | shopExRevenue.setObjType(Constants.ZERO); |
| | | shopExRevenue.setStatus(Constants.ZERO); |
| | | shopExRevenue.setOrderNo(order.getCode()); |
| | | shopExRevenue.setDeleted(Constants.ZERO); |
| | | shopExRevenue.setCreateTime(now); |
| | | revenueMapper.insert(shopExRevenue); |
| | | } |
| | | } |
| | | |
| | | // 取件门店收益(异地寄存且有取件门店) |
| | | if (takeShopFee > 0 && order.getTakeShopId() != null) { |
| | | ShopInfo takeShop = shopInfoMapper.selectById(order.getTakeShopId()); |
| | |
| | | } |
| | | } |
| | | |
| | | // 异常订单:司机异常补偿(异地 + 异常标记 + 有异常补偿金额) |
| | | // 异常订单:司机异常补偿(异地 + 异常标记,从关联异常子订单获取exceptionFee) |
| | | 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); |
| | | Orders childOrder = ordersMapper.selectOne(new QueryWrapper<Orders>().lambda() |
| | | .eq(Orders::getRelationOrderId, orderId) |
| | | .eq(Orders::getExceptionStatus, Constants.ONE) |
| | | .eq(Orders::getDeleted, Constants.ZERO) |
| | | .last("limit 1")); |
| | | if (childOrder != null && childOrder.getExceptionFee() != null && childOrder.getExceptionFee() > 0) { |
| | | 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(childOrder.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); |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | 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(), "当前订单状态不允许核销"); |
| | | } |
| | | |
| | |
| | | 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 driverExceptionFee = order.getExceptionFee() != null ? order.getExceptionFee() : 0L; |
| | | long shopExceptionFee = order.getShopCompensationAmount() != null ? order.getShopCompensationAmount() : 0L; |
| | | long totalExceptionFee = driverExceptionFee + shopExceptionFee; |
| | | |
| | |
| | | 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.setShopCompensationAmount(0L); |
| | | } |
| | | |
| | | order.setConfirmArriveTime(now); |
| | |
| | | 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()); |
| | |
| | | } |
| | | 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(), "无权操作该订单"); |
| | |
| | | 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(), "该订单已处理过异常,请勿重复操作"); |
| | |
| | | |
| | | Date now = new Date(); |
| | | |
| | | // ========== B. 创建新订单(就地存取) ========== |
| | | // ========== B. 创建新订单(就地寄存) ========== |
| | | String orderCode = "JC" + new java.text.SimpleDateFormat("yyyyMMddHHmmss").format(now) |
| | | + String.format("%04d", new java.util.Random().nextInt(10000)); |
| | | String orderTradeNo = generateOrderTradeNo(); |
| | |
| | | } |
| | | } |
| | | |
| | | // 存件门店分成占比(就地存取) |
| | | // 存件门店分成占比(就地寄存) |
| | | Integer cityId = Integer.valueOf(original.getCityId()); |
| | | boolean isCompany = Constants.equalsInteger(newShop.getCompanyType(), Constants.ONE); |
| | | int fallbackFieldA = isCompany ? Constants.FIVE : Constants.SIX; |
| | |
| | | newOrder.setCode(orderCode); |
| | | newOrder.setOutTradeNo(orderTradeNo); |
| | | newOrder.setMemberId(original.getMemberId()); |
| | | newOrder.setType(Constants.ZERO); // 就地存取 |
| | | newOrder.setType(Constants.ZERO); // 就地寄存 |
| | | newOrder.setCityId(original.getCityId()); |
| | | newOrder.setStatus(Constants.ONE); // 待寄存 |
| | | newOrder.setPayStatus(Constants.ONE); // 已支付 |
| | |
| | | newOrder.setDeclaredAmount(0L); |
| | | newOrder.setDeclaredFee(0L); |
| | | newOrder.setPrice(price); |
| | | newOrder.setBasicAmount(basicAmount); |
| | | newOrder.setEstimatedAmount(basicAmount); |
| | | newOrder.setBasicAmount(0L);//); |
| | | newOrder.setEstimatedAmount(0L);//basicAmount); |
| | | newOrder.setTotalAmount(0L); |
| | | newOrder.setPayAmount(0L); |
| | | newOrder.setManualRefund(Constants.ZERO); |
| | |
| | | |
| | | // 门店补偿金额 |
| | | newOrder.setShopCompensationAmount(dto.getShopCompensation()); |
| | | // 司机异常补偿金额 |
| | | newOrder.setExceptionFee(dto.getDriverCompensation()); |
| | | |
| | | newOrder.setRemark(dto.getRemark()); |
| | | newOrder.setPlatformSmsNotified(Constants.ZERO); |
| | |
| | | // ========== 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())); |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | @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; |
| | | } |
| | | |
| | | } |