| | |
| | | .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) |
| | | .select("s2.name", Orders::getTakeShopName) |
| | | .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()); |
| | | queryWrapper.like(StringUtils.isNotBlank(pageWrap.getModel().getCode()), Orders::getCode, pageWrap.getModel().getCode()); |
| | | queryWrapper.like(StringUtils.isNotBlank(pageWrap.getModel().getDepositShopName()), "s1.name", pageWrap.getModel().getDepositShopName()); |
| | | queryWrapper.like(StringUtils.isNotBlank(pageWrap.getModel().getTakeShopName()), "s2.name", pageWrap.getModel().getTakeShopName()); |
| | | queryWrapper.eq(StringUtils.isNotBlank(pageWrap.getModel().getTakeShopName()), Orders::getType,Constants.ONE); |
| | | queryWrapper.like(StringUtils.isNotBlank(pageWrap.getModel().getGoodsInfo()), Orders::getGoodsInfo, pageWrap.getModel().getGoodsInfo()); |
| | | queryWrapper.ge(pageWrap.getModel().getCreateStartTime() != null, Orders::getCreateTime, pageWrap.getModel().getCreateStartTime()); |
| | | queryWrapper.le(pageWrap.getModel().getCreateEndTime() != null, Orders::getCreateTime, Utils.Date.getEnd(pageWrap.getModel().getCreateEndTime())); |
| | |
| | | .or().like(DriverInfo::getTelephone, pageWrap.getModel().getDriverKeyword())); |
| | | queryWrapper.eq(pageWrap.getModel().getSettlementStatus() != null, Orders::getSettlementStatus, pageWrap.getModel().getSettlementStatus()); |
| | | queryWrapper.eq(pageWrap.getModel().getAcceptDriver() != null, Orders::getAcceptDriver, pageWrap.getModel().getAcceptDriver()); |
| | | queryWrapper.and(pageWrap.getModel().getTakeKeyword() != null, i -> i.like(Orders::getTakeUser, pageWrap.getModel().getTakeKeyword()) |
| | | .or().like(Orders::getTakePhone, pageWrap.getModel().getTakeKeyword())); |
| | | queryWrapper.and(pageWrap.getModel().getShopId() != null, i -> i.eq(Orders::getDepositShopId, pageWrap.getModel().getShopId()) |
| | | .or().eq(Orders::getTakeShopId, pageWrap.getModel().getShopId())); |
| | | queryWrapper.orderByDesc(Orders::getId); |
| | |
| | | } |
| | | |
| | | /** |
| | | * 计算就地存取预估费用 |
| | | * 计算就地寄存预估费用 |
| | | * |
| | | * 计算规则: |
| | | * 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; |
| | | |
| | |
| | | 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); |
| | |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "用户信息异常,无法发起支付"); |
| | | } |
| | | PayResponse payResponse = wxPayV3(orders.getOutTradeNo(), orders.getTotalAmount(), orders.getId(), |
| | | member.getOpenid(), Constants.OrdersAttach.STORAGE_ORDER); |
| | | member.getOpenid(), Constants.equalsInteger(orders.getType(), Constants.ONE) |
| | | ? Constants.OrdersAttach.DELIVERY_ORDER : Constants.OrdersAttach.STORAGE_ORDER); |
| | | payResponse.setLockKey(lockKey); |
| | | return payResponse; |
| | | } |
| | |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "用户信息异常,无法发起支付"); |
| | | } |
| | | return wxPayV3(orders.getOutTradeNo(), orders.getTotalAmount(), orders.getId(), |
| | | member.getOpenid(), Constants.OrdersAttach.STORAGE_ORDER); |
| | | member.getOpenid(), Constants.equalsInteger(orders.getType(), Constants.ONE) |
| | | ? Constants.OrdersAttach.DELIVERY_ORDER : Constants.OrdersAttach.STORAGE_ORDER); |
| | | } |
| | | |
| | | /** |
| | |
| | | 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(), "仅已寄存状态订单可派单"); |
| | |
| | | } |
| | | } |
| | | |
| | | private void clearVerifyCodes(Integer orderId) { |
| | | ordersMapper.update(null, new UpdateWrapper<Orders>().lambda() |
| | | .eq(Orders::getId, orderId) |
| | | .set(Orders::getMemberVerifyCode, null) |
| | | .set(Orders::getDriverVerifyCode, null)); |
| | | } |
| | | |
| | | private String getOrdersPrefix() { |
| | | try { |
| | | return systemDictDataBiz.queryByCode(Constants.OSS, Constants.RESOURCE_PATH).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; |
| | |
| | | } |
| | | |
| | | // 计算薪酬(分) |
| | | long driverFee = new BigDecimal(totalAmount).multiply(driverRata).longValue(); |
| | | long depositShopFee = new BigDecimal(totalAmount).multiply(depositShopRata).longValue(); |
| | | long takeShopFee = new BigDecimal(totalAmount).multiply(takeShopRata).longValue(); |
| | | long driverFee = new BigDecimal(totalAmount).multiply(driverRata).setScale(0, RoundingMode.HALF_UP).longValue(); |
| | | long depositShopFee = new BigDecimal(totalAmount).multiply(depositShopRata).setScale(0, RoundingMode.HALF_UP).longValue(); |
| | | long takeShopFee = new BigDecimal(totalAmount).multiply(takeShopRata).setScale(0, RoundingMode.HALF_UP).longValue(); |
| | | |
| | | orders.setDriverFee(driverFee); |
| | | orders.setDepositShopFee(depositShopFee); |
| | |
| | | |
| | | // 评价状态 |
| | | 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()); |
| | | } |
| | |
| | | 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; |
| | | } |
| | |
| | | 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. 校验退款金额 |
| | |
| | | |
| | | // 5. 唤起微信支付V3 |
| | | return wxPayV3(otherOrders.getOutTradeNo(), otherOrders.getPayAccount(), otherOrders.getId(), |
| | | member.getOpenid(), Constants.OrdersAttach.OVERDUE_FEE); |
| | | member.getOpenid(), Constants.equalsInteger(order.getType(), Constants.ONE) |
| | | ? Constants.OrdersAttach.DELIVERY_OVERDUE_FEE : Constants.OrdersAttach.OVERDUE_FEE); |
| | | } |
| | | |
| | | @Override |
| | |
| | | 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()); |
| | | } |
| | |
| | | } |
| | | // 寄存成功赠送优惠券 |
| | | 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); |
| | | clearVerifyCodes(originalOrder.getId()); |
| | | // 触发原订单收益计算 |
| | | 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) { |
| | |
| | | order.setFinishTime(now); |
| | | order.setInvoiceStatus(Constants.ONE); |
| | | ordersMapper.updateById(order); |
| | | // 就地寄存(type=0)取件时图片不必填,其他类型取件必填 |
| | | clearVerifyCodes(order.getId()); |
| | | if (!Constants.equalsInteger(order.getType(), Constants.ZERO)) { |
| | | if (images == null || images.isEmpty()) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "请上传取件图片"); |
| | |
| | | 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) { |
| | |
| | | order.setInvoiceStatus(Constants.ONE); |
| | | order.setConfirmArriveTime(now); |
| | | ordersMapper.updateById(order); |
| | | clearVerifyCodes(order.getId()); |
| | | // 订单完成,释放核销码 |
| | | releaseVerifyCode(verifyCode); |
| | | // 保存出库图片(obj_type=13 门店出库图片,最多3张) |
| | |
| | | order.setFinishTime(now); |
| | | order.setUpdateTime(now); |
| | | ordersMapper.updateById(order); |
| | | clearVerifyCodes(order.getId()); |
| | | |
| | | // 8. 释放核销码 |
| | | if (StringUtils.isNotBlank(order.getMemberVerifyCode())) { |
| | |
| | | order.setFinishTime(now); |
| | | order.setUpdateTime(now); |
| | | ordersMapper.updateById(order); |
| | | clearVerifyCodes(order.getId()); |
| | | |
| | | // 7. 生成收益记录 |
| | | calculateAndSaveOrderFees(orderId); |
| | |
| | | } |
| | | |
| | | 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); |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | 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); |
| | |
| | | order.setFinishTime(now); |
| | | order.setUpdateTime(now); |
| | | ordersMapper.updateById(order); |
| | | clearVerifyCodes(order.getId()); |
| | | |
| | | // 释放核销码 |
| | | if (StringUtils.isNotBlank(order.getMemberVerifyCode())) { |
| | |
| | | targetLat = order.getDepositLat(); |
| | | targetLgt = order.getDepositLgt(); |
| | | } 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(), "无权操作该订单"); |
| | | } |
| | |
| | | |
| | | 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())); |
| | | |
| | |
| | | return vo; |
| | | } |
| | | |
| | | @Override |
| | | public List<OrderTimelineVO> getOrderTimeline(Integer orderId) { |
| | | Orders order = ordersMapper.selectById(orderId); |
| | | if (order == null || Constants.equalsInteger(order.getDeleted(), Constants.ONE)) { |
| | | throw new BusinessException(ResponseStatus.DATA_EMPTY); |
| | | } |
| | | List<OrderTimelineVO> timeline = new ArrayList<>(); |
| | | String imgPrefix = getOrdersPrefix(); |
| | | |
| | | // 门店/司机名称 |
| | | String depositShopName = ""; |
| | | if (order.getDepositShopId() != null) { |
| | | ShopInfo depositShop = shopInfoMapper.selectById(order.getDepositShopId()); |
| | | if (depositShop != null) { |
| | | depositShopName = depositShop.getName(); |
| | | } |
| | | } |
| | | String takeShopName = ""; |
| | | if (order.getTakeShopId() != null) { |
| | | ShopInfo takeShop = shopInfoMapper.selectById(order.getTakeShopId()); |
| | | if (takeShop != null) { |
| | | takeShopName = takeShop.getName(); |
| | | } |
| | | } |
| | | String driverName = ""; |
| | | if (order.getAcceptDriver() != null) { |
| | | DriverInfo driver = driverInfoMapper.selectById(order.getAcceptDriver()); |
| | | if (driver != null) { |
| | | driverName = driver.getName(); |
| | | } |
| | | } |
| | | |
| | | boolean isLocal = Constants.equalsInteger(order.getType(), Constants.ZERO); |
| | | boolean hasTakeShop = order.getTakeShopId() != null; |
| | | boolean isException = Constants.equalsInteger(order.getExceptionStatus(), Constants.ONE); |
| | | int status = order.getStatus() != null ? order.getStatus() : 0; |
| | | |
| | | // 1. 门店寄存 (status >= 2) |
| | | if (status >= Constants.OrderStatus.deposited.getKey() && order.getDepositTime() != null) { |
| | | OrderTimelineVO node = new OrderTimelineVO(); |
| | | node.setTitle("门店【" + depositShopName + "】确认收件"); |
| | | node.setTime(order.getDepositTime()); |
| | | node.setImages(getFileUrls(orderId, Constants.FileType.ORDER_DEPOSIT.getKey(), imgPrefix)); |
| | | timeline.add(node); |
| | | } |
| | | |
| | | if (!isLocal) { |
| | | // 2. 司机取件 (status >= 4) |
| | | if (status >= Constants.OrderStatus.delivering.getKey() && order.getDriverTakeTime() != null) { |
| | | OrderTimelineVO node = new OrderTimelineVO(); |
| | | node.setTitle("司机【" + driverName + "】确认取件"); |
| | | node.setTime(order.getDriverTakeTime()); |
| | | node.setImages(getFileUrls(orderId, Constants.FileType.DRIVER_TAKE.getKey(), imgPrefix)); |
| | | timeline.add(node); |
| | | } |
| | | |
| | | if (isException) { |
| | | // 异常:关联查询异常订单 |
| | | Orders exceptionOrder = ordersMapper.selectOne(new QueryWrapper<Orders>().lambda() |
| | | .eq(Orders::getRelationOrderId, orderId) |
| | | .eq(Orders::getExceptionStatus, Constants.ONE) |
| | | .last("limit 1")); |
| | | if (exceptionOrder != null) { |
| | | OrderTimelineVO node = new OrderTimelineVO(); |
| | | node.setTitle("行李已异常转存,新订单号【" + exceptionOrder.getCode() + "】"); |
| | | node.setTime(exceptionOrder.getCreateTime()); |
| | | timeline.add(node); |
| | | } |
| | | } else { |
| | | // 3. 正常:司机送达 (status >= 5) |
| | | if(StringUtils.isBlank(takeShopName)){ |
| | | if (status >= Constants.OrderStatus.arrived.getKey() && order.getArriveTime() != null) { |
| | | OrderTimelineVO node = new OrderTimelineVO(); |
| | | node.setTitle("司机【" + driverName + "】确认送达"); |
| | | node.setTime(order.getArriveTime()); |
| | | node.setImages(getFileUrls(orderId, Constants.FileType.DRIVER_DONE.getKey(), imgPrefix)); |
| | | timeline.add(node); |
| | | } |
| | | } |
| | | // 4. 有门店:门店收件 (status >= 5) |
| | | if (hasTakeShop && status >= Constants.OrderStatus.arrived.getKey() && order.getArriveTime() != null) { |
| | | OrderTimelineVO node = new OrderTimelineVO(); |
| | | node.setTitle("门店【" + takeShopName + "】确认收件"); |
| | | node.setTime(order.getArriveTime()); |
| | | node.setImages(getFileUrls(orderId, Constants.FileType.ORDER_TAKE.getKey(), imgPrefix)); |
| | | timeline.add(node); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 最后:订单完成 (status = 7) |
| | | if (status == Constants.OrderStatus.finished.getKey() && order.getFinishTime() != null) { |
| | | OrderTimelineVO node = new OrderTimelineVO(); |
| | | node.setTitle("订单已完成"); |
| | | node.setTime(order.getFinishTime()); |
| | | timeline.add(node); |
| | | } |
| | | |
| | | timeline.sort((a, b) -> b.getTime() != null && a.getTime() != null ? b.getTime().compareTo(a.getTime()) : 0); |
| | | return timeline; |
| | | } |
| | | |
| | | } |