Commit f217ba0807a29102febfcb140ce5e2cb0bc17adf

Authored by YunaiV
1 parent 97fc4027

售后:

1、完善整个流程的实现
Showing 18 changed files with 232 additions and 158 deletions
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java
... ... @@ -45,7 +45,8 @@ public interface ErrorCodeConstants {
45 45 ErrorCode AFTER_SALE_DELIVERY_FAIL_STATUS_NOT_SELLER_AGREE = new ErrorCode(1011000108, "退货失败,售后单状态不处于【待买家退货】");
46 46 ErrorCode AFTER_SALE_CONFIRM_FAIL_STATUS_NOT_BUYER_DELIVERY = new ErrorCode(1011000109, "确认收货失败,售后单状态不处于【待确认收货】");
47 47 ErrorCode AFTER_SALE_REFUND_FAIL_STATUS_NOT_WAIT_REFUND = new ErrorCode(1011000110, "退款失败,售后单状态不是【待退款】");
48   - ErrorCode AFTER_SALE_CANCEL_FAIL_STATUS_NOT_APPLY_OR_AGREE = new ErrorCode(1011000111, "取消售后单失败,售后单状态不是【待审核】或【卖家同意】");
  48 + ErrorCode AFTER_SALE_CANCEL_FAIL_STATUS_NOT_APPLY_OR_AGREE_OR_BUYER_DELIVERY =
  49 + new ErrorCode(1011000111, "取消售后单失败,售后单状态不是【待审核】或【卖家同意】或【商家待收货】");
49 50  
50 51 // ========== Cart 模块 1011002000 ==========
51 52 ErrorCode CARD_ITEM_NOT_FOUND = new ErrorCode(1011002000, "购物车项不存在");
... ...
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/TradeAfterSaleStatusEnum.java
... ... @@ -22,35 +22,35 @@ public enum TradeAfterSaleStatusEnum implements IntArrayValuable {
22 22 /**
23 23 * 【申请售后】
24 24 */
25   - APPLY(10,"申请中", "会员申请退款"),
  25 + APPLY(10,"申请中", "会员申请退款"), // 有赞的状态提示:退款申请待商家处理
26 26 /**
27 27 * 卖家通过售后;【商品待退货】
28 28 */
29   - SELLER_AGREE(20, "卖家通过", "商家同意退款"),
  29 + SELLER_AGREE(20, "卖家通过", "商家同意退款"), // 有赞的状态提示:请退货并填写物流信息
30 30 /**
31 31 * 买家已退货,等待卖家收货;【商家待收货】
32 32 */
33   - BUYER_DELIVERY(30,"待卖家收货", "会员填写退货物流信息"),
  33 + BUYER_DELIVERY(30,"待卖家收货", "会员填写退货物流信息"), // 有赞的状态提示:退货退款申请待商家处理
34 34 /**
35 35 * 卖家已收货,等待平台退款;等待退款【等待退款】
36 36 */
37   - WAIT_REFUND(40, "等待平台退款", "商家收货"),
  37 + WAIT_REFUND(40, "等待平台退款", "商家收货"), // 有赞的状态提示:无(有赞无该状态)
38 38 /**
39 39 * 完成退款【退款成功】
40 40 */
41   - COMPLETE(50, "完成", "商家确认退款"),
  41 + COMPLETE(50, "完成", "商家确认退款"), // 有赞的状态提示:退款成功
42 42 /**
43 43 * 【买家取消】
44 44 */
45   - BUYER_CANCEL(61, "买家取消售后", "会员取消退款"),
  45 + BUYER_CANCEL(61, "买家取消售后", "会员取消退款"), // 有赞的状态提示:退款关闭
46 46 /**
47 47 * 卖家拒绝售后;商家拒绝【商家拒绝】
48 48 */
49   - SELLER_DISAGREE(62,"卖家拒绝", "商家拒绝退款"),
  49 + SELLER_DISAGREE(62,"卖家拒绝", "商家拒绝退款"), // 有赞的状态提示:商家不同意退款申请
50 50 /**
51 51 * 卖家拒绝收货,终止售后;【商家拒收货】
52 52 */
53   - SELLER_REFUSE(63,"卖家拒绝收货", "商家拒绝收货"),
  53 + SELLER_REFUSE(63,"卖家拒绝收货", "商家拒绝收货"), // 有赞的状态提示:商家拒绝收货,不同意退款
54 54 ;
55 55  
56 56 public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TradeAfterSaleStatusEnum::getStatus).toArray();
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.http
... ... @@ -2,3 +2,32 @@
2 2 GET {{baseUrl}}/trade/after-sale/page?pageNo=1&pageSize=10
3 3 Authorization: Bearer {{token}}
4 4 tenant-id: {{adminTenentId}}
  5 +
  6 +### 同意售后 => 成功
  7 +PUT {{baseUrl}}/trade/after-sale/agree?id=7
  8 +Authorization: Bearer {{token}}
  9 +tenant-id: {{adminTenentId}}
  10 +Content-Type: application/json
  11 +
  12 +### 拒绝售后 => 成功
  13 +PUT {{baseUrl}}/trade/after-sale/disagree
  14 +Authorization: Bearer {{token}}
  15 +tenant-id: {{adminTenentId}}
  16 +Content-Type: application/json
  17 +
  18 +{
  19 + "id": 6,
  20 + "auditReason": "阿巴巴"
  21 +}
  22 +
  23 +### 确认退款 => 成功
  24 +PUT {{baseUrl}}/trade/after-sale/refund?id=6
  25 +Authorization: Bearer {{token}}
  26 +tenant-id: {{adminTenentId}}
  27 +Content-Type: application/json
  28 +
  29 +### 确认收货 => 成功
  30 +PUT {{baseUrl}}/trade/after-sale/receive?id=7
  31 +Authorization: Bearer {{token}}
  32 +tenant-id: {{adminTenentId}}
  33 +Content-Type: application/json
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.java
... ... @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.trade.controller.admin.aftersale;
3 3 import cn.hutool.core.collection.CollUtil;
4 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
5 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
6 7 import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
7 8 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
8   -import cn.iocoder.yudao.module.product.api.property.ProductPropertyValueApi;
9   -import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
  9 +import cn.iocoder.yudao.module.pay.api.notify.dto.PayRefundNotifyReqDTO;
10 10 import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleDisagreeReqVO;
11 11 import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSalePageReqVO;
12 12 import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleRefuseReqVO;
... ... @@ -23,8 +23,8 @@ import org.springframework.validation.annotation.Validated;
23 23 import org.springframework.web.bind.annotation.*;
24 24  
25 25 import javax.annotation.Resource;
  26 +import javax.annotation.security.PermitAll;
26 27 import javax.validation.Valid;
27   -import java.util.List;
28 28 import java.util.Map;
29 29  
30 30 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
... ... @@ -32,7 +32,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.
32 32 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
33 33 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
34 34  
35   -@Tag(name = "管理后台 - 交易售后")
  35 +@Tag(name = "管理后台 - 售后订单")
36 36 @RestController
37 37 @RequestMapping("/trade/after-sale")
38 38 @Validated
... ... @@ -44,11 +44,9 @@ public class TradeAfterSaleController {
44 44  
45 45 @Resource
46 46 private MemberUserApi memberUserApi;
47   - @Resource
48   - private ProductPropertyValueApi productPropertyValueApi;
49 47  
50 48 @GetMapping("/page")
51   - @Operation(summary = "获得交易售后分页")
  49 + @Operation(summary = "获得售后订单分页")
52 50 @PreAuthorize("@ss.hasPermission('trade:after-sale:query')")
53 51 public CommonResult<PageResult<TradeAfterSaleRespPageItemVO>> getAfterSalePage(@Valid TradeAfterSalePageReqVO pageVO) {
54 52 // 查询售后
... ... @@ -57,13 +55,10 @@ public class TradeAfterSaleController {
57 55 return success(PageResult.empty());
58 56 }
59 57  
60   - // 查询商品属性
61   - List<ProductPropertyValueDetailRespDTO> propertyValueDetails = productPropertyValueApi
62   - .getPropertyValueDetailList(TradeAfterSaleConvert.INSTANCE.convertPropertyValueIds(pageResult.getList()));
63 58 // 查询会员
64 59 Map<Long, MemberUserRespDTO> memberUsers = memberUserApi.getUserMap(
65 60 convertSet(pageResult.getList(), TradeAfterSaleDO::getUserId));
66   - return success(TradeAfterSaleConvert.INSTANCE.convertPage(pageResult, memberUsers, propertyValueDetails));
  61 + return success(TradeAfterSaleConvert.INSTANCE.convertPage(pageResult, memberUsers));
67 62 }
68 63  
69 64 @PutMapping("/agree")
... ... @@ -101,7 +96,7 @@ public class TradeAfterSaleController {
101 96 return success(true);
102 97 }
103 98  
104   - @PostMapping("/refund")
  99 + @PutMapping("/refund")
105 100 @Operation(summary = "确认退款")
106 101 @Parameter(name = "id", description = "售后编号", required = true, example = "1")
107 102 @PreAuthorize("@ss.hasPermission('trade:after-sale:refund')")
... ... @@ -110,4 +105,15 @@ public class TradeAfterSaleController {
110 105 return success(true);
111 106 }
112 107  
  108 + @PostMapping("/update-refunded")
  109 + @Operation(summary = "更新售后订单为已退款") // 由 pay-module 支付服务,进行回调,可见 PayNotifyJob
  110 + @PermitAll // 无需登录,安全由 PayDemoOrderService 内部校验实现
  111 + @OperateLog(enable = false) // 禁用操作日志,因为没有操作人
  112 + public CommonResult<Boolean> updateAfterRefund(@RequestBody PayRefundNotifyReqDTO notifyReqDTO) {
  113 + // 目前业务逻辑,不需要做任何事情
  114 + // 当然,退款会有小概率会失败的情况,可以监控失败状态,进行告警
  115 + log.info("[updateAfterRefund][notifyReqDTO({})]", notifyReqDTO);
  116 + return success(true);
  117 + }
  118 +
113 119 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/AppTradeAfterSaleController.java
1 1 package cn.iocoder.yudao.module.trade.controller.app.aftersale;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  4 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
4 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 6 import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleCreateReqVO;
6 7 import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleDeliveryReqVO;
7   -import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSalePageItemRespVO;
8   -import cn.iocoder.yudao.module.trade.controller.app.base.property.AppProductPropertyValueDetailRespVO;
  8 +import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleRespVO;
  9 +import cn.iocoder.yudao.module.trade.convert.aftersale.TradeAfterSaleConvert;
9 10 import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleOperateTypeEnum;
10 11 import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleWayEnum;
11 12 import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.annotations.AfterSaleLog;
... ... @@ -18,7 +19,6 @@ import org.springframework.validation.annotation.Validated;
18 19 import org.springframework.web.bind.annotation.*;
19 20  
20 21 import javax.annotation.Resource;
21   -import java.time.LocalDateTime;
22 22 import java.util.Arrays;
23 23 import java.util.List;
24 24 import java.util.Objects;
... ... @@ -36,49 +36,18 @@ public class AppTradeAfterSaleController {
36 36 @Resource
37 37 private TradeAfterSaleService afterSaleService;
38 38  
39   - // TODO 芋艿:待实现
40 39 @GetMapping(value = "/page")
41 40 @Operation(summary = "获得售后分页")
42   - public CommonResult<PageResult<AppTradeAfterSalePageItemRespVO>> getAfterSalePage() {
43   - AppTradeAfterSalePageItemRespVO vo = new AppTradeAfterSalePageItemRespVO();
44   - vo.setId(1L);
45   - vo.setNo("1146347329394184195");
46   - vo.setStatus(61);
47   - vo.setWay(10);
48   - vo.setType(10);
49   - vo.setApplyReason("不想要了");
50   - vo.setApplyDescription("这个商品我不喜欢,想退款");
51   - vo.setApplyPicUrls(Arrays.asList("pic_url_1", "pic_url_2", "pic_url_3"));
52   -
53   - // 设置订单相关信息
54   - vo.setOrderId(2001L);
55   - vo.setOrderNo("23456789009876");
56   - vo.setOrderItemId(3001L);
57   - vo.setSpuId(4001L);
58   - vo.setSpuName("商品名");
59   - vo.setSkuId(5001L);
60   - vo.setProperties(Arrays.asList(
61   - new AppProductPropertyValueDetailRespVO().setPropertyId(6001L).setPropertyName("颜色").setValueId(7001L).setValueName("红色"),
62   - new AppProductPropertyValueDetailRespVO().setPropertyId(6002L).setPropertyName("尺寸").setValueId(7002L).setValueName("XL")));
63   - vo.setPicUrl("https://cdn.pixabay.com/photo/2022/12/06/06/21/lavender-7638368_1280.jpg");
64   - vo.setCount(2);
65   -
66   - // 设置审批相关信息
67   - vo.setAuditReason("审核通过");
68   -
69   - // 设置退款相关信息
70   - vo.setRefundPrice(1000);
71   - vo.setRefundTime(LocalDateTime.now());
72   -
73   - // 设置退货相关信息
74   - vo.setLogisticsId(7001L);
75   - vo.setLogisticsNo("LAGN101010101001");
76   - vo.setDeliveryTime(LocalDateTime.now());
77   - vo.setReceiveTime(LocalDateTime.now());
78   - vo.setReceiveReason("收货正常");
  41 + public CommonResult<PageResult<AppTradeAfterSaleRespVO>> getAfterSalePage(PageParam pageParam) {
  42 + return success(TradeAfterSaleConvert.INSTANCE.convertPage02(
  43 + afterSaleService.getAfterSalePage(getLoginUserId(), pageParam)));
  44 + }
79 45  
80   - return success(new PageResult<>(Arrays.asList(vo), 1L));
81   -// return success(afterSaleService.getAfterSalePage(getLoginUserId()));
  46 + @GetMapping(value = "/get")
  47 + @Operation(summary = "获得售后订单")
  48 + @Parameter(name = "id", description = "售后编号", required = true, example = "1")
  49 + public CommonResult<AppTradeAfterSaleRespVO> getAfterSale(@RequestParam("id") Long id) {
  50 + return success(TradeAfterSaleConvert.INSTANCE.convert(afterSaleService.getAfterSale(getLoginUserId(), id)));
82 51 }
83 52  
84 53 // TODO 芋艿:待实现
... ... @@ -99,7 +68,7 @@ public class AppTradeAfterSaleController {
99 68 return success(afterSaleService.createAfterSale(getLoginUserId(), createReqVO));
100 69 }
101 70  
102   - @PostMapping(value = "/delivery")
  71 + @PutMapping(value = "/delivery")
103 72 @Operation(summary = "退回货物")
104 73 public CommonResult<Boolean> deliveryAfterSale(@RequestBody AppTradeAfterSaleDeliveryReqVO deliveryReqVO) {
105 74 afterSaleService.deliveryAfterSale(getLoginUserId(), deliveryReqVO);
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppTradeAfterSaleDeliveryReqVO.java
... ... @@ -3,9 +3,7 @@ package cn.iocoder.yudao.module.trade.controller.app.aftersale.vo;
3 3 import io.swagger.v3.oas.annotations.media.Schema;
4 4 import lombok.Data;
5 5  
6   -import javax.validation.constraints.NotEmpty;
7 6 import javax.validation.constraints.NotNull;
8   -import java.time.LocalDateTime;
9 7  
10 8 @Schema(description = "用户 App - 交易售后退回货物 Request VO")
11 9 @Data
... ... @@ -23,8 +21,4 @@ public class AppTradeAfterSaleDeliveryReqVO {
23 21 @NotNull(message = "退货物流单号不能为空")
24 22 private String logisticsNo;
25 23  
26   - @Schema(description = "退货时间", requiredMode = Schema.RequiredMode.REQUIRED)
27   - @NotEmpty(message = "退货时间不能为空")
28   - private LocalDateTime deliveryTime;
29   -
30 24 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppTradeAfterSalePageItemRespVO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppTradeAfterSaleRespVO.java
... ... @@ -7,9 +7,9 @@ import lombok.Data;
7 7 import java.time.LocalDateTime;
8 8 import java.util.List;
9 9  
10   -@Schema(description = "用户 App - 交易售后的分页项 Request VO")
  10 +@Schema(description = "用户 App - 交易售后 Response VO")
11 11 @Data
12   -public class AppTradeAfterSalePageItemRespVO {
  12 +public class AppTradeAfterSaleRespVO {
13 13  
14 14 @Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
15 15 private Long id;
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/delivery/AppDeliverExpressController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.trade.controller.app.delivery;
  2 +
  3 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  4 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  5 +import cn.iocoder.yudao.module.trade.controller.app.delivery.vo.express.AppDeliveryExpressRespVO;
  6 +import cn.iocoder.yudao.module.trade.convert.delivery.DeliveryExpressConvert;
  7 +import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO;
  8 +import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService;
  9 +import io.swagger.v3.oas.annotations.Operation;
  10 +import io.swagger.v3.oas.annotations.tags.Tag;
  11 +import org.springframework.validation.annotation.Validated;
  12 +import org.springframework.web.bind.annotation.GetMapping;
  13 +import org.springframework.web.bind.annotation.RequestMapping;
  14 +import org.springframework.web.bind.annotation.RestController;
  15 +
  16 +import javax.annotation.Resource;
  17 +import java.util.Comparator;
  18 +import java.util.List;
  19 +
  20 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  21 +
  22 +@Tag(name = "用户 App - 快递公司")
  23 +@RestController
  24 +@RequestMapping("/trade/delivery/express")
  25 +@Validated
  26 +public class AppDeliverExpressController {
  27 +
  28 + @Resource
  29 + private DeliveryExpressService deliveryExpressService;
  30 +
  31 + @GetMapping("/list")
  32 + @Operation(summary = "获得快递公司列表")
  33 + public CommonResult<List<AppDeliveryExpressRespVO>> getDeliveryExpressList() {
  34 + List<DeliveryExpressDO> list = deliveryExpressService.getDeliveryExpressList(CommonStatusEnum.ENABLE.getStatus());
  35 + list.sort(Comparator.comparing(DeliveryExpressDO::getSort));
  36 + return success(DeliveryExpressConvert.INSTANCE.convertList03(list));
  37 + }
  38 +
  39 +}
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/delivery/vo/express/AppDeliveryExpressRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.trade.controller.app.delivery.vo.express;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +
  6 +@Schema(description = "用户 App - 快递公司 Response VO")
  7 +@Data
  8 +public class AppDeliveryExpressRespVO {
  9 +
  10 + @Schema(description = "编号", required = true, example = "1")
  11 + private Long id;
  12 +
  13 + @Schema(description = "门店名称", required = true, example = "顺丰")
  14 + private String name;
  15 +
  16 +}
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/TradeAfterSaleConvert.java
1 1 package cn.iocoder.yudao.module.trade.convert.aftersale;
2 2  
3   -import cn.hutool.core.collection.CollUtil;
4 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 4 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
6 5 import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO;
... ... @@ -9,6 +8,7 @@ import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSal
9 8 import cn.iocoder.yudao.module.trade.controller.admin.base.member.user.MemberUserRespVO;
10 9 import cn.iocoder.yudao.module.trade.controller.admin.base.product.property.ProductPropertyValueDetailRespVO;
11 10 import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleCreateReqVO;
  11 +import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleRespVO;
12 12 import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO;
13 13 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
14 14 import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
... ... @@ -17,10 +17,7 @@ import org.mapstruct.Mapping;
17 17 import org.mapstruct.Mappings;
18 18 import org.mapstruct.factory.Mappers;
19 19  
20   -import java.util.*;
21   -import java.util.stream.Collectors;
22   -
23   -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
  20 +import java.util.Map;
24 21  
25 22 @Mapper
26 23 public interface TradeAfterSaleConvert {
... ... @@ -37,6 +34,8 @@ public interface TradeAfterSaleConvert {
37 34 TradeAfterSaleDO convert(AppTradeAfterSaleCreateReqVO createReqVO, TradeOrderItemDO tradeOrderItem);
38 35  
39 36 @Mappings({
  37 + @Mapping(source = "afterSale.orderId", target = "merchantOrderId"),
  38 + @Mapping(source = "afterSale.id", target = "merchantRefundId"),
40 39 @Mapping(source = "afterSale.applyReason", target = "reason"),
41 40 @Mapping(source = "afterSale.refundPrice", target = "price")
42 41 })
... ... @@ -48,41 +47,18 @@ public interface TradeAfterSaleConvert {
48 47 PageResult<TradeAfterSaleRespPageItemVO> convertPage(PageResult<TradeAfterSaleDO> page);
49 48  
50 49 default PageResult<TradeAfterSaleRespPageItemVO> convertPage(PageResult<TradeAfterSaleDO> pageResult,
51   - Map<Long, MemberUserRespDTO> memberUsers, List<ProductPropertyValueDetailRespDTO> propertyValueDetails) {
52   - PageResult<TradeAfterSaleRespPageItemVO> pageVOResult = convertPage(pageResult);
53   - // 处理会员 + 商品属性等关联信息
54   - Map<Long, ProductPropertyValueDetailRespDTO> propertyValueDetailMap = convertMap(propertyValueDetails, ProductPropertyValueDetailRespDTO::getValueId);
55   - for (int i = 0; i < pageResult.getList().size(); i++) {
56   - TradeAfterSaleRespPageItemVO afterSaleVO = pageVOResult.getList().get(i);
57   - TradeAfterSaleDO afterSaleDO = pageResult.getList().get(i);
58   - // 会员
59   - afterSaleVO.setUser(convert(memberUsers.get(afterSaleDO.getUserId())));
60   - // 商品属性
61   - if (CollUtil.isNotEmpty(afterSaleDO.getProperties())) {
62   - afterSaleVO.setProperties(new ArrayList<>(afterSaleDO.getProperties().size()));
63   - // 遍历每个 properties,设置到 TradeOrderPageItemRespVO.Item 中
64   - afterSaleDO.getProperties().forEach(property -> {
65   - ProductPropertyValueDetailRespDTO propertyValueDetail = propertyValueDetailMap.get(property.getValueId());
66   - if (propertyValueDetail == null) {
67   - return;
68   - }
69   - afterSaleVO.getProperties().add(convert(propertyValueDetail));
70   - });
71   - }
72   - }
73   - return pageVOResult;
  50 + Map<Long, MemberUserRespDTO> memberUsers) {
  51 + PageResult<TradeAfterSaleRespPageItemVO> voPageResult = convertPage(pageResult);
  52 + // 处理会员
  53 + voPageResult.getList().forEach(afterSale -> afterSale.setUser(
  54 + convert(memberUsers.get(afterSale.getUserId()))));
  55 + return voPageResult;
74 56 }
75 57  
76 58 ProductPropertyValueDetailRespVO convert(ProductPropertyValueDetailRespDTO bean);
77 59  
78   - default Set<Long> convertPropertyValueIds(List<TradeAfterSaleDO> list) {
79   - if (CollUtil.isEmpty(list)) {
80   - return new HashSet<>();
81   - }
82   - return list.stream().filter(item -> item.getProperties() != null)
83   - .flatMap(p -> p.getProperties().stream()) // 遍历多个 Property 属性
84   - .map(TradeOrderItemDO.Property::getValueId) // 将每个 Property 转换成对应的 propertyId,最后形成集合
85   - .collect(Collectors.toSet());
86   - }
  60 + AppTradeAfterSaleRespVO convert(TradeAfterSaleDO bean);
  61 +
  62 + PageResult<AppTradeAfterSaleRespVO> convertPage02(PageResult<TradeAfterSaleDO> page);
87 63  
88 64 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/delivery/DeliveryExpressConvert.java
1 1 package cn.iocoder.yudao.module.trade.convert.delivery;
2 2  
3   -import java.util.*;
4   -
5 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6   -
7 4 import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressCreateReqVO;
8 5 import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressExcelVO;
9 6 import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressRespVO;
10 7 import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressUpdateReqVO;
  8 +import cn.iocoder.yudao.module.trade.controller.app.delivery.vo.express.AppDeliveryExpressRespVO;
11 9 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO;
12 10 import org.mapstruct.Mapper;
13 11 import org.mapstruct.factory.Mappers;
14 12  
  13 +import java.util.List;
  14 +
15 15 @Mapper
16 16 public interface DeliveryExpressConvert {
17 17  
... ... @@ -29,4 +29,6 @@ public interface DeliveryExpressConvert {
29 29  
30 30 List<DeliveryExpressExcelVO> convertList02(List<DeliveryExpressDO> list);
31 31  
  32 + List<AppDeliveryExpressRespVO> convertList03(List<DeliveryExpressDO> list);
  33 +
32 34 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/TradeAfterSaleDO.java
... ... @@ -17,7 +17,7 @@ import java.time.LocalDateTime;
17 17 import java.util.List;
18 18  
19 19 /**
20   - * 交易售后,用于处理 {@link TradeOrderDO} 交易订单的退款退货流程
  20 + * 售后订单,用于处理 {@link TradeOrderDO} 交易订单的退款退货流程
21 21 *
22 22 * @author 芋道源码
23 23 */
... ... @@ -32,7 +32,7 @@ public class TradeAfterSaleDO extends BaseDO {
32 32 */
33 33 private Long id;
34 34 /**
35   - * 售后流水号
  35 + * 售后单号
36 36 *
37 37 * 例如说,1146347329394184195
38 38 */
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/TradeAfterSaleMapper.java
1 1 package cn.iocoder.yudao.module.trade.dal.mysql.aftersale;
2 2  
  3 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
3 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 5 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 6 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
... ... @@ -23,13 +24,20 @@ public interface TradeAfterSaleMapper extends BaseMapperX&lt;TradeAfterSaleDO&gt; {
23 24 .orderByDesc(TradeAfterSaleDO::getId));
24 25 }
25 26  
  27 + default PageResult<TradeAfterSaleDO> selectPage(Long userId, PageParam pageParam) {
  28 + return selectPage(pageParam, new LambdaQueryWrapperX<TradeAfterSaleDO>()
  29 + .eqIfPresent(TradeAfterSaleDO::getUserId, userId)
  30 + .orderByDesc(TradeAfterSaleDO::getId));
  31 + }
  32 +
26 33 default int updateByIdAndStatus(Long id, Integer status, TradeAfterSaleDO update) {
27 34 return update(update, new LambdaUpdateWrapper<TradeAfterSaleDO>()
28 35 .eq(TradeAfterSaleDO::getId, id).eq(TradeAfterSaleDO::getStatus, status));
29 36 }
30 37  
31   - default TradeAfterSaleDO selectByPayRefundId(Long payRefundId) {
32   - return selectOne(TradeAfterSaleDO::getPayRefundId, payRefundId);
  38 + default TradeAfterSaleDO selectByIdAndUserId(Long id, Long userId) {
  39 + return selectOne(TradeAfterSaleDO::getId, id,
  40 + TradeAfterSaleDO::getUserId, userId);
33 41 }
34 42  
35 43 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/delivery/DeliveryExpressMapper.java
... ... @@ -36,6 +36,11 @@ public interface DeliveryExpressMapper extends BaseMapperX&lt;DeliveryExpressDO&gt; {
36 36 return selectOne(new LambdaQueryWrapper<DeliveryExpressDO>()
37 37 .eq(DeliveryExpressDO::getCode, code));
38 38 }
  39 +
  40 + default List<DeliveryExpressDO> selectListByStatus(Integer status) {
  41 + return selectList(DeliveryExpressDO::getStatus, status);
  42 + }
  43 +
39 44 }
40 45  
41 46  
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleService.java
1 1 package cn.iocoder.yudao.module.trade.service.aftersale;
2 2  
  3 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
3 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 5 import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleDisagreeReqVO;
5 6 import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSalePageReqVO;
... ... @@ -9,41 +10,57 @@ import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSa
9 10 import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO;
10 11  
11 12 /**
12   - * 交易售后 Service 接口
  13 + * 售后订单 Service 接口
13 14 *
14 15 * @author 芋道源码
15 16 */
16 17 public interface TradeAfterSaleService {
17 18  
18 19 /**
19   - * 获得交易售后分页
  20 + * 【管理员】获得售后订单分页
20 21 *
21 22 * @param pageReqVO 分页查询
22   - * @return 交易售后分页
  23 + * @return 售后订单分页
23 24 */
24 25 PageResult<TradeAfterSaleDO> getAfterSalePage(TradeAfterSalePageReqVO pageReqVO);
25 26  
26 27 /**
27   - * 【会员】创建交易售后
28   - * <p>
29   - * 一般是用户发起售后请求
  28 + * 【会员】获得售后订单分页
  29 + *
  30 + * @param userId 用户编号
  31 + * @param pageParam 分页参数
  32 + * @return 售后订单分页
  33 + */
  34 + PageResult<TradeAfterSaleDO> getAfterSalePage(Long userId, PageParam pageParam);
  35 +
  36 + /**
  37 + * 【会员】获得售后单
  38 + *
  39 + * @param userId 用户编号
  40 + * @param id 售后编号
  41 + * @return 售后订单
  42 + */
  43 + TradeAfterSaleDO getAfterSale(Long userId, Long id);
  44 +
  45 + /**
  46 + * 【会员】创建售后订单
30 47 *
31 48 * @param userId 会员用户编号
32 49 * @param createReqVO 创建 Request 信息
33   - * @return 交易售后编号
  50 + * @return 售后编号
34 51 */
35 52 Long createAfterSale(Long userId, AppTradeAfterSaleCreateReqVO createReqVO);
36 53  
37 54 /**
38   - * 【管理员】同意交易售后
  55 + * 【管理员】同意售后订单
39 56 *
40 57 * @param userId 管理员用户编号
41   - * @param id 交易售后编号
  58 + * @param id 售后编号
42 59 */
43 60 void agreeAfterSale(Long userId, Long id);
44 61  
45 62 /**
46   - * 【管理员】拒绝交易售后
  63 + * 【管理员】拒绝售后订单
47 64 *
48 65 * @param userId 管理员用户编号
49 66 * @param auditReqVO 审批 Request 信息
... ... @@ -62,7 +79,7 @@ public interface TradeAfterSaleService {
62 79 * 【管理员】确认收货
63 80 *
64 81 * @param userId 管理员编号
65   - * @param id 交易售后编号
  82 + * @param id 售后编号
66 83 */
67 84 void receiveAfterSale(Long userId, Long id);
68 85  
... ... @@ -87,7 +104,7 @@ public interface TradeAfterSaleService {
87 104 * 【会员】取消售后
88 105 *
89 106 * @param userId 会员用户编号
90   - * @param id 交易售后编号
  107 + * @param id 售后编号
91 108 */
92 109 void cancelAfterSale(Long userId, Long id);
93 110  
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java
... ... @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.trade.service.aftersale;
3 3 import cn.hutool.core.util.ObjectUtil;
4 4 import cn.hutool.core.util.RandomUtil;
5 5 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
  6 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
6 7 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 8 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
8 9 import cn.iocoder.yudao.module.pay.api.refund.PayRefundApi;
... ... @@ -45,7 +46,7 @@ import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString
45 46 import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*;
46 47  
47 48 /**
48   - * 交易售后 Service 实现类
  49 + * 售后订单 Service 实现类
49 50 *
50 51 * @author 芋道源码
51 52 */
... ... @@ -76,12 +77,22 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa
76 77 }
77 78  
78 79 @Override
  80 + public PageResult<TradeAfterSaleDO> getAfterSalePage(Long userId, PageParam pageParam) {
  81 + return tradeAfterSaleMapper.selectPage(userId, pageParam);
  82 + }
  83 +
  84 + @Override
  85 + public TradeAfterSaleDO getAfterSale(Long userId, Long id) {
  86 + return tradeAfterSaleMapper.selectByIdAndUserId(id, userId);
  87 + }
  88 +
  89 + @Override
79 90 @Transactional(rollbackFor = Exception.class)
80 91 public Long createAfterSale(Long userId, AppTradeAfterSaleCreateReqVO createReqVO) {
81 92 // 第一步,前置校验
82 93 TradeOrderItemDO tradeOrderItem = validateOrderItemApplicable(userId, createReqVO);
83 94  
84   - // 第二步,存储交易售后
  95 + // 第二步,存储售后订单
85 96 TradeAfterSaleDO afterSale = createAfterSale(createReqVO, tradeOrderItem);
86 97 return afterSale.getId();
87 98 }
... ... @@ -168,7 +179,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa
168 179 // 更新售后单的状态
169 180 // 情况一:退款:标记为 WAIT_REFUND 状态。后续等退款发起成功后,在标记为 COMPLETE 状态
170 181 // 情况二:退货退款:需要等用户退货后,才能发起退款
171   - Integer newStatus = afterSale.getType().equals(TradeAfterSaleWayEnum.REFUND.getWay()) ?
  182 + Integer newStatus = afterSale.getWay().equals(TradeAfterSaleWayEnum.REFUND.getWay()) ?
172 183 TradeAfterSaleStatusEnum.WAIT_REFUND.getStatus() : TradeAfterSaleStatusEnum.SELLER_AGREE.getStatus();
173 184 updateAfterSaleStatus(afterSale.getId(), TradeAfterSaleStatusEnum.APPLY.getStatus(), new TradeAfterSaleDO()
174 185 .setStatus(newStatus).setAuditUserId(userId).setAuditTime(LocalDateTime.now()));
... ... @@ -243,7 +254,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa
243 254 updateAfterSaleStatus(afterSale.getId(), TradeAfterSaleStatusEnum.SELLER_AGREE.getStatus(), new TradeAfterSaleDO()
244 255 .setStatus(TradeAfterSaleStatusEnum.BUYER_DELIVERY.getStatus())
245 256 .setLogisticsId(deliveryReqVO.getLogisticsId()).setLogisticsNo(deliveryReqVO.getLogisticsNo())
246   - .setDeliveryTime(deliveryReqVO.getDeliveryTime()));
  257 + .setDeliveryTime(LocalDateTime.now()));
247 258  
248 259 // 记录售后日志
249 260 createAfterSaleLog(userId, UserTypeEnum.MEMBER.getValue(),
... ... @@ -318,7 +329,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa
318 329 @Transactional(rollbackFor = Exception.class)
319 330 public void refundAfterSale(Long userId, String userIp, Long id) {
320 331 // 校验售后单的状态,并状态待退款
321   - TradeAfterSaleDO afterSale = tradeAfterSaleMapper.selectByPayRefundId(id);
  332 + TradeAfterSaleDO afterSale = tradeAfterSaleMapper.selectById(id);
322 333 if (afterSale == null) {
323 334 throw exception(AFTER_SALE_NOT_FOUND);
324 335 }
... ... @@ -362,13 +373,14 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa
362 373 @Override
363 374 public void cancelAfterSale(Long userId, Long id) {
364 375 // 校验售后单的状态,并状态待退款
365   - TradeAfterSaleDO afterSale = tradeAfterSaleMapper.selectByPayRefundId(id);
  376 + TradeAfterSaleDO afterSale = tradeAfterSaleMapper.selectById(id);
366 377 if (afterSale == null) {
367 378 throw exception(AFTER_SALE_NOT_FOUND);
368 379 }
369   - if (ObjectUtils.equalsAny(afterSale.getStatus(), TradeAfterSaleStatusEnum.APPLY.getStatus(),
370   - TradeAfterSaleStatusEnum.SELLER_AGREE.getStatus())) {
371   - throw exception(AFTER_SALE_CANCEL_FAIL_STATUS_NOT_APPLY_OR_AGREE);
  380 + if (!ObjectUtils.equalsAny(afterSale.getStatus(), TradeAfterSaleStatusEnum.APPLY.getStatus(),
  381 + TradeAfterSaleStatusEnum.SELLER_AGREE.getStatus(),
  382 + TradeAfterSaleStatusEnum.BUYER_DELIVERY.getStatus())) {
  383 + throw exception(AFTER_SALE_CANCEL_FAIL_STATUS_NOT_APPLY_OR_AGREE_OR_BUYER_DELIVERY);
372 384 }
373 385  
374 386 // 更新售后单的状态为【已取消】
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressService.java
1 1 package cn.iocoder.yudao.module.trade.service.delivery;
2 2  
3   -import java.util.*;
4   -import javax.validation.*;
5   -
6 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 4 import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressCreateReqVO;
8 5 import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressExportReqVO;
... ... @@ -10,6 +7,9 @@ import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.Delive
10 7 import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressUpdateReqVO;
11 8 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO;
12 9  
  10 +import javax.validation.Valid;
  11 +import java.util.List;
  12 +
13 13 /**
14 14 * 快递公司 Service 接口
15 15 *
... ... @@ -48,14 +48,6 @@ public interface DeliveryExpressService {
48 48 DeliveryExpressDO getDeliveryExpress(Long id);
49 49  
50 50 /**
51   - * 获得快递公司列表
52   - *
53   - * @param ids 编号
54   - * @return 快递公司列表
55   - */
56   - List<DeliveryExpressDO> getDeliveryExpressList(Collection<Long> ids);
57   -
58   - /**
59 51 * 获得快递公司分页
60 52 *
61 53 * @param pageReqVO 分页查询
... ... @@ -71,4 +63,12 @@ public interface DeliveryExpressService {
71 63 */
72 64 List<DeliveryExpressDO> getDeliveryExpressList(DeliveryExpressExportReqVO exportReqVO);
73 65  
  66 + /**
  67 + * 获得快递公司列表
  68 + *
  69 + * @param status 状态
  70 + * @return 快递公司列表
  71 + */
  72 + List<DeliveryExpressDO> getDeliveryExpressList(Integer status);
  73 +
74 74 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressServiceImpl.java
... ... @@ -9,14 +9,14 @@ import cn.iocoder.yudao.module.trade.convert.delivery.DeliveryExpressConvert;
9 9 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO;
10 10 import cn.iocoder.yudao.module.trade.dal.mysql.delivery.DeliveryExpressMapper;
11 11 import org.springframework.stereotype.Service;
12   -import javax.annotation.Resource;
13 12 import org.springframework.validation.annotation.Validated;
14 13  
15   -import java.util.*;
16   -
  14 +import javax.annotation.Resource;
  15 +import java.util.List;
17 16  
18 17 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
19   -import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*;
  18 +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.EXPRESS_CODE_DUPLICATE;
  19 +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.EXPRESS_NOT_EXISTS;
20 20  
21 21 /**
22 22 * 快递公司 Service 实现类
... ... @@ -85,11 +85,6 @@ public class DeliveryExpressServiceImpl implements DeliveryExpressService {
85 85 }
86 86  
87 87 @Override
88   - public List<DeliveryExpressDO> getDeliveryExpressList(Collection<Long> ids) {
89   - return deliveryExpressMapper.selectBatchIds(ids);
90   - }
91   -
92   - @Override
93 88 public PageResult<DeliveryExpressDO> getDeliveryExpressPage(DeliveryExpressPageReqVO pageReqVO) {
94 89 return deliveryExpressMapper.selectPage(pageReqVO);
95 90 }
... ... @@ -99,4 +94,9 @@ public class DeliveryExpressServiceImpl implements DeliveryExpressService {
99 94 return deliveryExpressMapper.selectList(exportReqVO);
100 95 }
101 96  
  97 + @Override
  98 + public List<DeliveryExpressDO> getDeliveryExpressList(Integer status) {
  99 + return deliveryExpressMapper.selectListByStatus(status);
  100 + }
  101 +
102 102 }
... ...