Commit 67050eeaa8047c57df1f5e81bac9e79185f9476a
1 parent
40f01171
trade:【交易售后】确认收货
Showing
6 changed files
with
105 additions
and
6 deletions
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java
| @@ -32,7 +32,8 @@ public interface ErrorCodeConstants { | @@ -32,7 +32,8 @@ public interface ErrorCodeConstants { | ||
| 32 | ErrorCode AFTER_SALE_CREATE_FAIL_ORDER_ITEM_APPLIED = new ErrorCode(1011000105, "订单项已申请售后,无法重复申请"); | 32 | ErrorCode AFTER_SALE_CREATE_FAIL_ORDER_ITEM_APPLIED = new ErrorCode(1011000105, "订单项已申请售后,无法重复申请"); |
| 33 | ErrorCode AFTER_SALE_AUDIT_FAIL_STATUS_NOT_APPLY = new ErrorCode(1011000106, "审批失败,售后状态不处于审批中"); | 33 | ErrorCode AFTER_SALE_AUDIT_FAIL_STATUS_NOT_APPLY = new ErrorCode(1011000106, "审批失败,售后状态不处于审批中"); |
| 34 | ErrorCode AFTER_SALE_UPDATE_STATUS_FAIL = new ErrorCode(1011000107, "操作售后单失败,请刷新后重试"); | 34 | ErrorCode AFTER_SALE_UPDATE_STATUS_FAIL = new ErrorCode(1011000107, "操作售后单失败,请刷新后重试"); |
| 35 | - ErrorCode AFTER_SALE_DELIVERY_FAIL_STATUS_NOT_BUYER_RETURN = new ErrorCode(1011000108, "退货失败,售后单状态不处于【买家退货】"); | 35 | + ErrorCode AFTER_SALE_DELIVERY_FAIL_STATUS_NOT_SELLER_PASS = new ErrorCode(1011000108, "退货失败,售后单状态不处于【待买家退货】"); |
| 36 | + ErrorCode AFTER_SALE_CONFIRM_FAIL_STATUS_NOT_BUYER_RETURN = new ErrorCode(1011000109, "确认收货失败,售后单状态不处于【待确认收货】"); | ||
| 36 | 37 | ||
| 37 | // ========== Cart 模块 1-011-001-000 ========== | 38 | // ========== Cart 模块 1-011-001-000 ========== |
| 38 | ErrorCode CARD_ITEM_NOT_FOUND = new ErrorCode(1011002000, "购物车项不存在"); | 39 | ErrorCode CARD_ITEM_NOT_FOUND = new ErrorCode(1011002000, "购物车项不存在"); |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.java
| @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.trade.controller.admin.aftersale; | @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.trade.controller.admin.aftersale; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 4 | import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleAuditReqVO; | 4 | import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleAuditReqVO; |
| 5 | +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleConfirmReqVO; | ||
| 5 | import cn.iocoder.yudao.module.trade.service.aftersale.TradeAfterSaleService; | 6 | import cn.iocoder.yudao.module.trade.service.aftersale.TradeAfterSaleService; |
| 6 | import io.swagger.annotations.Api; | 7 | import io.swagger.annotations.Api; |
| 7 | import io.swagger.annotations.ApiOperation; | 8 | import io.swagger.annotations.ApiOperation; |
| @@ -37,4 +38,12 @@ public class TradeAfterSaleController { | @@ -37,4 +38,12 @@ public class TradeAfterSaleController { | ||
| 37 | return success(true); | 38 | return success(true); |
| 38 | } | 39 | } |
| 39 | 40 | ||
| 41 | + @PutMapping("/confirm") | ||
| 42 | + @ApiOperation("确认收货") | ||
| 43 | + @PreAuthorize("@ss.hasPermission('trade:after-sale:audit')") | ||
| 44 | + public CommonResult<Boolean> confirmAfterSale(@RequestBody TradeAfterSaleConfirmReqVO confirmReqVO) { | ||
| 45 | + afterSaleService.confirmAfterSale(getLoginUserId(), getClientIP(), confirmReqVO); | ||
| 46 | + return success(true); | ||
| 47 | + } | ||
| 48 | + | ||
| 40 | } | 49 | } |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleAuditReqVO.java
| @@ -17,7 +17,7 @@ public class TradeAfterSaleAuditReqVO { | @@ -17,7 +17,7 @@ public class TradeAfterSaleAuditReqVO { | ||
| 17 | @ApiModelProperty(value = "审批结果", required = true, example = "true", | 17 | @ApiModelProperty(value = "审批结果", required = true, example = "true", |
| 18 | notes = "true - 通过;false - 不通过") | 18 | notes = "true - 通过;false - 不通过") |
| 19 | @NotNull(message = "审批结果不能为空") | 19 | @NotNull(message = "审批结果不能为空") |
| 20 | - private Boolean audit; | 20 | + private Boolean pass; |
| 21 | 21 | ||
| 22 | @ApiModelProperty(value = "审批备注", example = "你猜") | 22 | @ApiModelProperty(value = "审批备注", example = "你猜") |
| 23 | private String auditReason; | 23 | private String auditReason; |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleConfirmReqVO.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 | + | ||
| 7 | +import javax.validation.constraints.NotNull; | ||
| 8 | + | ||
| 9 | +@ApiModel("管理后台 - 交易售后确认收货 Request VO") | ||
| 10 | +@Data | ||
| 11 | +public class TradeAfterSaleConfirmReqVO { | ||
| 12 | + | ||
| 13 | + @ApiModelProperty(value = "售后编号", required = true, example = "1024") | ||
| 14 | + @NotNull(message = "售后编号不能为空") | ||
| 15 | + private Long id; | ||
| 16 | + | ||
| 17 | + @ApiModelProperty(value = "收货结果", required = true, example = "true", | ||
| 18 | + notes = "true - 确认收货;false - 拒绝收货") | ||
| 19 | + @NotNull(message = "审批结果不能为空") | ||
| 20 | + private Boolean pass; | ||
| 21 | + | ||
| 22 | + @ApiModelProperty(value = "收货备注", example = "你猜") | ||
| 23 | + private String receiptMemo; | ||
| 24 | + | ||
| 25 | +} |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleService.java
| 1 | package cn.iocoder.yudao.module.trade.service.aftersale; | 1 | package cn.iocoder.yudao.module.trade.service.aftersale; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleAuditReqVO; | 3 | import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleAuditReqVO; |
| 4 | +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleConfirmReqVO; | ||
| 4 | import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleCreateReqVO; | 5 | import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleCreateReqVO; |
| 5 | import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleDeliveryReqVO; | 6 | import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleDeliveryReqVO; |
| 6 | 7 | ||
| @@ -39,4 +40,13 @@ public interface TradeAfterSaleService { | @@ -39,4 +40,13 @@ public interface TradeAfterSaleService { | ||
| 39 | */ | 40 | */ |
| 40 | void deliveryAfterSale(Long userId, AppTradeAfterSaleDeliveryReqVO deliveryReqVO); | 41 | void deliveryAfterSale(Long userId, AppTradeAfterSaleDeliveryReqVO deliveryReqVO); |
| 41 | 42 | ||
| 43 | + /** | ||
| 44 | + * 确认收货 | ||
| 45 | + * | ||
| 46 | + * @param userId 管理员用户编号 | ||
| 47 | + * @param userIp 操作 IP | ||
| 48 | + * @param confirmReqVO 收货 Request 信息 | ||
| 49 | + */ | ||
| 50 | + void confirmAfterSale(Long userId, String userIp, TradeAfterSaleConfirmReqVO confirmReqVO); | ||
| 51 | + | ||
| 42 | } | 52 | } |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java
| 1 | package cn.iocoder.yudao.module.trade.service.aftersale; | 1 | package cn.iocoder.yudao.module.trade.service.aftersale; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.util.ObjectUtil; | ||
| 3 | import cn.hutool.core.util.RandomUtil; | 4 | import cn.hutool.core.util.RandomUtil; |
| 4 | import cn.iocoder.yudao.module.pay.api.refund.PayRefundApi; | 5 | import cn.iocoder.yudao.module.pay.api.refund.PayRefundApi; |
| 5 | import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO; | 6 | import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO; |
| 6 | import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleAuditReqVO; | 7 | import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleAuditReqVO; |
| 8 | +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleConfirmReqVO; | ||
| 7 | import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleCreateReqVO; | 9 | import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleCreateReqVO; |
| 8 | import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleDeliveryReqVO; | 10 | import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleDeliveryReqVO; |
| 9 | import cn.iocoder.yudao.module.trade.convert.aftersale.TradeAfterSaleConvert; | 11 | import cn.iocoder.yudao.module.trade.convert.aftersale.TradeAfterSaleConvert; |
| @@ -129,12 +131,12 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService { | @@ -129,12 +131,12 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService { | ||
| 129 | if (afterSale == null) { | 131 | if (afterSale == null) { |
| 130 | throw exception(AFTER_SALE_NOT_FOUND); | 132 | throw exception(AFTER_SALE_NOT_FOUND); |
| 131 | } | 133 | } |
| 132 | - if (afterSale.getStatus().equals(TradeAfterSaleStatusEnum.APPLY.getStatus())) { | 134 | + if (ObjectUtil.notEqual(afterSale.getStatus(), TradeAfterSaleStatusEnum.APPLY.getStatus())) { |
| 133 | throw exception(AFTER_SALE_AUDIT_FAIL_STATUS_NOT_APPLY); | 135 | throw exception(AFTER_SALE_AUDIT_FAIL_STATUS_NOT_APPLY); |
| 134 | } | 136 | } |
| 135 | 137 | ||
| 136 | // 进行审批 | 138 | // 进行审批 |
| 137 | - if (auditReqVO.getAudit()) { | 139 | + if (auditReqVO.getPass()) { |
| 138 | auditAfterSalePass(userId, userIp, auditReqVO, afterSale); | 140 | auditAfterSalePass(userId, userIp, auditReqVO, afterSale); |
| 139 | } else { | 141 | } else { |
| 140 | auditAfterSaleReject(userId, auditReqVO, afterSale); | 142 | auditAfterSaleReject(userId, auditReqVO, afterSale); |
| @@ -207,8 +209,8 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService { | @@ -207,8 +209,8 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService { | ||
| 207 | if (afterSale == null) { | 209 | if (afterSale == null) { |
| 208 | throw exception(AFTER_SALE_NOT_FOUND); | 210 | throw exception(AFTER_SALE_NOT_FOUND); |
| 209 | } | 211 | } |
| 210 | - if (afterSale.getStatus().equals(TradeAfterSaleStatusEnum.SELLER_PASS.getStatus())) { | ||
| 211 | - throw exception(AFTER_SALE_DELIVERY_FAIL_STATUS_NOT_BUYER_RETURN); | 212 | + if (ObjectUtil.notEqual(afterSale.getStatus(), TradeAfterSaleStatusEnum.SELLER_PASS.getStatus())) { |
| 213 | + throw exception(AFTER_SALE_DELIVERY_FAIL_STATUS_NOT_SELLER_PASS); | ||
| 212 | } | 214 | } |
| 213 | 215 | ||
| 214 | // 更新售后单的物流信息 | 216 | // 更新售后单的物流信息 |
| @@ -222,4 +224,56 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService { | @@ -222,4 +224,56 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService { | ||
| 222 | // TODO 发送售后消息 | 224 | // TODO 发送售后消息 |
| 223 | } | 225 | } |
| 224 | 226 | ||
| 227 | + @Override | ||
| 228 | + public void confirmAfterSale(Long userId, String userIp, | ||
| 229 | + TradeAfterSaleConfirmReqVO confirmReqVO) { | ||
| 230 | + // 校验售后单存在,并状态未审批 | ||
| 231 | + TradeAfterSaleDO afterSale = tradeAfterSaleMapper.selectById(confirmReqVO.getId()); | ||
| 232 | + if (afterSale == null) { | ||
| 233 | + throw exception(AFTER_SALE_NOT_FOUND); | ||
| 234 | + } | ||
| 235 | + if (ObjectUtil.notEqual(afterSale.getStatus(), TradeAfterSaleStatusEnum.BUYER_RETURN.getStatus())) { | ||
| 236 | + throw exception(AFTER_SALE_CONFIRM_FAIL_STATUS_NOT_BUYER_RETURN); | ||
| 237 | + } | ||
| 238 | + | ||
| 239 | + // 进行审批 | ||
| 240 | + if (confirmReqVO.getPass()) { | ||
| 241 | + confirmAfterSalePass(userId, userIp, confirmReqVO, afterSale); | ||
| 242 | + } else { | ||
| 243 | + confirmAfterSaleReject(userId, confirmReqVO, afterSale); | ||
| 244 | + } | ||
| 245 | + } | ||
| 246 | + | ||
| 247 | + private void confirmAfterSalePass(Long userId, String userIp, | ||
| 248 | + TradeAfterSaleConfirmReqVO confirmReqVO, TradeAfterSaleDO afterSale) { | ||
| 249 | + // 更新售后单的状态 | ||
| 250 | + Integer newStatus = TradeAfterSaleStatusEnum.WAIT_REFUND.getStatus(); | ||
| 251 | + updateAfterSaleStatus(afterSale.getId(), TradeAfterSaleStatusEnum.BUYER_RETURN.getStatus(), new TradeAfterSaleDO() | ||
| 252 | + .setStatus(newStatus).setReceiptTime(LocalDateTime.now()).setReceiptMemo(confirmReqVO.getReceiptMemo())); | ||
| 253 | + | ||
| 254 | + // 如果直接退款,则发起售后退款 | ||
| 255 | + if (afterSale.getType().equals(TradeAfterSaleTypeEnum.REFUND.getType())) { | ||
| 256 | + createPayRefund(userIp, afterSale); | ||
| 257 | + } | ||
| 258 | + | ||
| 259 | + // TODO 记录售后日志 | ||
| 260 | + | ||
| 261 | + // TODO 发送售后消息 | ||
| 262 | + } | ||
| 263 | + | ||
| 264 | + private void confirmAfterSaleReject(Long userId, TradeAfterSaleConfirmReqVO confirmReqVO, TradeAfterSaleDO afterSale) { | ||
| 265 | + // 更新售后单的状态 | ||
| 266 | + Integer newStatus = TradeAfterSaleStatusEnum.SELLER_TERMINATION.getStatus(); | ||
| 267 | + updateAfterSaleStatus(afterSale.getId(), TradeAfterSaleStatusEnum.BUYER_RETURN.getStatus(), new TradeAfterSaleDO() | ||
| 268 | + .setStatus(newStatus).setReceiptTime(LocalDateTime.now()).setReceiptMemo(confirmReqVO.getReceiptMemo())); | ||
| 269 | + | ||
| 270 | + // 更新交易订单项的售后状态为【未申请】 | ||
| 271 | + tradeOrderService.updateOrderItemAfterSaleStatus(afterSale.getOrderItemId(), | ||
| 272 | + TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(), TradeOrderItemAfterSaleStatusEnum.NONE.getStatus()); | ||
| 273 | + | ||
| 274 | + // TODO 记录售后日志 | ||
| 275 | + | ||
| 276 | + // TODO 发送售后消息 | ||
| 277 | + } | ||
| 278 | + | ||
| 225 | } | 279 | } |