Commit 35528e8267ce549ff4bc658ee51d0788afc21089
1 parent
73b92190
trade:【交易售后】查询分页列表
Showing
22 changed files
with
419 additions
and
8 deletions
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/CommonStatusEnum.java
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenBuilder.java
| ... | ... | @@ -18,6 +18,8 @@ import org.springframework.stereotype.Component; |
| 18 | 18 | import java.util.*; |
| 19 | 19 | |
| 20 | 20 | import static cn.hutool.core.text.CharSequenceUtil.*; |
| 21 | +import static cn.hutool.core.util.RandomUtil.randomEle; | |
| 22 | +import static cn.hutool.core.util.RandomUtil.randomInt; | |
| 21 | 23 | |
| 22 | 24 | /** |
| 23 | 25 | * 代码生成器的 Builder,负责: |
| ... | ... | @@ -128,6 +130,7 @@ public class CodegenBuilder { |
| 128 | 130 | // 初始化 Column 列的默认字段 |
| 129 | 131 | processColumnOperation(column); // 处理 CRUD 相关的字段的默认值 |
| 130 | 132 | processColumnUI(column); // 处理 UI 相关的字段的默认值 |
| 133 | + processColumnExample(column); // 处理字段的 swagger example 示例 | |
| 131 | 134 | } |
| 132 | 135 | return columns; |
| 133 | 136 | } |
| ... | ... | @@ -169,4 +172,42 @@ public class CodegenBuilder { |
| 169 | 172 | } |
| 170 | 173 | } |
| 171 | 174 | |
| 175 | + /** | |
| 176 | + * 处理字段的 swagger example 示例 | |
| 177 | + * | |
| 178 | + * @param column 字段 | |
| 179 | + */ | |
| 180 | + private void processColumnExample(CodegenColumnDO column) { | |
| 181 | + // id、price、count 等可能是整数的后缀 | |
| 182 | + if (StrUtil.endWithAnyIgnoreCase(column.getJavaField(), "id", "price", "count")) { | |
| 183 | + column.setExample(String.valueOf(randomInt(1, Short.MAX_VALUE))); | |
| 184 | + return; | |
| 185 | + } | |
| 186 | + // name | |
| 187 | + if (StrUtil.endWithIgnoreCase(column.getJavaField(), "name")) { | |
| 188 | + column.setExample(randomEle(new String[]{"张三", "李四", "王五", "赵六", "芋艿"})); | |
| 189 | + return; | |
| 190 | + } | |
| 191 | + // status | |
| 192 | + if (StrUtil.endWithAnyIgnoreCase(column.getJavaField(), "status", "type")) { | |
| 193 | + column.setExample(randomEle(new String[]{"1", "2"})); | |
| 194 | + return; | |
| 195 | + } | |
| 196 | + // url | |
| 197 | + if (StrUtil.endWithIgnoreCase(column.getColumnName(), "url")) { | |
| 198 | + column.setExample("https://www.iocoder.cn"); | |
| 199 | + return; | |
| 200 | + } | |
| 201 | + // reason | |
| 202 | + if (StrUtil.endWithIgnoreCase(column.getColumnName(), "reason")) { | |
| 203 | + column.setExample(randomEle(new String[]{"不喜欢", "不对", "不好", "不香"})); | |
| 204 | + return; | |
| 205 | + } | |
| 206 | + // description、memo、remark | |
| 207 | + if (StrUtil.endWithAnyIgnoreCase(column.getColumnName(), "description", "memo", "remark")) { | |
| 208 | + column.setExample(randomEle(new String[]{"你猜", "随便", "你说的对"})); | |
| 209 | + return; | |
| 210 | + } | |
| 211 | + } | |
| 212 | + | |
| 172 | 213 | } | ... | ... |
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/TradeAfterSaleStatusEnum.java
| 1 | 1 | package cn.iocoder.yudao.module.trade.enums.aftersale; |
| 2 | 2 | |
| 3 | +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; | |
| 3 | 4 | import lombok.AllArgsConstructor; |
| 4 | 5 | import lombok.Getter; |
| 5 | 6 | |
| 7 | +import java.util.Arrays; | |
| 8 | + | |
| 6 | 9 | /** |
| 7 | 10 | * 售后状态的枚举 |
| 8 | 11 | * |
| ... | ... | @@ -12,7 +15,7 @@ import lombok.Getter; |
| 12 | 15 | */ |
| 13 | 16 | @AllArgsConstructor |
| 14 | 17 | @Getter |
| 15 | -public enum TradeAfterSaleStatusEnum { | |
| 18 | +public enum TradeAfterSaleStatusEnum implements IntArrayValuable { | |
| 16 | 19 | |
| 17 | 20 | APPLY(10,"申请中"), |
| 18 | 21 | SELLER_AGREE(20, "卖家通过"), // 卖家通过售后 |
| ... | ... | @@ -25,6 +28,8 @@ public enum TradeAfterSaleStatusEnum { |
| 25 | 28 | SELLER_REFUSE(63,"卖家拒绝收货"), // 卖家拒绝收货,终止售后 |
| 26 | 29 | ; |
| 27 | 30 | |
| 31 | + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TradeAfterSaleStatusEnum::getStatus).toArray(); | |
| 32 | + | |
| 28 | 33 | /** |
| 29 | 34 | * 状态 |
| 30 | 35 | */ |
| ... | ... | @@ -34,4 +39,9 @@ public enum TradeAfterSaleStatusEnum { |
| 34 | 39 | */ |
| 35 | 40 | private final String name; |
| 36 | 41 | |
| 42 | + @Override | |
| 43 | + public int[] array() { | |
| 44 | + return ARRAYS; | |
| 45 | + } | |
| 46 | + | |
| 37 | 47 | } | ... | ... |
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderAfterSaleStatusEnum.java
| 1 | 1 | package cn.iocoder.yudao.module.trade.enums.order; |
| 2 | 2 | |
| 3 | +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; | |
| 3 | 4 | import lombok.Getter; |
| 4 | 5 | import lombok.RequiredArgsConstructor; |
| 5 | 6 | |
| 7 | +import java.util.Arrays; | |
| 8 | + | |
| 6 | 9 | /** |
| 7 | 10 | * 交易订单 - 售后状态 |
| 8 | 11 | * |
| ... | ... | @@ -10,12 +13,14 @@ import lombok.RequiredArgsConstructor; |
| 10 | 13 | */ |
| 11 | 14 | @RequiredArgsConstructor |
| 12 | 15 | @Getter |
| 13 | -public enum TradeOrderAfterSaleStatusEnum { | |
| 16 | +public enum TradeOrderAfterSaleStatusEnum implements IntArrayValuable { | |
| 14 | 17 | |
| 15 | 18 | NONE(0, "未退款"), |
| 16 | 19 | PART(1, "部分退款"), |
| 17 | 20 | ALL(2, "全部退款"); |
| 18 | 21 | |
| 22 | + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TradeOrderAfterSaleStatusEnum::getStatus).toArray(); | |
| 23 | + | |
| 19 | 24 | /** |
| 20 | 25 | * 状态值 |
| 21 | 26 | */ |
| ... | ... | @@ -25,4 +30,9 @@ public enum TradeOrderAfterSaleStatusEnum { |
| 25 | 30 | */ |
| 26 | 31 | private final String name; |
| 27 | 32 | |
| 33 | + @Override | |
| 34 | + public int[] array() { | |
| 35 | + return ARRAYS; | |
| 36 | + } | |
| 37 | + | |
| 28 | 38 | } | ... | ... |
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderCancelTypeEnum.java
| 1 | 1 | package cn.iocoder.yudao.module.trade.enums.order; |
| 2 | 2 | |
| 3 | +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; | |
| 3 | 4 | import lombok.Getter; |
| 4 | 5 | import lombok.RequiredArgsConstructor; |
| 5 | 6 | |
| 7 | +import java.util.Arrays; | |
| 8 | + | |
| 6 | 9 | /** |
| 7 | 10 | * 交易订单 - 关闭类型 |
| 8 | 11 | * |
| ... | ... | @@ -10,13 +13,15 @@ import lombok.RequiredArgsConstructor; |
| 10 | 13 | */ |
| 11 | 14 | @RequiredArgsConstructor |
| 12 | 15 | @Getter |
| 13 | -public enum TradeOrderCancelTypeEnum { | |
| 16 | +public enum TradeOrderCancelTypeEnum implements IntArrayValuable { | |
| 14 | 17 | |
| 15 | 18 | PAY_TIMEOUT(10, "超时未支付"), |
| 16 | 19 | AFTER_SALE_CLOSE(20, "退款关闭"), |
| 17 | 20 | MEMBER_CANCEL(30, "买家取消"), |
| 18 | 21 | PAY_ON_DELIVERY(40, "已通过货到付款交易"),; // TODO 芋艿:这个类型,是不是可以去掉 |
| 19 | 22 | |
| 23 | + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TradeOrderCancelTypeEnum::getType).toArray(); | |
| 24 | + | |
| 20 | 25 | /** |
| 21 | 26 | * 关闭类型 |
| 22 | 27 | */ |
| ... | ... | @@ -26,4 +31,9 @@ public enum TradeOrderCancelTypeEnum { |
| 26 | 31 | */ |
| 27 | 32 | private final String name; |
| 28 | 33 | |
| 34 | + @Override | |
| 35 | + public int[] array() { | |
| 36 | + return ARRAYS; | |
| 37 | + } | |
| 38 | + | |
| 29 | 39 | } | ... | ... |
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderItemAfterSaleStatusEnum.java
| 1 | 1 | package cn.iocoder.yudao.module.trade.enums.order; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.util.ObjectUtil; |
| 4 | +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; | |
| 4 | 5 | import lombok.Getter; |
| 5 | 6 | import lombok.RequiredArgsConstructor; |
| 6 | 7 | |
| 8 | +import java.util.Arrays; | |
| 9 | + | |
| 7 | 10 | /** |
| 8 | 11 | * 交易订单项 - 售后状态 |
| 9 | 12 | * |
| ... | ... | @@ -11,12 +14,14 @@ import lombok.RequiredArgsConstructor; |
| 11 | 14 | */ |
| 12 | 15 | @RequiredArgsConstructor |
| 13 | 16 | @Getter |
| 14 | -public enum TradeOrderItemAfterSaleStatusEnum { | |
| 17 | +public enum TradeOrderItemAfterSaleStatusEnum implements IntArrayValuable { | |
| 15 | 18 | |
| 16 | 19 | NONE(0, "未申请"), |
| 17 | 20 | APPLY(1, "已申请"), |
| 18 | 21 | SUCCESS(2, "申请成功"); |
| 19 | 22 | |
| 23 | + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TradeOrderItemAfterSaleStatusEnum::getStatus).toArray(); | |
| 24 | + | |
| 20 | 25 | /** |
| 21 | 26 | * 状态值 |
| 22 | 27 | */ |
| ... | ... | @@ -29,6 +34,11 @@ public enum TradeOrderItemAfterSaleStatusEnum { |
| 29 | 34 | // TODO 芋艿:EXPIRED 已失效不允许申请售后 |
| 30 | 35 | // TODO 芋艿:PART_AFTER_SALE 部分售后 |
| 31 | 36 | |
| 37 | + @Override | |
| 38 | + public int[] array() { | |
| 39 | + return ARRAYS; | |
| 40 | + } | |
| 41 | + | |
| 32 | 42 | /** |
| 33 | 43 | * 判断指定状态,是否正处于【未申请】状态 |
| 34 | 44 | * | ... | ... |
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderStatusEnum.java
| 1 | 1 | package cn.iocoder.yudao.module.trade.enums.order; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.util.ObjectUtil; |
| 4 | +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; | |
| 4 | 5 | import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; |
| 5 | 6 | import lombok.Getter; |
| 6 | 7 | import lombok.RequiredArgsConstructor; |
| 7 | 8 | |
| 9 | +import java.util.Arrays; | |
| 10 | + | |
| 8 | 11 | /** |
| 9 | 12 | * 交易订单 - 状态 |
| 10 | 13 | * |
| ... | ... | @@ -12,7 +15,7 @@ import lombok.RequiredArgsConstructor; |
| 12 | 15 | */ |
| 13 | 16 | @RequiredArgsConstructor |
| 14 | 17 | @Getter |
| 15 | -public enum TradeOrderStatusEnum { | |
| 18 | +public enum TradeOrderStatusEnum implements IntArrayValuable { | |
| 16 | 19 | |
| 17 | 20 | UNPAID(0, "未付款"), |
| 18 | 21 | PAID(10, "已付款"), // 例如说,拼团订单,支付后,需要拼团成功后,才会处于待发货 |
| ... | ... | @@ -23,6 +26,8 @@ public enum TradeOrderStatusEnum { |
| 23 | 26 | |
| 24 | 27 | // TODO 芋艿: TAKE("待核验"):虚拟订单需要核验商品 |
| 25 | 28 | |
| 29 | + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TradeOrderStatusEnum::getStatus).toArray(); | |
| 30 | + | |
| 26 | 31 | /** |
| 27 | 32 | * 状态值 |
| 28 | 33 | */ |
| ... | ... | @@ -32,6 +37,11 @@ public enum TradeOrderStatusEnum { |
| 32 | 37 | */ |
| 33 | 38 | private final String name; |
| 34 | 39 | |
| 40 | + @Override | |
| 41 | + public int[] array() { | |
| 42 | + return ARRAYS; | |
| 43 | + } | |
| 44 | + | |
| 35 | 45 | /** |
| 36 | 46 | * 判断指定状态,是否正处于【已取消】状态 |
| 37 | 47 | * | ... | ... |
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderTypeEnum.java
| 1 | 1 | package cn.iocoder.yudao.module.trade.enums.order; |
| 2 | 2 | |
| 3 | +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; | |
| 3 | 4 | import lombok.Getter; |
| 4 | 5 | import lombok.RequiredArgsConstructor; |
| 5 | 6 | |
| 7 | +import java.util.Arrays; | |
| 8 | + | |
| 6 | 9 | /** |
| 7 | 10 | * 交易订单 - 类型 |
| 8 | 11 | * |
| ... | ... | @@ -10,13 +13,15 @@ import lombok.RequiredArgsConstructor; |
| 10 | 13 | */ |
| 11 | 14 | @RequiredArgsConstructor |
| 12 | 15 | @Getter |
| 13 | -public enum TradeOrderTypeEnum { | |
| 16 | +public enum TradeOrderTypeEnum implements IntArrayValuable { | |
| 14 | 17 | |
| 15 | 18 | NORMAL(0, "普通订单"), |
| 16 | 19 | SECKILL(1, "秒杀订单"), |
| 17 | 20 | TEAM(2, "拼团订单"), |
| 18 | 21 | BARGAIN(3, "砍价订单"); |
| 19 | 22 | |
| 23 | + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TradeOrderTypeEnum::getType).toArray(); | |
| 24 | + | |
| 20 | 25 | /** |
| 21 | 26 | * 类型 |
| 22 | 27 | */ |
| ... | ... | @@ -26,4 +31,9 @@ public enum TradeOrderTypeEnum { |
| 26 | 31 | */ |
| 27 | 32 | private final String name; |
| 28 | 33 | |
| 34 | + @Override | |
| 35 | + public int[] array() { | |
| 36 | + return ARRAYS; | |
| 37 | + } | |
| 38 | + | |
| 29 | 39 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.java
| 1 | 1 | package cn.iocoder.yudao.module.trade.controller.admin.aftersale; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 4 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 4 | 5 | import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleDisagreeReqVO; |
| 6 | +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSalePageReqVO; | |
| 7 | +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleRespVO; | |
| 8 | +import cn.iocoder.yudao.module.trade.convert.aftersale.TradeAfterSaleConvert; | |
| 9 | +import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO; | |
| 5 | 10 | import cn.iocoder.yudao.module.trade.service.aftersale.TradeAfterSaleService; |
| 6 | 11 | import io.swagger.annotations.Api; |
| 7 | 12 | import io.swagger.annotations.ApiImplicitParam; |
| ... | ... | @@ -12,6 +17,7 @@ import org.springframework.validation.annotation.Validated; |
| 12 | 17 | import org.springframework.web.bind.annotation.*; |
| 13 | 18 | |
| 14 | 19 | import javax.annotation.Resource; |
| 20 | +import javax.validation.Valid; | |
| 15 | 21 | |
| 16 | 22 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 17 | 23 | import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; |
| ... | ... | @@ -27,6 +33,14 @@ public class TradeAfterSaleController { |
| 27 | 33 | @Resource |
| 28 | 34 | private TradeAfterSaleService afterSaleService; |
| 29 | 35 | |
| 36 | + @GetMapping("/page") | |
| 37 | + @ApiOperation("获得交易售后分页") | |
| 38 | + @PreAuthorize("@ss.hasPermission('trade:after-sale:query')") | |
| 39 | + public CommonResult<PageResult<TradeAfterSaleRespVO>> getAfterSalePage(@Valid TradeAfterSalePageReqVO pageVO) { | |
| 40 | + PageResult<TradeAfterSaleDO> pageResult = afterSaleService.getAfterSalePage(pageVO); | |
| 41 | + return success(TradeAfterSaleConvert.INSTANCE.convertPage(pageResult)); | |
| 42 | + } | |
| 43 | + | |
| 30 | 44 | @PutMapping("/agree") |
| 31 | 45 | @ApiOperation("同意售后") |
| 32 | 46 | @ApiImplicitParam(name = "id", value = "售后编号", required = true, example = "1") | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleBaseVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.trade.controller.admin.base.property.ProductPropertyRespVO; | |
| 4 | +import io.swagger.annotations.ApiModelProperty; | |
| 5 | +import lombok.Data; | |
| 6 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 7 | + | |
| 8 | +import javax.validation.constraints.NotNull; | |
| 9 | +import java.time.LocalDateTime; | |
| 10 | +import java.util.List; | |
| 11 | + | |
| 12 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | |
| 13 | + | |
| 14 | +/** | |
| 15 | +* 交易售后 Base VO,提供给添加、修改、详细的子 VO 使用 | |
| 16 | +* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 | |
| 17 | +*/ | |
| 18 | +@Data | |
| 19 | +public class TradeAfterSaleBaseVO { | |
| 20 | + | |
| 21 | + @ApiModelProperty(value = "售后流水号", required = true, example = "202211190847450020500077") | |
| 22 | + @NotNull(message = "售后流水号不能为空") | |
| 23 | + private String no; | |
| 24 | + | |
| 25 | + @ApiModelProperty(value = "售后状态", required = true, example = "2", notes = "参见 TradeAfterSaleStatusEnum 枚举") | |
| 26 | + @NotNull(message = "售后状态不能为空") | |
| 27 | + private Integer status; | |
| 28 | + | |
| 29 | + @ApiModelProperty(value = "售后类型", required = true, example = "2", notes = "参见 TradeAfterSaleTypeEnum 枚举") | |
| 30 | + @NotNull(message = "售后类型不能为空") | |
| 31 | + private Integer type; | |
| 32 | + | |
| 33 | + @ApiModelProperty(value = "用户编号", required = true, example = "30337") | |
| 34 | + @NotNull(message = "用户编号不能为空") | |
| 35 | + private Long userId; | |
| 36 | + | |
| 37 | + @ApiModelProperty(value = "申请原因", required = true, example = "不喜欢") | |
| 38 | + @NotNull(message = "申请原因不能为空") | |
| 39 | + private String applyReason; | |
| 40 | + | |
| 41 | + @ApiModelProperty(value = "补充描述", example = "你说的对") | |
| 42 | + private String applyDescription; | |
| 43 | + | |
| 44 | + @ApiModelProperty(value = "补充凭证图片", example = "https://www.iocoder.cn/1.png") | |
| 45 | + private List<String> applyPicUrls; | |
| 46 | + | |
| 47 | + @ApiModelProperty(value = "订单编号", required = true, example = "18078") | |
| 48 | + @NotNull(message = "订单编号不能为空") | |
| 49 | + private Long orderId; | |
| 50 | + | |
| 51 | + @ApiModelProperty(value = "订单流水号", required = true, example = "2022111917190001") | |
| 52 | + @NotNull(message = "订单流水号不能为空") | |
| 53 | + private Long orderNo; | |
| 54 | + | |
| 55 | + @ApiModelProperty(value = "订单项编号", required = true, example = "572") | |
| 56 | + @NotNull(message = "订单项编号不能为空") | |
| 57 | + private Long orderItemId; | |
| 58 | + | |
| 59 | + @ApiModelProperty(value = "商品 SPU 编号", required = true, example = "2888") | |
| 60 | + @NotNull(message = "商品 SPU 编号不能为空") | |
| 61 | + private Long spuId; | |
| 62 | + | |
| 63 | + @ApiModelProperty(value = "商品 SPU 名称", required = true, example = "李四") | |
| 64 | + @NotNull(message = "商品 SPU 名称不能为空") | |
| 65 | + private String spuName; | |
| 66 | + | |
| 67 | + @ApiModelProperty(value = "商品 SKU 编号", required = true, example = "15657") | |
| 68 | + @NotNull(message = "商品 SKU 编号不能为空") | |
| 69 | + private Long skuId; | |
| 70 | + | |
| 71 | + @ApiModelProperty(value = "规格值数组") | |
| 72 | + private List<ProductPropertyRespVO> properties; | |
| 73 | + | |
| 74 | + @ApiModelProperty(value = "商品图片", example = "https://www.iocoder.cn/2.png") | |
| 75 | + private String picUrl; | |
| 76 | + | |
| 77 | + @ApiModelProperty(value = "购买数量", required = true, example = "20012") | |
| 78 | + @NotNull(message = "购买数量不能为空") | |
| 79 | + private Integer count; | |
| 80 | + | |
| 81 | + @ApiModelProperty(value = "审批时间") | |
| 82 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 83 | + private LocalDateTime auditTime; | |
| 84 | + | |
| 85 | + @ApiModelProperty(value = "审批人", example = "30835") | |
| 86 | + private Long auditUserId; | |
| 87 | + | |
| 88 | + @ApiModelProperty(value = "审批备注", example = "不香") | |
| 89 | + private String auditReason; | |
| 90 | + | |
| 91 | + @ApiModelProperty(value = "退款金额,单位:分", required = true, example = "18077") | |
| 92 | + @NotNull(message = "退款金额,单位:分不能为空") | |
| 93 | + private Integer refundPrice; | |
| 94 | + | |
| 95 | + @ApiModelProperty(value = "支付退款编号", example = "10271") | |
| 96 | + private Long payRefundId; | |
| 97 | + | |
| 98 | + @ApiModelProperty(value = "退款时间") | |
| 99 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 100 | + private LocalDateTime refundTime; | |
| 101 | + | |
| 102 | + @ApiModelProperty(value = "退货物流公司编号", example = "10") | |
| 103 | + private Long logisticsId; | |
| 104 | + | |
| 105 | + @ApiModelProperty(value = "退货物流单号", example = "610003952009") | |
| 106 | + private String logisticsNo; | |
| 107 | + | |
| 108 | + @ApiModelProperty(value = "退货时间") | |
| 109 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 110 | + private LocalDateTime deliveryTime; | |
| 111 | + | |
| 112 | + @ApiModelProperty(value = "收货时间") | |
| 113 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 114 | + private LocalDateTime receiveTime; | |
| 115 | + | |
| 116 | + @ApiModelProperty(value = "收货备注", example = "不喜欢") | |
| 117 | + private String receiveReason; | |
| 118 | + | |
| 119 | +} | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSalePageReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | |
| 4 | +import cn.iocoder.yudao.framework.common.validation.InEnum; | |
| 5 | +import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleStatusEnum; | |
| 6 | +import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleTypeEnum; | |
| 7 | +import io.swagger.annotations.ApiModel; | |
| 8 | +import io.swagger.annotations.ApiModelProperty; | |
| 9 | +import lombok.Data; | |
| 10 | +import lombok.EqualsAndHashCode; | |
| 11 | +import lombok.ToString; | |
| 12 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 13 | + | |
| 14 | +import java.time.LocalDateTime; | |
| 15 | + | |
| 16 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | |
| 17 | + | |
| 18 | +@ApiModel("管理后台 - 交易售后分页 Request VO") | |
| 19 | +@Data | |
| 20 | +@EqualsAndHashCode(callSuper = true) | |
| 21 | +@ToString(callSuper = true) | |
| 22 | +public class TradeAfterSalePageReqVO extends PageParam { | |
| 23 | + | |
| 24 | + @ApiModelProperty(value = "售后流水号", example = "202211190847450020500077", notes = "模糊匹配") | |
| 25 | + private String no; | |
| 26 | + | |
| 27 | + @ApiModelProperty(value = "售后状态", example = "2", notes = "参见 TradeAfterSaleStatusEnum 枚举") | |
| 28 | + @InEnum(value = TradeAfterSaleStatusEnum.class, message = "售后状态必须是 {value}") | |
| 29 | + private Integer status; | |
| 30 | + | |
| 31 | + @ApiModelProperty(value = "售后类型", example = "2", notes = "参见 TradeAfterSaleTypeEnum 枚举") | |
| 32 | + @InEnum(value = TradeAfterSaleTypeEnum.class, message = "售后类型必须是 {value}") | |
| 33 | + private Integer type; | |
| 34 | + | |
| 35 | + @ApiModelProperty(value = "订单编号", example = "18078", notes = "模糊匹配") | |
| 36 | + private String orderNo; | |
| 37 | + | |
| 38 | + @ApiModelProperty(value = "商品 SPU 名称", example = "李四", notes = "模糊匹配") | |
| 39 | + private String spuName; | |
| 40 | + | |
| 41 | + @ApiModelProperty(value = "创建时间") | |
| 42 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 43 | + private LocalDateTime[] createTime; | |
| 44 | + | |
| 45 | +} | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo; | |
| 2 | + | |
| 3 | +import io.swagger.annotations.ApiModel; | |
| 4 | +import io.swagger.annotations.ApiModelProperty; | |
| 5 | +import lombok.Data; | |
| 6 | +import lombok.EqualsAndHashCode; | |
| 7 | +import lombok.ToString; | |
| 8 | + | |
| 9 | +import java.time.LocalDateTime; | |
| 10 | + | |
| 11 | +@ApiModel("管理后台 - 交易售后 Response VO") | |
| 12 | +@Data | |
| 13 | +@EqualsAndHashCode(callSuper = true) | |
| 14 | +@ToString(callSuper = true) | |
| 15 | +public class TradeAfterSaleRespVO extends TradeAfterSaleBaseVO { | |
| 16 | + | |
| 17 | + @ApiModelProperty(value = "售后编号", required = true, example = "27630") | |
| 18 | + private Long id; | |
| 19 | + | |
| 20 | + @ApiModelProperty(value = "创建时间", required = true) | |
| 21 | + private LocalDateTime createTime; | |
| 22 | + | |
| 23 | +} | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/base/package-info.java
0 → 100644
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/base/property/ProductPropertyRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.trade.controller.admin.base.property; | |
| 2 | + | |
| 3 | +import io.swagger.annotations.ApiModel; | |
| 4 | +import io.swagger.annotations.ApiModelProperty; | |
| 5 | +import lombok.Data; | |
| 6 | + | |
| 7 | +@ApiModel("管理后台 - 商品规格 Request VO") | |
| 8 | +@Data | |
| 9 | +public class ProductPropertyRespVO { | |
| 10 | + | |
| 11 | + @ApiModelProperty(value = "属性编号", required = true, example = "1") | |
| 12 | + private Long propertyId; | |
| 13 | + | |
| 14 | + @ApiModelProperty(value = "属性值编号", required = true, example = "2") | |
| 15 | + private Long valueId; | |
| 16 | + | |
| 17 | +} | ... | ... |
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.iocoder.yudao.framework.common.pojo.PageResult; | |
| 3 | 4 | import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO; |
| 5 | +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleRespVO; | |
| 4 | 6 | import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleCreateReqVO; |
| 5 | 7 | import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO; |
| 6 | 8 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; |
| ... | ... | @@ -32,4 +34,6 @@ public interface TradeAfterSaleConvert { |
| 32 | 34 | PayRefundCreateReqDTO convert(String userIp, TradeAfterSaleDO afterSale, |
| 33 | 35 | TradeOrderProperties orderProperties); |
| 34 | 36 | |
| 37 | + PageResult<TradeAfterSaleRespVO> convertPage(PageResult<TradeAfterSaleDO> page); | |
| 38 | + | |
| 35 | 39 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/TradeAfterSaleDO.java
| ... | ... | @@ -81,6 +81,12 @@ public class TradeAfterSaleDO extends BaseDO { |
| 81 | 81 | */ |
| 82 | 82 | private Long orderId; |
| 83 | 83 | /** |
| 84 | + * 订单流水号 | |
| 85 | + * | |
| 86 | + * 冗余 {@link TradeOrderDO#getNo()} | |
| 87 | + */ | |
| 88 | + private String orderNo; | |
| 89 | + /** | |
| 84 | 90 | * 交易订单项编号 |
| 85 | 91 | * |
| 86 | 92 | * 关联 {@link TradeOrderItemDO#getId()} | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderItemDO.java
| ... | ... | @@ -11,6 +11,7 @@ import lombok.Data; |
| 11 | 11 | import lombok.EqualsAndHashCode; |
| 12 | 12 | import lombok.experimental.Accessors; |
| 13 | 13 | |
| 14 | +import java.io.Serializable; | |
| 14 | 15 | import java.util.List; |
| 15 | 16 | |
| 16 | 17 | /** |
| ... | ... | @@ -153,7 +154,7 @@ public class TradeOrderItemDO extends BaseDO { |
| 153 | 154 | * 商品属性 |
| 154 | 155 | */ |
| 155 | 156 | @Data |
| 156 | - public static class Property { | |
| 157 | + public static class Property implements Serializable { | |
| 157 | 158 | |
| 158 | 159 | /** |
| 159 | 160 | * 属性编号 | ... | ... |
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.PageResult; | |
| 3 | 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 5 | +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | |
| 6 | +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSalePageReqVO; | |
| 4 | 7 | import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO; |
| 5 | 8 | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
| 6 | 9 | import org.apache.ibatis.annotations.Mapper; |
| ... | ... | @@ -8,6 +11,17 @@ import org.apache.ibatis.annotations.Mapper; |
| 8 | 11 | @Mapper |
| 9 | 12 | public interface TradeAfterSaleMapper extends BaseMapperX<TradeAfterSaleDO> { |
| 10 | 13 | |
| 14 | + default PageResult<TradeAfterSaleDO> selectPage(TradeAfterSalePageReqVO reqVO) { | |
| 15 | + return selectPage(reqVO, new LambdaQueryWrapperX<TradeAfterSaleDO>() | |
| 16 | + .likeIfPresent(TradeAfterSaleDO::getNo, reqVO.getNo()) | |
| 17 | + .eqIfPresent(TradeAfterSaleDO::getStatus, reqVO.getStatus()) | |
| 18 | + .eqIfPresent(TradeAfterSaleDO::getType, reqVO.getType()) | |
| 19 | + .likeIfPresent(TradeAfterSaleDO::getOrderNo, reqVO.getOrderNo()) | |
| 20 | + .likeIfPresent(TradeAfterSaleDO::getSpuName, reqVO.getSpuName()) | |
| 21 | + .betweenIfPresent(TradeAfterSaleDO::getCreateTime, reqVO.getCreateTime()) | |
| 22 | + .orderByDesc(TradeAfterSaleDO::getId)); | |
| 23 | + } | |
| 24 | + | |
| 11 | 25 | default int updateByIdAndStatus(Long id, Integer status, TradeAfterSaleDO update) { |
| 12 | 26 | return update(update, new LambdaUpdateWrapper<TradeAfterSaleDO>() |
| 13 | 27 | .eq(TradeAfterSaleDO::getId, id).eq(TradeAfterSaleDO::getStatus, status)); | ... | ... |
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.PageResult; | |
| 3 | 4 | import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleDisagreeReqVO; |
| 5 | +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSalePageReqVO; | |
| 4 | 6 | import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleRefuseReqVO; |
| 5 | 7 | import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleCreateReqVO; |
| 6 | 8 | import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleDeliveryReqVO; |
| 9 | +import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO; | |
| 7 | 10 | |
| 8 | 11 | /** |
| 9 | 12 | * 交易售后 Service 接口 |
| ... | ... | @@ -13,6 +16,14 @@ import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSa |
| 13 | 16 | public interface TradeAfterSaleService { |
| 14 | 17 | |
| 15 | 18 | /** |
| 19 | + * 获得交易售后分页 | |
| 20 | + * | |
| 21 | + * @param pageReqVO 分页查询 | |
| 22 | + * @return 交易售后分页 | |
| 23 | + */ | |
| 24 | + PageResult<TradeAfterSaleDO> getAfterSalePage(TradeAfterSalePageReqVO pageReqVO); | |
| 25 | + | |
| 26 | + /** | |
| 16 | 27 | * 【会员】创建交易售后 |
| 17 | 28 | * <p> |
| 18 | 29 | * 一般是用户发起售后请求 | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java
| ... | ... | @@ -2,9 +2,11 @@ package cn.iocoder.yudao.module.trade.service.aftersale; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.util.ObjectUtil; |
| 4 | 4 | import cn.hutool.core.util.RandomUtil; |
| 5 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 5 | 6 | import cn.iocoder.yudao.module.pay.api.refund.PayRefundApi; |
| 6 | 7 | import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO; |
| 7 | 8 | import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleDisagreeReqVO; |
| 9 | +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSalePageReqVO; | |
| 8 | 10 | import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleRefuseReqVO; |
| 9 | 11 | import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleCreateReqVO; |
| 10 | 12 | import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleDeliveryReqVO; |
| ... | ... | @@ -53,6 +55,11 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService { |
| 53 | 55 | private TradeOrderProperties tradeOrderProperties; |
| 54 | 56 | |
| 55 | 57 | @Override |
| 58 | + public PageResult<TradeAfterSaleDO> getAfterSalePage(TradeAfterSalePageReqVO pageReqVO) { | |
| 59 | + return tradeAfterSaleMapper.selectPage(pageReqVO); | |
| 60 | + } | |
| 61 | + | |
| 62 | + @Override | |
| 56 | 63 | @Transactional(rollbackFor = Exception.class) |
| 57 | 64 | public Long createAfterSale(Long userId, AppTradeAfterSaleCreateReqVO createReqVO) { |
| 58 | 65 | // 第一步,前置校验 | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceTest.java
| 1 | 1 | package cn.iocoder.yudao.module.trade.service.aftersale; |
| 2 | 2 | |
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 3 | 4 | import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; |
| 4 | 5 | import cn.iocoder.yudao.module.pay.api.refund.PayRefundApi; |
| 6 | +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSalePageReqVO; | |
| 5 | 7 | import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleCreateReqVO; |
| 6 | 8 | import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO; |
| 7 | 9 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; |
| ... | ... | @@ -18,7 +20,10 @@ import org.springframework.boot.test.mock.mockito.MockBean; |
| 18 | 20 | import org.springframework.context.annotation.Import; |
| 19 | 21 | |
| 20 | 22 | import javax.annotation.Resource; |
| 23 | +import java.time.LocalDateTime; | |
| 21 | 24 | |
| 25 | +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; | |
| 26 | +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; | |
| 22 | 27 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; |
| 23 | 28 | import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; |
| 24 | 29 | import static java.util.Arrays.asList; |
| ... | ... | @@ -84,4 +89,44 @@ public class TradeAfterSaleServiceTest extends BaseDbUnitTest { |
| 84 | 89 | assertNull(afterSale.getReceiveReason()); |
| 85 | 90 | } |
| 86 | 91 | |
| 92 | + @Test | |
| 93 | + public void testGetAfterSalePage() { | |
| 94 | + // mock 数据 | |
| 95 | + TradeAfterSaleDO dbAfterSale = randomPojo(TradeAfterSaleDO.class, o -> { // 等会查询到 | |
| 96 | + o.setNo("202211190847450020500077"); | |
| 97 | + o.setStatus(TradeAfterSaleStatusEnum.APPLY.getStatus()); | |
| 98 | + o.setType(TradeAfterSaleTypeEnum.RETURN_AND_REFUND.getType()); | |
| 99 | + o.setOrderNo("202211190847450020500011"); | |
| 100 | + o.setSpuName("芋艿"); | |
| 101 | + o.setCreateTime(buildTime(2022, 1, 15)); | |
| 102 | + }); | |
| 103 | + tradeAfterSaleMapper.insert(dbAfterSale); | |
| 104 | + // 测试 no 不匹配 | |
| 105 | + tradeAfterSaleMapper.insert(cloneIgnoreId(dbAfterSale, o -> o.setNo("202211190847450020500066"))); | |
| 106 | + // 测试 status 不匹配 | |
| 107 | + tradeAfterSaleMapper.insert(cloneIgnoreId(dbAfterSale, o -> o.setStatus(TradeAfterSaleStatusEnum.SELLER_REFUSE.getStatus()))); | |
| 108 | + // 测试 type 不匹配 | |
| 109 | + tradeAfterSaleMapper.insert(cloneIgnoreId(dbAfterSale, o -> o.setType(TradeAfterSaleTypeEnum.REFUND.getType()))); | |
| 110 | + // 测试 orderNo 不匹配 | |
| 111 | + tradeAfterSaleMapper.insert(cloneIgnoreId(dbAfterSale, o -> o.setOrderNo("202211190847450020500022"))); | |
| 112 | + // 测试 spuName 不匹配 | |
| 113 | + tradeAfterSaleMapper.insert(cloneIgnoreId(dbAfterSale, o -> o.setSpuName("土豆"))); | |
| 114 | + // 测试 createTime 不匹配 | |
| 115 | + tradeAfterSaleMapper.insert(cloneIgnoreId(dbAfterSale, o -> o.setCreateTime(buildTime(2022, 1, 20)))); | |
| 116 | + // 准备参数 | |
| 117 | + TradeAfterSalePageReqVO reqVO = new TradeAfterSalePageReqVO(); | |
| 118 | + reqVO.setNo("20221119084745002050007"); | |
| 119 | + reqVO.setStatus(TradeAfterSaleStatusEnum.APPLY.getStatus()); | |
| 120 | + reqVO.setType(TradeAfterSaleTypeEnum.RETURN_AND_REFUND.getType()); | |
| 121 | + reqVO.setOrderNo("20221119084745002050001"); | |
| 122 | + reqVO.setSpuName("芋"); | |
| 123 | + reqVO.setCreateTime(new LocalDateTime[]{buildTime(2022, 1, 1), buildTime(2022, 1, 16)}); | |
| 124 | + | |
| 125 | + // 调用 | |
| 126 | + PageResult<TradeAfterSaleDO> pageResult = tradeAfterSaleService.getAfterSalePage(reqVO); | |
| 127 | + // 断言 | |
| 128 | + assertEquals(1, pageResult.getTotal()); | |
| 129 | + assertEquals(1, pageResult.getList().size()); | |
| 130 | + assertPojoEquals(dbAfterSale, pageResult.getList().get(0)); | |
| 131 | + } | |
| 87 | 132 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql
| ... | ... | @@ -80,6 +80,7 @@ CREATE TABLE IF NOT EXISTS "trade_after_sale" ( |
| 80 | 80 | "apply_description" varchar, |
| 81 | 81 | "apply_pic_urls" varchar, |
| 82 | 82 | "order_id" bigint NOT NULL, |
| 83 | + "order_no" varchar NOT NULL, | |
| 83 | 84 | "order_item_id" bigint NOT NULL, |
| 84 | 85 | "spu_id" bigint NOT NULL, |
| 85 | 86 | "spu_name" varchar NOT NULL, | ... | ... |