From 7ed96770769b776523c658a8945211f9788cfa22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=81=E5=AE=87=E5=A5=87?= Date: Fri, 18 Apr 2025 18:37:41 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=AE=A2=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/xkt/StoreOrderController.java | 69 ++++++++- .../vo/order/StoreOrderAfterSaleReqVO.java | 30 ++++ .../xkt/vo/order/StoreOrderInfoVO.java | 4 +- .../xkt/vo/order/StoreOrderPageItemVO.java | 4 +- .../xkt/vo/order/StoreOrderPrintReqVO.java | 22 +++ .../xkt/vo/order/StoreOrderPrintRespVO.java | 21 +++ .../xkt/vo/order/StoreOrderReceiptReqVO.java | 20 +++ .../order/StoreOrderShipByPlatformReqVO.java | 31 ++++ .../vo/order/StoreOrderShipByStoreReqVO.java | 35 +++++ .../xkt/vo/order/StoreOrderShipRespVO.java | 25 ++++ .../java/com/ruoyi/xkt/domain/StoreOrder.java | 2 +- .../ruoyi/xkt/domain/StoreOrderDetail.java | 2 +- .../xkt/dto/express/ExpressPrintDTO.java | 23 +++ .../xkt/dto/order/StoreOrderAfterSaleDTO.java | 21 +++ .../ruoyi/xkt/dto/order/StoreOrderDTO.java | 2 +- .../xkt/dto/order/StoreOrderDetailDTO.java | 2 +- .../com/ruoyi/xkt/enums/EOrderAction.java | 1 + .../com/ruoyi/xkt/manager/ExpressManager.java | 10 +- .../manager/impl/YtoExpressManagerImpl.java | 50 ++++--- .../manager/impl/ZtoExpressManagerImpl.java | 59 +++++--- .../ruoyi/xkt/service/IStoreOrderService.java | 30 +++- .../service/impl/StoreOrderServiceImpl.java | 137 ++++++++++++++++-- 22 files changed, 529 insertions(+), 71 deletions(-) create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderAfterSaleReqVO.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderPrintReqVO.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderPrintRespVO.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderReceiptReqVO.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderShipByPlatformReqVO.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderShipByStoreReqVO.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderShipRespVO.java create mode 100644 xkt/src/main/java/com/ruoyi/xkt/dto/express/ExpressPrintDTO.java create mode 100644 xkt/src/main/java/com/ruoyi/xkt/dto/order/StoreOrderAfterSaleDTO.java diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/StoreOrderController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/StoreOrderController.java index 75a725476..7668497f9 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/StoreOrderController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/StoreOrderController.java @@ -10,6 +10,8 @@ import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.web.controller.xkt.vo.order.*; +import com.ruoyi.xkt.domain.StoreOrderDetail; +import com.ruoyi.xkt.dto.express.ExpressPrintDTO; import com.ruoyi.xkt.dto.order.*; import com.ruoyi.xkt.enums.EPayChannel; import com.ruoyi.xkt.enums.EPayPage; @@ -24,7 +26,9 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; +import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; /** * @author liangyq @@ -59,7 +63,7 @@ public class StoreOrderController extends XktBaseController { @PreAuthorize("@ss.hasPermi('system:order:edit')") @Log(title = "订单", businessType = BusinessType.UPDATE) @ApiOperation("修改订单") - @PutMapping("edit") + @PostMapping("edit") public R edit(@Valid @RequestBody StoreOrderUpdateReqVO vo) { StoreOrderUpdateDTO dto = BeanUtil.toBean(vo, StoreOrderUpdateDTO.class); dto.setOrderUserId(SecurityUtils.getUserId()); @@ -86,7 +90,7 @@ public class StoreOrderController extends XktBaseController { @PreAuthorize("@ss.hasPermi('system:order:edit')") @Log(title = "订单", businessType = BusinessType.UPDATE) @ApiOperation("取消订单") - @PutMapping("cancel") + @PostMapping("cancel") public R cancel(@Valid @RequestBody StoreOrderCancelReqVO vo) { OrderOptDTO dto = OrderOptDTO.builder() .storeOrderId(vo.getStoreOrderId()) @@ -121,6 +125,67 @@ public class StoreOrderController extends XktBaseController { return success(PageVO.of(pageDTO, StoreOrderPageItemVO.class)); } + @PreAuthorize("@ss.hasPermi('system:order:add')") + @Log(title = "订单", businessType = BusinessType.OTHER) + @ApiOperation("发货-平台物流") + @PostMapping("ship-platform") + public R> shipByPlatform(@Valid @RequestBody StoreOrderShipByPlatformReqVO vo) { + //TODO 权限 + StoreOrderExt orderExt = storeOrderService.shipOrderByPlatform(vo.getStoreOrderId(), + vo.getStoreOrderDetailIds(), vo.getExpressId(), SecurityUtils.getUserId()); + List respList = new ArrayList<>(vo.getStoreOrderDetailIds().size()); + for (StoreOrderDetail detail : orderExt.getOrderDetails()) { + if (vo.getStoreOrderDetailIds().contains(detail.getId())) { + respList.add(new StoreOrderShipRespVO(detail.getId(), detail.getExpressWaybillNo())); + } + } + return success(respList); + } + + @PreAuthorize("@ss.hasPermi('system:order:add')") + @Log(title = "订单", businessType = BusinessType.OTHER) + @ApiOperation("发货-档口物流") + @PostMapping("ship-store") + public R> shipByStore(@Valid @RequestBody StoreOrderShipByStoreReqVO vo) { + //TODO 权限 + StoreOrderExt orderExt = storeOrderService.shipOrderByStore(vo.getStoreOrderId(), + vo.getStoreOrderDetailIds(), vo.getExpressId(), vo.getExpressWaybillNo(), SecurityUtils.getUserId()); + List respList = new ArrayList<>(vo.getStoreOrderDetailIds().size()); + for (StoreOrderDetail detail : orderExt.getOrderDetails()) { + if (vo.getStoreOrderDetailIds().contains(detail.getId())) { + respList.add(new StoreOrderShipRespVO(detail.getId(), detail.getExpressWaybillNo())); + } + } + return success(respList); + } + + @PreAuthorize("@ss.hasPermi('system:order:add')") + @Log(title = "订单", businessType = BusinessType.OTHER) + @ApiOperation("打印面单") + @PostMapping("print") + public R> print(@Valid @RequestBody StoreOrderPrintReqVO vo) { + //TODO 权限 + List dtoList = storeOrderService.printOrder(vo.getStoreOrderDetailIds()); + List rtnList = dtoList.stream().map(o -> { + StoreOrderPrintRespVO rtn = new StoreOrderPrintRespVO(); + rtn.setExpressWaybillNo(o.getWaybillNo()); + rtn.setResult(o.getResult()); + return rtn; + }).collect(Collectors.toList()); + return success(rtnList); + } + + @PreAuthorize("@ss.hasPermi('system:order:add')") + @Log(title = "订单", businessType = BusinessType.OTHER) + @ApiOperation("确认收货") + @PostMapping("receipt") + public R receipt(@Valid @RequestBody StoreOrderReceiptReqVO vo) { + //TODO 权限 + storeOrderService.receiptOrder(vo.getStoreOrderId(), SecurityUtils.getUserId()); + return success(); + } + + /** * 根据支付渠道匹配支付类 * diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderAfterSaleReqVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderAfterSaleReqVO.java new file mode 100644 index 000000000..8a01d7e31 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderAfterSaleReqVO.java @@ -0,0 +1,30 @@ +package com.ruoyi.web.controller.xkt.vo.order; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author liangyq + * @date 2025-04-18 16:17 + */ +@ApiModel +@Data +public class StoreOrderAfterSaleReqVO { + + @NotNull(message = "订单ID不能为空") + @ApiModelProperty(value = "订单ID") + private Long storeOrderId; + + @NotEmpty(message = "订单明细ID不能为空") + @ApiModelProperty(value = "订单明细ID") + private List storeOrderDetailIds; + + @NotNull(message = "退货原因不能为空") + @ApiModelProperty(value = "退货原因code") + private String refundReasonCode; +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderInfoVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderInfoVO.java index 0b67be037..a3c23e92f 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderInfoVO.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderInfoVO.java @@ -104,7 +104,7 @@ public class StoreOrderInfoVO { * 退货原因 */ @ApiModelProperty(value = "退货原因") - private Integer refundReasonCode; + private String refundReasonCode; /** * 退货拒绝原因 */ @@ -348,7 +348,7 @@ public class StoreOrderInfoVO { * 退货原因 */ @ApiModelProperty(value = "退货原因") - private Integer refundReasonCode; + private String refundReasonCode; /** * 退货拒绝原因 */ diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderPageItemVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderPageItemVO.java index 3b585dfd5..459dd9e98 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderPageItemVO.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderPageItemVO.java @@ -108,7 +108,7 @@ public class StoreOrderPageItemVO extends StoreOrderDTO { * 退货原因 */ @ApiModelProperty(value = "退货原因") - private Integer refundReasonCode; + private String refundReasonCode; /** * 退货拒绝原因 */ @@ -351,7 +351,7 @@ public class StoreOrderPageItemVO extends StoreOrderDTO { * 退货原因 */ @ApiModelProperty(value = "退货原因") - private Integer refundReasonCode; + private String refundReasonCode; /** * 退货拒绝原因 */ diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderPrintReqVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderPrintReqVO.java new file mode 100644 index 000000000..fabe0c5e5 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderPrintReqVO.java @@ -0,0 +1,22 @@ +package com.ruoyi.web.controller.xkt.vo.order; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author liangyq + * @date 2025-04-18 14:36 + */ +@ApiModel +@Data +public class StoreOrderPrintReqVO { + + @NotEmpty(message = "订单明细ID不能为空") + @ApiModelProperty(value = "订单明细ID") + private List storeOrderDetailIds; +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderPrintRespVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderPrintRespVO.java new file mode 100644 index 000000000..6b023e8de --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderPrintRespVO.java @@ -0,0 +1,21 @@ +package com.ruoyi.web.controller.xkt.vo.order; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author liangyq + * @date 2025-04-18 14:36 + */ +@ApiModel +@Data +public class StoreOrderPrintRespVO { + + @ApiModelProperty(value = "物流单号") + private String expressWaybillNo; + + @ApiModelProperty(value = "文件流Base64编码") + private String result; + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderReceiptReqVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderReceiptReqVO.java new file mode 100644 index 000000000..2a88b024c --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderReceiptReqVO.java @@ -0,0 +1,20 @@ +package com.ruoyi.web.controller.xkt.vo.order; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author liangyq + * @date 2025-04-18 14:36 + */ +@ApiModel +@Data +public class StoreOrderReceiptReqVO { + + @NotNull(message = "订单ID不能为空") + @ApiModelProperty(value = "订单ID") + private Long storeOrderId; +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderShipByPlatformReqVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderShipByPlatformReqVO.java new file mode 100644 index 000000000..b0292d611 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderShipByPlatformReqVO.java @@ -0,0 +1,31 @@ +package com.ruoyi.web.controller.xkt.vo.order; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author liangyq + * @date 2025-04-18 14:36 + */ +@ApiModel +@Data +public class StoreOrderShipByPlatformReqVO { + + @NotNull(message = "订单ID不能为空") + @ApiModelProperty(value = "订单ID") + private Long storeOrderId; + + @NotEmpty(message = "订单明细ID不能为空") + @ApiModelProperty(value = "订单明细ID") + private List storeOrderDetailIds; + + @NotNull(message = "物流ID不能为空") + @ApiModelProperty(value = "物流ID") + private Long expressId; + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderShipByStoreReqVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderShipByStoreReqVO.java new file mode 100644 index 000000000..afea12eeb --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderShipByStoreReqVO.java @@ -0,0 +1,35 @@ +package com.ruoyi.web.controller.xkt.vo.order; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author liangyq + * @date 2025-04-18 14:36 + */ +@ApiModel +@Data +public class StoreOrderShipByStoreReqVO { + + @NotNull(message = "订单ID不能为空") + @ApiModelProperty(value = "订单ID") + private Long storeOrderId; + + @NotEmpty(message = "订单明细ID不能为空") + @ApiModelProperty(value = "订单明细ID") + private List storeOrderDetailIds; + + @NotNull(message = "物流ID不能为空") + @ApiModelProperty(value = "物流ID") + private Long expressId; + + @NotEmpty(message = "物流单号不能为空") + @ApiModelProperty(value = "物流单号") + private String expressWaybillNo; + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderShipRespVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderShipRespVO.java new file mode 100644 index 000000000..6c1f5e8a3 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderShipRespVO.java @@ -0,0 +1,25 @@ +package com.ruoyi.web.controller.xkt.vo.order; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author liangyq + * @date 2025-04-18 14:36 + */ +@ApiModel +@Data +@AllArgsConstructor +@NoArgsConstructor +public class StoreOrderShipRespVO { + + @ApiModelProperty(value = "订单明细ID") + private Long storeOrderDetailId; + + @ApiModelProperty(value = "物流单号") + private String expressWaybillNo; + +} diff --git a/xkt/src/main/java/com/ruoyi/xkt/domain/StoreOrder.java b/xkt/src/main/java/com/ruoyi/xkt/domain/StoreOrder.java index e419059b3..cd3babc45 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/domain/StoreOrder.java +++ b/xkt/src/main/java/com/ruoyi/xkt/domain/StoreOrder.java @@ -78,7 +78,7 @@ public class StoreOrder extends SimpleEntity { /** * 退货原因 */ - private Integer refundReasonCode; + private String refundReasonCode; /** * 退货拒绝原因 */ diff --git a/xkt/src/main/java/com/ruoyi/xkt/domain/StoreOrderDetail.java b/xkt/src/main/java/com/ruoyi/xkt/domain/StoreOrderDetail.java index b99889e87..9b8bb71ca 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/domain/StoreOrderDetail.java +++ b/xkt/src/main/java/com/ruoyi/xkt/domain/StoreOrderDetail.java @@ -113,7 +113,7 @@ public class StoreOrderDetail extends SimpleEntity { /** * 退货原因 */ - private Integer refundReasonCode; + private String refundReasonCode; /** * 退货拒绝原因 */ diff --git a/xkt/src/main/java/com/ruoyi/xkt/dto/express/ExpressPrintDTO.java b/xkt/src/main/java/com/ruoyi/xkt/dto/express/ExpressPrintDTO.java new file mode 100644 index 000000000..34814b731 --- /dev/null +++ b/xkt/src/main/java/com/ruoyi/xkt/dto/express/ExpressPrintDTO.java @@ -0,0 +1,23 @@ +package com.ruoyi.xkt.dto.express; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author liangyq + * @date 2025-04-18 15:15 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class ExpressPrintDTO { + /** + * 运单号 + */ + private String waybillNo; + /** + * 文件流Base64编码 + */ + private String result; +} diff --git a/xkt/src/main/java/com/ruoyi/xkt/dto/order/StoreOrderAfterSaleDTO.java b/xkt/src/main/java/com/ruoyi/xkt/dto/order/StoreOrderAfterSaleDTO.java new file mode 100644 index 000000000..0db808074 --- /dev/null +++ b/xkt/src/main/java/com/ruoyi/xkt/dto/order/StoreOrderAfterSaleDTO.java @@ -0,0 +1,21 @@ +package com.ruoyi.xkt.dto.order; + +import lombok.Data; + +import java.util.List; + +/** + * @author liangyq + * @date 2025-04-18 16:17 + */ +@Data +public class StoreOrderAfterSaleDTO { + + private Long storeOrderId; + + private List storeOrderDetailIds; + + private Long operatorId; + + private String refundReasonCode; +} diff --git a/xkt/src/main/java/com/ruoyi/xkt/dto/order/StoreOrderDTO.java b/xkt/src/main/java/com/ruoyi/xkt/dto/order/StoreOrderDTO.java index c0b120b5f..ef0a9a050 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/dto/order/StoreOrderDTO.java +++ b/xkt/src/main/java/com/ruoyi/xkt/dto/order/StoreOrderDTO.java @@ -76,7 +76,7 @@ public class StoreOrderDTO { /** * 退货原因 */ - private Integer refundReasonCode; + private String refundReasonCode; /** * 退货拒绝原因 */ diff --git a/xkt/src/main/java/com/ruoyi/xkt/dto/order/StoreOrderDetailDTO.java b/xkt/src/main/java/com/ruoyi/xkt/dto/order/StoreOrderDetailDTO.java index 143b7427f..8e81a99b4 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/dto/order/StoreOrderDetailDTO.java +++ b/xkt/src/main/java/com/ruoyi/xkt/dto/order/StoreOrderDetailDTO.java @@ -112,7 +112,7 @@ public class StoreOrderDetailDTO { /** * 退货原因 */ - private Integer refundReasonCode; + private String refundReasonCode; /** * 退货拒绝原因 */ diff --git a/xkt/src/main/java/com/ruoyi/xkt/enums/EOrderAction.java b/xkt/src/main/java/com/ruoyi/xkt/enums/EOrderAction.java index 18ab7e98d..7f088b677 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/enums/EOrderAction.java +++ b/xkt/src/main/java/com/ruoyi/xkt/enums/EOrderAction.java @@ -17,6 +17,7 @@ public enum EOrderAction { PAY(4, "支付"), CANCEL(5, "取消"), SHIP(6, "发货"), + COMPLETE(7, "完成"), ; private final Integer value; diff --git a/xkt/src/main/java/com/ruoyi/xkt/manager/ExpressManager.java b/xkt/src/main/java/com/ruoyi/xkt/manager/ExpressManager.java index 3ade8ddff..09cb519e9 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/manager/ExpressManager.java +++ b/xkt/src/main/java/com/ruoyi/xkt/manager/ExpressManager.java @@ -1,8 +1,12 @@ package com.ruoyi.xkt.manager; +import com.ruoyi.xkt.dto.express.ExpressPrintDTO; import com.ruoyi.xkt.dto.express.ExpressShipReqDTO; import com.ruoyi.xkt.enums.EExpressChannel; +import java.util.Collection; +import java.util.List; + /** * @author liangyq * @date 2025-04-15 15:43 @@ -26,9 +30,9 @@ public interface ExpressManager { /** * 打印面单 * - * @param waybillNo - * @return 文件流Base64编码 + * @param waybillNos + * @return */ - String printOrder(String waybillNo); + List printOrder(Collection waybillNos); } diff --git a/xkt/src/main/java/com/ruoyi/xkt/manager/impl/YtoExpressManagerImpl.java b/xkt/src/main/java/com/ruoyi/xkt/manager/impl/YtoExpressManagerImpl.java index d48120183..70e20f59a 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/manager/impl/YtoExpressManagerImpl.java +++ b/xkt/src/main/java/com/ruoyi/xkt/manager/impl/YtoExpressManagerImpl.java @@ -1,10 +1,12 @@ package com.ruoyi.xkt.manager.impl; +import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import cn.hutool.http.HttpUtil; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.xkt.dto.express.ExpressPrintDTO; import com.ruoyi.xkt.dto.express.ExpressShipReqDTO; import com.ruoyi.xkt.enums.EExpressChannel; import com.ruoyi.xkt.manager.ExpressManager; @@ -17,6 +19,8 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.util.ArrayList; +import java.util.Collection; +import java.util.List; /** * @author liangyq @@ -72,28 +76,34 @@ public class YtoExpressManagerImpl implements ExpressManager { } @Override - public String printOrder(String waybillNo) { - YtoPrintOrderParam printOrderParam = YtoPrintOrderParam.builder().waybillNo(waybillNo).build(); - try { - String param = JSONUtil.toJsonStr(printOrderParam); - String sign = YtoSignUtil.sign("waybill_print_adapter", "v1", param, appSecret); - YtoPublicRequest request = YtoPublicRequest.builder() - .timestamp(System.currentTimeMillis()) - .param(param) - .format(YtoPublicRequest.EFormat.JSON) - .sign(sign).build(); - String rtnStr = HttpUtil.post(gatewayUrl + "open/waybill_print_adapter/v1/N364gM/" + appKey, - JSONUtil.toJsonStr(request)); - log.info("圆通打印回单返回信息: {}", rtnStr); - JSONObject rtnJson = JSONUtil.parseObj(rtnStr); - String rtn = rtnJson.getJSONObject("data").getStr("pdfBase64"); - if (StrUtil.isNotEmpty(rtn)) { - return rtn; + public List printOrder(Collection waybillNos) { + Assert.notEmpty(waybillNos); + List list = new ArrayList<>(waybillNos.size()); + for (String waybillNo : waybillNos) { + YtoPrintOrderParam printOrderParam = YtoPrintOrderParam.builder().waybillNo(waybillNo).build(); + try { + String param = JSONUtil.toJsonStr(printOrderParam); + String sign = YtoSignUtil.sign("waybill_print_adapter", "v1", param, appSecret); + YtoPublicRequest request = YtoPublicRequest.builder() + .timestamp(System.currentTimeMillis()) + .param(param) + .format(YtoPublicRequest.EFormat.JSON) + .sign(sign).build(); + String rtnStr = HttpUtil.post(gatewayUrl + "open/waybill_print_adapter/v1/N364gM/" + appKey, + JSONUtil.toJsonStr(request)); + log.info("圆通打印面单返回信息: {}", rtnStr); + JSONObject rtnJson = JSONUtil.parseObj(rtnStr); + String rtn = rtnJson.getJSONObject("data").getStr("pdfBase64"); + if (StrUtil.isNotEmpty(rtn)) { + list.add(new ExpressPrintDTO(waybillNo, rtn)); + continue; + } + } catch (Exception e) { + log.error("圆通打印面单异常" + waybillNo, e); } - } catch (Exception e) { - log.error("圆通打印回单异常", e); + throw new ServiceException("圆通打印面单失败"); } - throw new ServiceException("圆通打印回单失败"); + return list; } diff --git a/xkt/src/main/java/com/ruoyi/xkt/manager/impl/ZtoExpressManagerImpl.java b/xkt/src/main/java/com/ruoyi/xkt/manager/impl/ZtoExpressManagerImpl.java index 85feccb8d..fedd6cb61 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/manager/impl/ZtoExpressManagerImpl.java +++ b/xkt/src/main/java/com/ruoyi/xkt/manager/impl/ZtoExpressManagerImpl.java @@ -7,6 +7,7 @@ import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.xkt.dto.express.ExpressPrintDTO; import com.ruoyi.xkt.dto.express.ExpressShipReqDTO; import com.ruoyi.xkt.enums.EExpressChannel; import com.ruoyi.xkt.manager.ExpressManager; @@ -17,6 +18,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; import java.util.concurrent.TimeUnit; /** @@ -83,30 +87,43 @@ public class ZtoExpressManagerImpl implements ExpressManager, InitializingBean { } @Override - public String printOrder(String waybillNo) { - Assert.notEmpty(waybillNo); - ZopPublicRequest request = new ZopPublicRequest(); - request.setBody(JSONUtil.toJsonStr(new ZtoPrintOrderParam(1, waybillNo, true))); - request.setUrl(gatewayUrl + ORDER_PRINT_URI); - request.setEncryptionType(EncryptionType.MD5); - try { - String bodyStr = client.execute(request); - log.info("中通订单打印返回信息: {}", bodyStr); - JSONObject bodyJson = JSONUtil.parseObj(bodyStr); - boolean success = bodyJson.getBool("status"); - if (success) { - //TODO 测试环境接口不通 - //等待推送 - TimeUnit.SECONDS.sleep(3); - String rtn = redisCache.getCacheObject("ZTO_" + waybillNo); - if (StrUtil.isNotEmpty(rtn)) { - return rtn; + public List printOrder(Collection waybillNos) { + Assert.notEmpty(waybillNos); + List list = new ArrayList<>(waybillNos.size()); + for (String waybillNo : waybillNos) { + ZopPublicRequest request = new ZopPublicRequest(); + request.setBody(JSONUtil.toJsonStr(new ZtoPrintOrderParam(1, waybillNo, true))); + request.setUrl(gatewayUrl + ORDER_PRINT_URI); + request.setEncryptionType(EncryptionType.MD5); + try { + String bodyStr = client.execute(request); + log.info("中通订单打印返回信息: {}", bodyStr); + JSONObject bodyJson = JSONUtil.parseObj(bodyStr); + boolean success = bodyJson.getBool("status"); + if (success) { + continue; } + } catch (Exception e) { + log.error("中通订单打印异常", e); } - } catch (Exception e) { - log.error("中通订单打印异常", e); + throw new ServiceException("中通订单打印失败"); } - throw new ServiceException("中通订单打印失败"); + //等待推送 + try { + //TODO 等待时间? + TimeUnit.SECONDS.sleep(3); + } catch (InterruptedException e) { + throw new ServiceException("系统异常"); + } + for (String waybillNo : waybillNos) { + //从缓存中获取 + String rtn = redisCache.getCacheObject("ZTO_" + waybillNo); + if (StrUtil.isEmpty(rtn)) { + throw new ServiceException("中通订单打印失败,未能获取面单"); + } + list.add(new ExpressPrintDTO(waybillNo, rtn)); + } + return list; } /** diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/IStoreOrderService.java b/xkt/src/main/java/com/ruoyi/xkt/service/IStoreOrderService.java index c4185e7bd..8ee27e330 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/IStoreOrderService.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/IStoreOrderService.java @@ -2,6 +2,7 @@ package com.ruoyi.xkt.service; import com.github.pagehelper.Page; import com.ruoyi.xkt.domain.StoreOrder; +import com.ruoyi.xkt.dto.express.ExpressPrintDTO; import com.ruoyi.xkt.dto.order.*; import com.ruoyi.xkt.enums.EPayChannel; import com.ruoyi.xkt.enums.EPayPage; @@ -85,7 +86,7 @@ public interface IStoreOrderService { void cancelOrder(OrderOptDTO opt); /** - * 准备发货(平台物流) + * 发货(平台物流) * * @param storeOrderId * @param storeOrderDetailIds @@ -108,4 +109,31 @@ public interface IStoreOrderService { */ StoreOrderExt shipOrderByStore(Long storeOrderId, List storeOrderDetailIds, Long expressId, String expressWaybillNo, Long operatorId); + + /** + * 打印面单 + * + * @param storeOrderDetailIds + * @return + */ + List printOrder(List storeOrderDetailIds); + + /** + * 确认收货 + * + * @param storeOrderId + * @param operatorId + * @return + */ + StoreOrderExt receiptOrder(Long storeOrderId, Long operatorId); + + /** + * 创建售后订单 + * + * @param afterSaleDTO + * @return + */ + StoreOrderExt createAfterSaleOrder(StoreOrderAfterSaleDTO afterSaleDTO); + + } diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreOrderServiceImpl.java b/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreOrderServiceImpl.java index 5128ce111..784128732 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreOrderServiceImpl.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreOrderServiceImpl.java @@ -6,6 +6,7 @@ import cn.hutool.core.date.DateUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.github.pagehelper.Page; import com.github.pagehelper.PageHelper; @@ -16,6 +17,7 @@ import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.bean.BeanValidators; import com.ruoyi.xkt.domain.*; import com.ruoyi.xkt.dto.express.ExpressContactDTO; +import com.ruoyi.xkt.dto.express.ExpressPrintDTO; import com.ruoyi.xkt.dto.express.ExpressRegionDTO; import com.ruoyi.xkt.dto.express.ExpressShipReqDTO; import com.ruoyi.xkt.dto.order.*; @@ -447,6 +449,9 @@ public class StoreOrderServiceImpl implements IStoreOrderService { StoreOrder order = getAndBaseCheck(storeOrderId); Assert.isTrue(EOrderType.SALES_ORDER.getValue().equals(order.getOrderType()), "非销售订单无法发起支付"); + if (!EOrderStatus.PENDING_PAYMENT.getValue().equals(order.getOrderStatus())) { + throw new ServiceException("订单[" + order.getId() + "]当前状态无法支付"); + } if (payChannel != EPayChannel.of(order.getPayChannel())) { throw new ServiceException("订单支付渠道不允许修改"); } @@ -574,8 +579,7 @@ public class StoreOrderServiceImpl implements IStoreOrderService { throw new ServiceException("快递[" + expressId + "]不可用"); } StoreOrder order = getAndBaseCheck(storeOrderId); - if (!EOrderStatus.PENDING_SHIPMENT.getValue().equals(order.getOrderStatus()) - && !EOrderStatus.SHIPPED.getValue().equals(order.getOrderStatus())) { + if (!EOrderStatus.PENDING_SHIPMENT.getValue().equals(order.getOrderStatus())) { throw new ServiceException("订单[" + order.getId() + "]当前状态无法发货"); } List containDetails = storeOrderDetailMapper.selectList( @@ -595,12 +599,6 @@ public class StoreOrderServiceImpl implements IStoreOrderService { } } List orderDetails = storeOrderDetailMapper.selectByIds(storeOrderDetailIds); - //订单->已发货 - order.setOrderStatus(EOrderStatus.SHIPPED.getValue()); - int orderSuccess = storeOrderMapper.updateById(order); - if (orderSuccess == 0) { - throw new ServiceException(Constants.VERSION_LOCK_ERROR_COMMON_MSG); - } for (StoreOrderDetail orderDetail : orderDetails) { //校验明细状态 if (!BeanValidators.exists(orderDetail)) { @@ -632,6 +630,23 @@ public class StoreOrderServiceImpl implements IStoreOrderService { } orderDetailIdList.add(orderDetail.getId()); } + EOrderStatus currentOrderStatus = EOrderStatus.SHIPPED; + Map detailMap = orderDetails.stream() + .collect(Collectors.toMap(SimpleEntity::getId, Function.identity())); + for (StoreOrderDetail containDetail : containDetails) { + StoreOrderDetail now = detailMap.getOrDefault(containDetail.getId(), containDetail); + if (EOrderStatus.PENDING_SHIPMENT.getValue().equals(now.getDetailStatus())) { + //明细有一条或多条为代发货 + currentOrderStatus = EOrderStatus.PENDING_SHIPMENT; + break; + } + } + //订单 -> 代发货/已发货 + order.setOrderStatus(currentOrderStatus.getValue()); + int orderSuccess = storeOrderMapper.updateById(order); + if (orderSuccess == 0) { + throw new ServiceException(Constants.VERSION_LOCK_ERROR_COMMON_MSG); + } //操作记录 addOperationRecords(order.getId(), EOrderAction.SHIP, orderDetailIdList, EOrderAction.SHIP, "平台物流发货", operatorId, new Date()); @@ -648,8 +663,7 @@ public class StoreOrderServiceImpl implements IStoreOrderService { throw new ServiceException("快递[" + expressId + "]不可用"); } StoreOrder order = getAndBaseCheck(storeOrderId); - if (!EOrderStatus.PENDING_SHIPMENT.getValue().equals(order.getOrderStatus()) - && !EOrderStatus.SHIPPED.getValue().equals(order.getOrderStatus())) { + if (!EOrderStatus.PENDING_SHIPMENT.getValue().equals(order.getOrderStatus())) { throw new ServiceException("订单[" + order.getId() + "]当前状态无法发货"); } List containDetails = storeOrderDetailMapper.selectList( @@ -669,12 +683,6 @@ public class StoreOrderServiceImpl implements IStoreOrderService { } } List orderDetails = storeOrderDetailMapper.selectByIds(storeOrderDetailIds); - //订单->已发货 - order.setOrderStatus(EOrderStatus.SHIPPED.getValue()); - int orderSuccess = storeOrderMapper.updateById(order); - if (orderSuccess == 0) { - throw new ServiceException(Constants.VERSION_LOCK_ERROR_COMMON_MSG); - } List orderDetailIdList = new ArrayList<>(orderDetails.size()); for (StoreOrderDetail orderDetail : orderDetails) { if (!BeanValidators.exists(orderDetail)) { @@ -698,12 +706,109 @@ public class StoreOrderServiceImpl implements IStoreOrderService { } orderDetailIdList.add(orderDetail.getId()); } + EOrderStatus currentOrderStatus = EOrderStatus.SHIPPED; + Map detailMap = orderDetails.stream() + .collect(Collectors.toMap(SimpleEntity::getId, Function.identity())); + for (StoreOrderDetail containDetail : containDetails) { + StoreOrderDetail now = detailMap.getOrDefault(containDetail.getId(), containDetail); + if (EOrderStatus.PENDING_SHIPMENT.getValue().equals(now.getDetailStatus())) { + //明细有一条或多条为代发货 + currentOrderStatus = EOrderStatus.PENDING_SHIPMENT; + break; + } + } + //订单 -> 代发货/已发货 + order.setOrderStatus(currentOrderStatus.getValue()); + int orderSuccess = storeOrderMapper.updateById(order); + if (orderSuccess == 0) { + throw new ServiceException(Constants.VERSION_LOCK_ERROR_COMMON_MSG); + } //操作记录 addOperationRecords(order.getId(), EOrderAction.SHIP, orderDetailIdList, EOrderAction.SHIP, "档口物流发货", operatorId, new Date()); return new StoreOrderExt(order, orderDetails); } + @Override + public List printOrder(List storeOrderDetailIds) { + Assert.notEmpty(storeOrderDetailIds); + Map> detailMap = storeOrderDetailMapper.selectByIds(storeOrderDetailIds).stream() + .filter(o -> BeanValidators.exists(o) + && Objects.nonNull(o.getExpressId()) + && StrUtil.isNotEmpty(o.getExpressWaybillNo()) + && EExpressType.PLATFORM.getValue().equals(o.getExpressType())) + .collect(Collectors.groupingBy(StoreOrderDetail::getExpressId)); + List rtnList = new ArrayList<>(); + for (Map.Entry> entry : detailMap.entrySet()) { + ExpressManager expressManager = getExpressManager(entry.getKey()); + Map detailMap2 = entry.getValue() + .stream() + .collect(Collectors.toMap(SimpleEntity::getId, StoreOrderDetail::getExpressWaybillNo)); + List pds = expressManager.printOrder(new HashSet<>(detailMap2.values())); + rtnList.addAll(pds); + } + return rtnList; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public StoreOrderExt receiptOrder(Long storeOrderId, Long operatorId) { + StoreOrder order = getAndBaseCheck(storeOrderId); + if (!EOrderStatus.PENDING_SHIPMENT.getValue().equals(order.getOrderStatus()) + && !EOrderStatus.SHIPPED.getValue().equals(order.getOrderStatus())) { + throw new ServiceException("订单[" + order.getId() + "]当前状态无法确认收货"); + } + //订单->已完成 + order.setOrderStatus(EOrderStatus.COMPLETED.getValue()); + int orderSuccess = storeOrderMapper.updateById(order); + if (orderSuccess == 0) { + throw new ServiceException(Constants.VERSION_LOCK_ERROR_COMMON_MSG); + } + List orderDetails = storeOrderDetailMapper.selectList( + Wrappers.lambdaQuery(StoreOrderDetail.class) + .eq(StoreOrderDetail::getStoreOrderId, order.getId()) + .eq(SimpleEntity::getDelFlag, Constants.UNDELETED)); + List orderDetailIdList = new ArrayList<>(orderDetails.size()); + for (StoreOrderDetail orderDetail : orderDetails) { + if (!EOrderStatus.PENDING_SHIPMENT.getValue().equals(order.getOrderStatus()) + && !EOrderStatus.SHIPPED.getValue().equals(order.getOrderStatus())) { + throw new ServiceException("订单明细[" + order.getId() + "]当前状态无法确认收货"); + } + //订单明细->已完成 + orderDetail.setDetailStatus(EOrderStatus.SHIPPED.getValue()); + int orderDetailSuccess = storeOrderDetailMapper.updateById(orderDetail); + if (orderDetailSuccess == 0) { + throw new ServiceException(Constants.VERSION_LOCK_ERROR_COMMON_MSG); + } + orderDetailIdList.add(orderDetail.getId()); + } + //操作记录 + addOperationRecords(order.getId(), EOrderAction.COMPLETE, orderDetailIdList, EOrderAction.COMPLETE, + "确认收货", operatorId, new Date()); + return new StoreOrderExt(order, orderDetails); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public StoreOrderExt createAfterSaleOrder(StoreOrderAfterSaleDTO afterSaleDTO) { + //获取原订单 + StoreOrder originOrder = getAndBaseCheck(afterSaleDTO.getStoreOrderId()); + if (!EOrderStatus.PENDING_SHIPMENT.getValue().equals(originOrder.getOrderStatus()) + && !EOrderStatus.SHIPPED.getValue().equals(originOrder.getOrderStatus())) { + throw new ServiceException("订单[" + originOrder.getId() + "]当前状态无法申请售后"); + } + //已存在的售后订单 + StoreOrder afterSaleOrder = storeOrderMapper.selectOne(Wrappers.lambdaQuery(StoreOrder.class) + .eq(StoreOrder::getRefundOrderId, originOrder.getId()) + .eq(SimpleEntity::getDelFlag, Constants.UNDELETED)); + List originOrderDetails = storeOrderDetailMapper.selectList( + Wrappers.lambdaQuery(StoreOrderDetail.class) + .eq(StoreOrderDetail::getStoreOrderId, originOrder.getId()) + .eq(SimpleEntity::getDelFlag, Constants.UNDELETED)); + //TODO + return null; + } + private void checkPreparePayStatus(Integer payStatus) { if (!EPayStatus.INIT.getValue().equals(payStatus) && !EPayStatus.PAYING.getValue().equals(payStatus)) { throw new ServiceException("订单状态异常无法发起支付");