From 6f4c04d94491a1000d48e07fc7893def9d16ebad Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 2 Oct 2023 15:44:41 +0800 Subject: [PATCH] trade:完善退款详情 --- yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringExpressionUtils.java | 44 -------------------------------------------- yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/AfterSaleStatusEnum.java | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/AfterSaleTypeEnum.java | 37 +++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/AfterSaleWayEnum.java | 37 +++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/TradeAfterSaleStatusEnum.java | 95 ----------------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/TradeAfterSaleTypeEnum.java | 37 ------------------------------------- yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/TradeAfterSaleWayEnum.java | 37 ------------------------------------- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/AfterSaleController.java | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.java | 171 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/AfterSaleBaseVO.java | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/AfterSaleDetailRespVO.java | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/AfterSaleDisagreeReqVO.java | 21 +++++++++++++++++++++ yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/AfterSalePageReqVO.java | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/AfterSaleRefuseReqVO.java | 20 ++++++++++++++++++++ yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/AfterSaleRespPageItemVO.java | 35 +++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleBaseVO.java | 119 ----------------------------------------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleDetailRespVO.java | 51 --------------------------------------------------- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleDisagreeReqVO.java | 21 --------------------- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSalePageReqVO.java | 49 ------------------------------------------------- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleRefuseReqVO.java | 20 -------------------- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleRespPageItemVO.java | 35 ----------------------------------- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/log/AfterSaleLogRespVO.java | 42 ++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/log/TradeAfterSaleLogRespVO.java | 50 -------------------------------------------------- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/AppAfterSaleController.java | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/AppTradeAfterSaleController.java | 81 --------------------------------------------------------------------------------- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppAfterSaleCreateReqVO.java | 40 ++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppAfterSaleDeliveryReqVO.java | 24 ++++++++++++++++++++++++ yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppAfterSaleRespVO.java | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppTradeAfterSaleCreateReqVO.java | 40 ---------------------------------------- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppTradeAfterSaleDeliveryReqVO.java | 24 ------------------------ yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppTradeAfterSaleRespVO.java | 103 ------------------------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/AfterSaleConvert.java | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/AfterSaleLogConvert.java | 15 +++++++++++++++ yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/TradeAfterSaleConvert.java | 89 ----------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderLogConvert.java | 2 +- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/AfterSaleDO.java | 201 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/AfterSaleLogDO.java | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/TradeAfterSaleDO.java | 201 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/TradeAfterSaleLogDO.java | 64 ---------------------------------------------------------------- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderItemDO.java | 4 ++-- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/AfterSaleLogMapper.java | 16 ++++++++++++++++ yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/AfterSaleMapper.java | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/TradeAfterSaleLogMapper.java | 9 --------- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/TradeAfterSaleMapper.java | 51 --------------------------------------------------- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/redis/RedisKeyConstants.java | 18 ++++++++++++++++++ yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/redis/no/TradeNoRedisDAO.java | 44 ++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/redis/no/TradeOrderNoRedisDAO.java | 36 ------------------------------------ yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersale/config/AfterSaleLogConfiguration.java | 22 ++++++++++++++++++++++ yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersale/core/annotations/AfterSaleLog.java | 27 +++++++++++++++++++++++++++ yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersale/core/aop/AfterSaleLogAspect.java | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersale/core/utils/AfterSaleLogUtils.java | 25 +++++++++++++++++++++++++ yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/config/AfterSaleLogConfiguration.java | 22 ---------------------- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/annotations/AfterSaleLog.java | 38 -------------------------------------- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/aop/AfterSaleLogAspect.java | 122 -------------------------------------------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/dto/TradeAfterSaleLogCreateReqDTO.java | 54 ------------------------------------------------------ yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/service/AfterSaleLogService.java | 34 ---------------------------------- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/util/AfterSaleLogUtils.java | 33 --------------------------------- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/core/annotations/TradeOrderLog.java | 2 ++ yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/core/aop/TradeOrderLogAspect.java | 4 ++-- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleLogService.java | 34 ++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleLogServiceImpl.java | 36 ++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleService.java | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleServiceImpl.java | 413 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleService.java | 127 ------------------------------------------------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java | 466 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/bo/AfterSaleLogCreateReqBO.java | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryService.java | 9 ++++----- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryServiceImpl.java | 4 ++-- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java | 6 +++--- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/logger/TradeOrderLogCreateReqBO.java | 2 +- yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleServiceTest.java | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceTest.java | 156 ------------------------------------------------------------------------------------------------------------------------------------------------------------ yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/redis/RedisKeyConstants.java | 2 +- yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/redis/no/PayNoRedisDAO.java | 14 +++++++++++--- 74 files changed, 2457 insertions(+), 2499 deletions(-) create mode 100644 yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/AfterSaleStatusEnum.java create mode 100644 yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/AfterSaleTypeEnum.java create mode 100644 yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/AfterSaleWayEnum.java delete mode 100644 yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/TradeAfterSaleStatusEnum.java delete mode 100644 yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/TradeAfterSaleTypeEnum.java delete mode 100644 yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/TradeAfterSaleWayEnum.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/AfterSaleController.java delete mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/AfterSaleBaseVO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/AfterSaleDetailRespVO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/AfterSaleDisagreeReqVO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/AfterSalePageReqVO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/AfterSaleRefuseReqVO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/AfterSaleRespPageItemVO.java delete mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleBaseVO.java delete mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleDetailRespVO.java delete mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleDisagreeReqVO.java delete mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSalePageReqVO.java delete mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleRefuseReqVO.java delete mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleRespPageItemVO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/log/AfterSaleLogRespVO.java delete mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/log/TradeAfterSaleLogRespVO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/AppAfterSaleController.java delete mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/AppTradeAfterSaleController.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppAfterSaleCreateReqVO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppAfterSaleDeliveryReqVO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppAfterSaleRespVO.java delete mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppTradeAfterSaleCreateReqVO.java delete mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppTradeAfterSaleDeliveryReqVO.java delete mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppTradeAfterSaleRespVO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/AfterSaleConvert.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/AfterSaleLogConvert.java delete mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/TradeAfterSaleConvert.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/AfterSaleDO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/AfterSaleLogDO.java delete mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/TradeAfterSaleDO.java delete mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/TradeAfterSaleLogDO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/AfterSaleLogMapper.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/AfterSaleMapper.java delete mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/TradeAfterSaleLogMapper.java delete mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/TradeAfterSaleMapper.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/redis/RedisKeyConstants.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/redis/no/TradeNoRedisDAO.java delete mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/redis/no/TradeOrderNoRedisDAO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersale/config/AfterSaleLogConfiguration.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersale/core/annotations/AfterSaleLog.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersale/core/aop/AfterSaleLogAspect.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersale/core/utils/AfterSaleLogUtils.java delete mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/config/AfterSaleLogConfiguration.java delete mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/annotations/AfterSaleLog.java delete mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/aop/AfterSaleLogAspect.java delete mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/dto/TradeAfterSaleLogCreateReqDTO.java delete mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/service/AfterSaleLogService.java delete mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/util/AfterSaleLogUtils.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleLogService.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleLogServiceImpl.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleService.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleServiceImpl.java delete mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleService.java delete mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/bo/AfterSaleLogCreateReqBO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleServiceTest.java delete mode 100644 yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceTest.java diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringExpressionUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringExpressionUtils.java index 5e82d5e..ae8bcf9 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringExpressionUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringExpressionUtils.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.framework.common.util.spring; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ArrayUtil; -import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.core.DefaultParameterNameDiscoverer; @@ -87,47 +86,4 @@ public class SpringExpressionUtils { return result; } - /** - * JoinPoint 切面 批量解析 EL 表达式,转换 jspl参数 - * - * @param joinPoint 切面点 - * @param info 返回值 - * @param expressionStrings EL 表达式数组 - * @return Map 结果 - * @author 陈賝 - * @since 2023/6/18 11:20 - */ - // TODO @chenchen: 这个方法,和 parseExpressions 比较接近,是不是可以合并下; - public static Map parseExpression(JoinPoint joinPoint, Object info, List expressionStrings) { - // 如果为空,则不进行解析 - if (CollUtil.isEmpty(expressionStrings)) { - return MapUtil.newHashMap(); - } - - // 第一步,构建解析的上下文 EvaluationContext - // 通过 joinPoint 获取被注解方法 - MethodSignature signature = (MethodSignature) joinPoint.getSignature(); - Method method = signature.getMethod(); - // 使用 spring 的 ParameterNameDiscoverer 获取方法形参名数组 - String[] parameterNames = PARAMETER_NAME_DISCOVERER.getParameterNames(method); - // Spring 的表达式上下文对象 - EvaluationContext context = new StandardEvaluationContext(); - if (ArrayUtil.isNotEmpty(parameterNames)) { - //获取方法参数值 - Object[] args = joinPoint.getArgs(); - for (int i = 0; i < args.length; i++) { - // 替换 SP EL 里的变量值为实际值, 比如 #user --> user对象 - context.setVariable(parameterNames[i], args[i]); - } - context.setVariable("info", info); - } - // 第二步,逐个参数解析 - Map result = MapUtil.newHashMap(expressionStrings.size(), true); - expressionStrings.forEach(key -> { - Object value = EXPRESSION_PARSER.parseExpression(key).getValue(context); - result.put(key, value); - }); - return result; - } - } diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/AfterSaleStatusEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/AfterSaleStatusEnum.java new file mode 100644 index 0000000..23c1b2e --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/AfterSaleStatusEnum.java @@ -0,0 +1,95 @@ +package cn.iocoder.yudao.module.trade.enums.aftersale; + +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; +import java.util.Collection; + +import static cn.hutool.core.util.ArrayUtil.firstMatch; + +/** + * 售后状态的枚举 + * + * 状态流转 + * + * @author 芋道源码 + */ +@AllArgsConstructor +@Getter +public enum AfterSaleStatusEnum implements IntArrayValuable { + + /** + * 【申请售后】 + */ + APPLY(10,"申请中", "会员申请退款"), // 有赞的状态提示:退款申请待商家处理 + /** + * 卖家通过售后;【商品待退货】 + */ + SELLER_AGREE(20, "卖家通过", "商家同意退款"), // 有赞的状态提示:请退货并填写物流信息 + /** + * 买家已退货,等待卖家收货;【商家待收货】 + */ + BUYER_DELIVERY(30,"待卖家收货", "会员填写退货物流信息"), // 有赞的状态提示:退货退款申请待商家处理 + /** + * 卖家已收货,等待平台退款;等待退款【等待退款】 + */ + WAIT_REFUND(40, "等待平台退款", "商家收货"), // 有赞的状态提示:无(有赞无该状态) + /** + * 完成退款【退款成功】 + */ + COMPLETE(50, "完成", "商家确认退款"), // 有赞的状态提示:退款成功 + /** + * 【买家取消】 + */ + BUYER_CANCEL(61, "买家取消售后", "会员取消退款"), // 有赞的状态提示:退款关闭 + /** + * 卖家拒绝售后;商家拒绝【商家拒绝】 + */ + SELLER_DISAGREE(62,"卖家拒绝", "商家拒绝退款"), // 有赞的状态提示:商家不同意退款申请 + /** + * 卖家拒绝收货,终止售后;【商家拒收货】 + */ + SELLER_REFUSE(63,"卖家拒绝收货", "商家拒绝收货"), // 有赞的状态提示:商家拒绝收货,不同意退款 + ; + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(AfterSaleStatusEnum::getStatus).toArray(); + + /** + * 进行中的售后状态 + * + * 不包括已经结束的状态 + */ + public static final Collection APPLYING_STATUSES = Arrays.asList( + APPLY.getStatus(), + SELLER_AGREE.getStatus(), + BUYER_DELIVERY.getStatus(), + WAIT_REFUND.getStatus() + ); + + /** + * 状态 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + /** + * 操作内容 + * + * 目的:记录售后日志的内容 + */ + private final String content; + + @Override + public int[] array() { + return ARRAYS; + } + + public static AfterSaleStatusEnum valueOf(Integer status) { + return firstMatch(value -> value.getStatus().equals(status), values()); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/AfterSaleTypeEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/AfterSaleTypeEnum.java new file mode 100644 index 0000000..dfb32f7 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/AfterSaleTypeEnum.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.trade.enums.aftersale; + +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.util.Arrays; + +/** + * 交易售后 - 类型 + * + * @author 芋道源码 + */ +@RequiredArgsConstructor +@Getter +public enum AfterSaleTypeEnum implements IntArrayValuable { + + IN_SALE(10, "售中退款"), // 交易完成前买家申请退款 + AFTER_SALE(20, "售后退款"); // 交易完成后买家申请退款 + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(AfterSaleTypeEnum::getType).toArray(); + + /** + * 类型 + */ + private final Integer type; + /** + * 类型名 + */ + private final String name; + + @Override + public int[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/AfterSaleWayEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/AfterSaleWayEnum.java new file mode 100644 index 0000000..1d608a1 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/AfterSaleWayEnum.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.trade.enums.aftersale; + +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.util.Arrays; + +/** + * 交易售后 - 方式 + * + * @author Sin + */ +@RequiredArgsConstructor +@Getter +public enum AfterSaleWayEnum implements IntArrayValuable { + + REFUND(10, "仅退款"), + RETURN_AND_REFUND(20, "退货退款"); + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(AfterSaleWayEnum::getWay).toArray(); + + /** + * 方式 + */ + private final Integer way; + /** + * 方式名 + */ + private final String name; + + @Override + public int[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/TradeAfterSaleStatusEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/TradeAfterSaleStatusEnum.java deleted file mode 100644 index 3a8f3d4..0000000 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/TradeAfterSaleStatusEnum.java +++ /dev/null @@ -1,95 +0,0 @@ -package cn.iocoder.yudao.module.trade.enums.aftersale; - -import cn.iocoder.yudao.framework.common.core.IntArrayValuable; -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.util.Arrays; -import java.util.Collection; - -import static cn.hutool.core.util.ArrayUtil.firstMatch; - -/** - * 售后状态的枚举 - * - * 状态流转 - * - * @author 芋道源码 - */ -@AllArgsConstructor -@Getter -public enum TradeAfterSaleStatusEnum implements IntArrayValuable { - - /** - * 【申请售后】 - */ - APPLY(10,"申请中", "会员申请退款"), // 有赞的状态提示:退款申请待商家处理 - /** - * 卖家通过售后;【商品待退货】 - */ - SELLER_AGREE(20, "卖家通过", "商家同意退款"), // 有赞的状态提示:请退货并填写物流信息 - /** - * 买家已退货,等待卖家收货;【商家待收货】 - */ - BUYER_DELIVERY(30,"待卖家收货", "会员填写退货物流信息"), // 有赞的状态提示:退货退款申请待商家处理 - /** - * 卖家已收货,等待平台退款;等待退款【等待退款】 - */ - WAIT_REFUND(40, "等待平台退款", "商家收货"), // 有赞的状态提示:无(有赞无该状态) - /** - * 完成退款【退款成功】 - */ - COMPLETE(50, "完成", "商家确认退款"), // 有赞的状态提示:退款成功 - /** - * 【买家取消】 - */ - BUYER_CANCEL(61, "买家取消售后", "会员取消退款"), // 有赞的状态提示:退款关闭 - /** - * 卖家拒绝售后;商家拒绝【商家拒绝】 - */ - SELLER_DISAGREE(62,"卖家拒绝", "商家拒绝退款"), // 有赞的状态提示:商家不同意退款申请 - /** - * 卖家拒绝收货,终止售后;【商家拒收货】 - */ - SELLER_REFUSE(63,"卖家拒绝收货", "商家拒绝收货"), // 有赞的状态提示:商家拒绝收货,不同意退款 - ; - - public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TradeAfterSaleStatusEnum::getStatus).toArray(); - - /** - * 进行中的售后状态 - * - * 不包括已经结束的状态 - */ - public static final Collection APPLYING_STATUSES = Arrays.asList( - APPLY.getStatus(), - SELLER_AGREE.getStatus(), - BUYER_DELIVERY.getStatus(), - WAIT_REFUND.getStatus() - ); - - /** - * 状态 - */ - private final Integer status; - /** - * 状态名 - */ - private final String name; - /** - * 操作内容 - * - * 目的:记录售后日志的内容 - */ - private final String content; - - @Override - public int[] array() { - return ARRAYS; - } - - public static TradeAfterSaleStatusEnum valueOf(Integer status) { - return firstMatch(value -> value.getStatus().equals(status), values()); - } - -} diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/TradeAfterSaleTypeEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/TradeAfterSaleTypeEnum.java deleted file mode 100644 index d5323aa..0000000 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/TradeAfterSaleTypeEnum.java +++ /dev/null @@ -1,37 +0,0 @@ -package cn.iocoder.yudao.module.trade.enums.aftersale; - -import cn.iocoder.yudao.framework.common.core.IntArrayValuable; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -import java.util.Arrays; - -/** - * 交易售后 - 类型 - * - * @author 芋道源码 - */ -@RequiredArgsConstructor -@Getter -public enum TradeAfterSaleTypeEnum implements IntArrayValuable { - - IN_SALE(10, "售中退款"), // 交易完成前买家申请退款 - AFTER_SALE(20, "售后退款"); // 交易完成后买家申请退款 - - public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TradeAfterSaleTypeEnum::getType).toArray(); - - /** - * 类型 - */ - private final Integer type; - /** - * 类型名 - */ - private final String name; - - @Override - public int[] array() { - return ARRAYS; - } - -} diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/TradeAfterSaleWayEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/TradeAfterSaleWayEnum.java deleted file mode 100644 index 1bbb353..0000000 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/TradeAfterSaleWayEnum.java +++ /dev/null @@ -1,37 +0,0 @@ -package cn.iocoder.yudao.module.trade.enums.aftersale; - -import cn.iocoder.yudao.framework.common.core.IntArrayValuable; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -import java.util.Arrays; - -/** - * 交易售后 - 方式 - * - * @author Sin - */ -@RequiredArgsConstructor -@Getter -public enum TradeAfterSaleWayEnum implements IntArrayValuable { - - REFUND(10, "仅退款"), - RETURN_AND_REFUND(20, "退货退款"); - - public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TradeAfterSaleWayEnum::getWay).toArray(); - - /** - * 方式 - */ - private final Integer way; - /** - * 方式名 - */ - private final String name; - - @Override - public int[] array() { - return ARRAYS; - } - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/AfterSaleController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/AfterSaleController.java new file mode 100644 index 0000000..bfe9b2f --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/AfterSaleController.java @@ -0,0 +1,146 @@ +package cn.iocoder.yudao.module.trade.controller.admin.aftersale; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.member.api.user.MemberUserApi; +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; +import cn.iocoder.yudao.module.pay.api.notify.dto.PayRefundNotifyReqDTO; +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.*; +import cn.iocoder.yudao.module.trade.convert.aftersale.AfterSaleConvert; +import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleLogDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; +import cn.iocoder.yudao.module.trade.service.aftersale.AfterSaleLogService; +import cn.iocoder.yudao.module.trade.service.aftersale.AfterSaleService; +import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.annotation.security.PermitAll; +import javax.validation.Valid; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +@Tag(name = "管理后台 - 售后订单") +@RestController +@RequestMapping("/trade/after-sale") +@Validated +@Slf4j +public class AfterSaleController { + + @Resource + private AfterSaleService afterSaleService; + @Resource + private TradeOrderQueryService tradeOrderQueryService; + @Resource + private AfterSaleLogService afterSaleLogService; + @Resource + private MemberUserApi memberUserApi; + + @GetMapping("/page") + @Operation(summary = "获得售后订单分页") + @PreAuthorize("@ss.hasPermission('trade:after-sale:query')") + public CommonResult> getAfterSalePage(@Valid AfterSalePageReqVO pageVO) { + // 查询售后 + PageResult pageResult = afterSaleService.getAfterSalePage(pageVO); + if (CollUtil.isEmpty(pageResult.getList())) { + return success(PageResult.empty()); + } + + // 查询会员 + Map memberUsers = memberUserApi.getUserMap( + convertSet(pageResult.getList(), AfterSaleDO::getUserId)); + return success(AfterSaleConvert.INSTANCE.convertPage(pageResult, memberUsers)); + } + + @GetMapping("/get-detail") + @Operation(summary = "获得售后订单详情") + @Parameter(name = "id", description = "售后编号", required = true, example = "1") + @PreAuthorize("@ss.hasPermission('trade:after-sale:query')") + public CommonResult getOrderDetail(@RequestParam("id") Long id) { + // 查询订单 + AfterSaleDO afterSale = afterSaleService.getAfterSale(id); + if (afterSale == null) { + return success(null); + } + + // 查询订单 + TradeOrderDO order = tradeOrderQueryService.getOrder(afterSale.getOrderId()); + // 查询订单项 + TradeOrderItemDO orderItem = tradeOrderQueryService.getOrderItem(afterSale.getOrderItemId()); + // 拼接数据 + MemberUserRespDTO user = memberUserApi.getUser(afterSale.getUserId()); + List logs = afterSaleLogService.getAfterSaleLogList(afterSale.getId()); + return success(AfterSaleConvert.INSTANCE.convert(afterSale, order, orderItem, user, logs)); + } + + @PutMapping("/agree") + @Operation(summary = "同意售后") + @Parameter(name = "id", description = "售后编号", required = true, example = "1") + @PreAuthorize("@ss.hasPermission('trade:after-sale:agree')") + public CommonResult agreeAfterSale(@RequestParam("id") Long id) { + afterSaleService.agreeAfterSale(getLoginUserId(), id); + return success(true); + } + + @PutMapping("/disagree") + @Operation(summary = "拒绝售后") + @PreAuthorize("@ss.hasPermission('trade:after-sale:disagree')") + public CommonResult disagreeAfterSale(@RequestBody AfterSaleDisagreeReqVO confirmReqVO) { + afterSaleService.disagreeAfterSale(getLoginUserId(), confirmReqVO); + return success(true); + } + + @PutMapping("/receive") + @Operation(summary = "确认收货") + @Parameter(name = "id", description = "售后编号", required = true, example = "1") + @PreAuthorize("@ss.hasPermission('trade:after-sale:receive')") + public CommonResult receiveAfterSale(@RequestParam("id") Long id) { + afterSaleService.receiveAfterSale(getLoginUserId(), id); + return success(true); + } + + @PutMapping("/refuse") + @Operation(summary = "拒绝收货") + @Parameter(name = "id", description = "售后编号", required = true, example = "1") + @PreAuthorize("@ss.hasPermission('trade:after-sale:receive')") + public CommonResult refuseAfterSale(AfterSaleRefuseReqVO refuseReqVO) { + afterSaleService.refuseAfterSale(getLoginUserId(), refuseReqVO); + return success(true); + } + + @PutMapping("/refund") + @Operation(summary = "确认退款") + @Parameter(name = "id", description = "售后编号", required = true, example = "1") + @PreAuthorize("@ss.hasPermission('trade:after-sale:refund')") + public CommonResult refundAfterSale(@RequestParam("id") Long id) { + afterSaleService.refundAfterSale(getLoginUserId(), getClientIP(), id); + return success(true); + } + + @PostMapping("/update-refunded") + @Operation(summary = "更新售后订单为已退款") // 由 pay-module 支付服务,进行回调,可见 PayNotifyJob + @PermitAll // 无需登录,安全由 PayDemoOrderService 内部校验实现 + @OperateLog(enable = false) // 禁用操作日志,因为没有操作人 + public CommonResult updateAfterRefund(@RequestBody PayRefundNotifyReqDTO notifyReqDTO) { + // 目前业务逻辑,不需要做任何事情 + // 当然,退款会有小概率会失败的情况,可以监控失败状态,进行告警 + log.info("[updateAfterRefund][notifyReqDTO({})]", notifyReqDTO); + return success(true); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.java deleted file mode 100644 index 3b43856..0000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.java +++ /dev/null @@ -1,171 +0,0 @@ -package cn.iocoder.yudao.module.trade.controller.admin.aftersale; - -import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.module.member.api.user.MemberUserApi; -import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; -import cn.iocoder.yudao.module.pay.api.notify.dto.PayRefundNotifyReqDTO; -import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.*; -import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.log.TradeAfterSaleLogRespVO; -import cn.iocoder.yudao.module.trade.convert.aftersale.TradeAfterSaleConvert; -import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO; -import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; -import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; -import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.service.AfterSaleLogService; -import cn.iocoder.yudao.module.trade.service.aftersale.TradeAfterSaleService; -import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.extern.slf4j.Slf4j; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import javax.annotation.Resource; -import javax.annotation.security.PermitAll; -import javax.validation.Valid; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; -import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; - -@Tag(name = "管理后台 - 售后订单") -@RestController -@RequestMapping("/trade/after-sale") -@Validated -@Slf4j -public class TradeAfterSaleController { - - @Resource - private TradeAfterSaleService afterSaleService; - @Resource - private TradeOrderQueryService tradeOrderQueryService; - @Resource - private AfterSaleLogService afterSaleLogService; - @Resource - private MemberUserApi memberUserApi; - - @GetMapping("/page") - @Operation(summary = "获得售后订单分页") - @PreAuthorize("@ss.hasPermission('trade:after-sale:query')") - public CommonResult> getAfterSalePage(@Valid TradeAfterSalePageReqVO pageVO) { - // 查询售后 - PageResult pageResult = afterSaleService.getAfterSalePage(pageVO); - if (CollUtil.isEmpty(pageResult.getList())) { - return success(PageResult.empty()); - } - - // 查询会员 - Map memberUsers = memberUserApi.getUserMap( - convertSet(pageResult.getList(), TradeAfterSaleDO::getUserId)); - return success(TradeAfterSaleConvert.INSTANCE.convertPage(pageResult, memberUsers)); - } - - @GetMapping("/get-detail") - @Operation(summary = "获得售后订单详情") - @Parameter(name = "id", description = "售后编号", required = true, example = "1") - @PreAuthorize("@ss.hasPermission('trade:after-sale:query')") - public CommonResult getOrderDetail(@RequestParam("id") Long id) { - // 查询订单 - TradeAfterSaleDO afterSale = afterSaleService.getAfterSale(id); - if (afterSale == null) { - return success(null); - } - - // 查询订单 - TradeOrderDO order = tradeOrderQueryService.getOrder(afterSale.getOrderId()); - // 查询订单项 - List orderItems = tradeOrderQueryService.getOrderItemListByOrderId(id); - // 拼接数据 - MemberUserRespDTO user = memberUserApi.getUser(afterSale.getUserId()); - // 获取售后日志 - List logs = afterSaleLogService.getLog(afterSale.getId()); - // TODO 方便测试看效果,review 后移除 - if (logs == null) { - logs = new ArrayList<>(); - } - for (int i = 1; i <= 6; i++) { - TradeAfterSaleLogRespVO respVO = new TradeAfterSaleLogRespVO(); - respVO.setId((long) i); - respVO.setUserId((long) i); - respVO.setUserType(i % 2 == 0 ? 2 : 1); - // 模拟系统操作 - if (i == 2) { - respVO.setUserType(3); - } - respVO.setAfterSaleId(id); - respVO.setOrderId((long) i); - respVO.setOrderItemId((long) i); - respVO.setBeforeStatus((i - 1) * 10); - respVO.setAfterStatus(i * 10); - respVO.setContent("66+6"); - respVO.setCreateTime(LocalDateTime.now()); - logs.add(respVO); - } - return success(TradeAfterSaleConvert.INSTANCE.convert(afterSale, order, orderItems, user, logs)); - } - - @PutMapping("/agree") - @Operation(summary = "同意售后") - @Parameter(name = "id", description = "售后编号", required = true, example = "1") - @PreAuthorize("@ss.hasPermission('trade:after-sale:agree')") - public CommonResult agreeAfterSale(@RequestParam("id") Long id) { - afterSaleService.agreeAfterSale(getLoginUserId(), id); - return success(true); - } - - @PutMapping("/disagree") - @Operation(summary = "拒绝售后") - @PreAuthorize("@ss.hasPermission('trade:after-sale:disagree')") - public CommonResult disagreeAfterSale(@RequestBody TradeAfterSaleDisagreeReqVO confirmReqVO) { - afterSaleService.disagreeAfterSale(getLoginUserId(), confirmReqVO); - return success(true); - } - - @PutMapping("/receive") - @Operation(summary = "确认收货") - @Parameter(name = "id", description = "售后编号", required = true, example = "1") - @PreAuthorize("@ss.hasPermission('trade:after-sale:receive')") - public CommonResult receiveAfterSale(@RequestParam("id") Long id) { - afterSaleService.receiveAfterSale(getLoginUserId(), id); - return success(true); - } - - @PutMapping("/refuse") - @Operation(summary = "拒绝收货") - @Parameter(name = "id", description = "售后编号", required = true, example = "1") - @PreAuthorize("@ss.hasPermission('trade:after-sale:receive')") - public CommonResult refuseAfterSale(TradeAfterSaleRefuseReqVO refuseReqVO) { - afterSaleService.refuseAfterSale(getLoginUserId(), refuseReqVO); - return success(true); - } - - @PutMapping("/refund") - @Operation(summary = "确认退款") - @Parameter(name = "id", description = "售后编号", required = true, example = "1") - @PreAuthorize("@ss.hasPermission('trade:after-sale:refund')") - public CommonResult refundAfterSale(@RequestParam("id") Long id) { - afterSaleService.refundAfterSale(getLoginUserId(), getClientIP(), id); - return success(true); - } - - @PostMapping("/update-refunded") - @Operation(summary = "更新售后订单为已退款") // 由 pay-module 支付服务,进行回调,可见 PayNotifyJob - @PermitAll // 无需登录,安全由 PayDemoOrderService 内部校验实现 - @OperateLog(enable = false) // 禁用操作日志,因为没有操作人 - public CommonResult updateAfterRefund(@RequestBody PayRefundNotifyReqDTO notifyReqDTO) { - // 目前业务逻辑,不需要做任何事情 - // 当然,退款会有小概率会失败的情况,可以监控失败状态,进行告警 - log.info("[updateAfterRefund][notifyReqDTO({})]", notifyReqDTO); - return success(true); - } - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/AfterSaleBaseVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/AfterSaleBaseVO.java new file mode 100644 index 0000000..ae7bd39 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/AfterSaleBaseVO.java @@ -0,0 +1,119 @@ +package cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +/** +* 交易售后 Base VO,提供给添加、修改、详细的子 VO 使用 +* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 +*/ +@Data +public class AfterSaleBaseVO { + + @Schema(description = "售后流水号", requiredMode = Schema.RequiredMode.REQUIRED, example = "202211190847450020500077") + @NotNull(message = "售后流水号不能为空") + private String no; + + @Schema(description = "售后状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @NotNull(message = "售后状态不能为空") + private Integer status; + + @Schema(description = "售后类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "20") + @NotNull(message = "售后类型不能为空") + private Integer type; + + @Schema(description = "售后方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @NotNull(message = "售后方式不能为空") + private Integer way; + + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "30337") + @NotNull(message = "用户编号不能为空") + private Long userId; + + @Schema(description = "申请原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "不喜欢") + @NotNull(message = "申请原因不能为空") + private String applyReason; + + @Schema(description = "补充描述", example = "你说的对") + private String applyDescription; + + @Schema(description = "补充凭证图片", example = "https://www.iocoder.cn/1.png") + private List applyPicUrls; + + @Schema(description = "订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18078") + @NotNull(message = "订单编号不能为空") + private Long orderId; + + @Schema(description = "订单流水号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2022111917190001") + @NotNull(message = "订单流水号不能为空") + private String orderNo; + + @Schema(description = "订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "572") + @NotNull(message = "订单项编号不能为空") + private Long orderItemId; + + @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2888") + @NotNull(message = "商品 SPU 编号不能为空") + private Long spuId; + + @Schema(description = "商品 SPU 名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") + @NotNull(message = "商品 SPU 名称不能为空") + private String spuName; + + @Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15657") + @NotNull(message = "商品 SKU 编号不能为空") + private Long skuId; + + @Schema(description = "商品图片", example = "https://www.iocoder.cn/2.png") + private String picUrl; + + @Schema(description = "购买数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20012") + @NotNull(message = "购买数量不能为空") + private Integer count; + + @Schema(description = "审批时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime auditTime; + + @Schema(description = "审批人", example = "30835") + private Long auditUserId; + + @Schema(description = "审批备注", example = "不香") + private String auditReason; + + @Schema(description = "退款金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "18077") + @NotNull(message = "退款金额,单位:分不能为空") + private Integer refundPrice; + + @Schema(description = "支付退款编号", example = "10271") + private Long payRefundId; + + @Schema(description = "退款时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime refundTime; + + @Schema(description = "退货物流公司编号", example = "10") + private Long logisticsId; + + @Schema(description = "退货物流单号", example = "610003952009") + private String logisticsNo; + + @Schema(description = "退货时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime deliveryTime; + + @Schema(description = "收货时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime receiveTime; + + @Schema(description = "收货备注", example = "不喜欢") + private String receiveReason; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/AfterSaleDetailRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/AfterSaleDetailRespVO.java new file mode 100644 index 0000000..3f22077 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/AfterSaleDetailRespVO.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo; + +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.log.AfterSaleLogRespVO; +import cn.iocoder.yudao.module.trade.controller.admin.base.member.user.MemberUserRespVO; +import cn.iocoder.yudao.module.trade.controller.admin.base.product.property.ProductPropertyValueDetailRespVO; +import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderBaseVO; +import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderItemBaseVO; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +@Schema(description = "管理后台 - 售后订单的详情 Response VO") +@Data +public class AfterSaleDetailRespVO extends AfterSaleBaseVO { + + @Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + + + /** + * 订单基本信息 + */ + private TradeOrderBaseVO order; + /** + * 订单项列表 + */ + private OrderItem orderItem; + + /** + * 用户信息 + */ + private MemberUserRespVO user; + + /** + * 售后日志 + */ + private List logs; + + @Schema(description = "管理后台 - 交易订单的详情的订单项目") + @Data + public static class OrderItem extends TradeOrderItemBaseVO { + + /** + * 属性数组 + */ + private List properties; + + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/AfterSaleDisagreeReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/AfterSaleDisagreeReqVO.java new file mode 100644 index 0000000..6fa511a --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/AfterSaleDisagreeReqVO.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +@Schema(description = "管理后台 - 交易售后拒绝 Request VO") +@Data +public class AfterSaleDisagreeReqVO { + + @Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotNull(message = "售后编号不能为空") + private Long id; + + @Schema(description = "审批备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "你猜") + @NotEmpty(message = "审批备注不能为空") + private String auditReason; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/AfterSalePageReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/AfterSalePageReqVO.java new file mode 100644 index 0000000..f74c84b --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/AfterSalePageReqVO.java @@ -0,0 +1,49 @@ +package cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleStatusEnum; +import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleTypeEnum; +import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleWayEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 交易售后分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class AfterSalePageReqVO extends PageParam { + + @Schema(description = "售后流水号", example = "202211190847450020500077") + private String no; + + @Schema(description = "售后状态", example = "10") + @InEnum(value = AfterSaleStatusEnum.class, message = "售后状态必须是 {value}") + private Integer status; + + @Schema(description = "售后类型", example = "20") + @InEnum(value = AfterSaleTypeEnum.class, message = "售后类型必须是 {value}") + private Integer type; + + @Schema(description = "售后方式", example = "10") + @InEnum(value = AfterSaleWayEnum.class, message = "售后方式必须是 {value}") + private Integer way; + + @Schema(description = "订单编号", example = "18078") + private String orderNo; + + @Schema(description = "商品 SPU 名称", example = "李四") + private String spuName; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/AfterSaleRefuseReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/AfterSaleRefuseReqVO.java new file mode 100644 index 0000000..6dfced4 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/AfterSaleRefuseReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +@Schema(description = "管理后台 - 交易售后拒绝收货 Request VO") +@Data +public class AfterSaleRefuseReqVO { + + @Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotNull(message = "售后编号不能为空") + private Long id; + + @Schema(description = "收货备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "你猜") + @NotNull(message = "收货备注不能为空") + private String refuseMemo; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/AfterSaleRespPageItemVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/AfterSaleRespPageItemVO.java new file mode 100644 index 0000000..3e76405 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/AfterSaleRespPageItemVO.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo; + +import cn.iocoder.yudao.module.trade.controller.admin.base.member.user.MemberUserRespVO; +import cn.iocoder.yudao.module.trade.controller.admin.base.product.property.ProductPropertyValueDetailRespVO; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - 交易售后分页的每一条记录 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class AfterSaleRespPageItemVO extends AfterSaleBaseVO { + + @Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "27630") + private Long id; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + + /** + * 商品属性数组 + */ + private List properties; + + /** + * 用户信息 + */ + private MemberUserRespVO user; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleBaseVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleBaseVO.java deleted file mode 100644 index 456fa18..0000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleBaseVO.java +++ /dev/null @@ -1,119 +0,0 @@ -package cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import org.springframework.format.annotation.DateTimeFormat; - -import javax.validation.constraints.NotNull; -import java.time.LocalDateTime; -import java.util.List; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -/** -* 交易售后 Base VO,提供给添加、修改、详细的子 VO 使用 -* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 -*/ -@Data -public class TradeAfterSaleBaseVO { - - @Schema(description = "售后流水号", requiredMode = Schema.RequiredMode.REQUIRED, example = "202211190847450020500077") - @NotNull(message = "售后流水号不能为空") - private String no; - - @Schema(description = "售后状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") - @NotNull(message = "售后状态不能为空") - private Integer status; - - @Schema(description = "售后类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "20") - @NotNull(message = "售后类型不能为空") - private Integer type; - - @Schema(description = "售后方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") - @NotNull(message = "售后方式不能为空") - private Integer way; - - @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "30337") - @NotNull(message = "用户编号不能为空") - private Long userId; - - @Schema(description = "申请原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "不喜欢") - @NotNull(message = "申请原因不能为空") - private String applyReason; - - @Schema(description = "补充描述", example = "你说的对") - private String applyDescription; - - @Schema(description = "补充凭证图片", example = "https://www.iocoder.cn/1.png") - private List applyPicUrls; - - @Schema(description = "订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18078") - @NotNull(message = "订单编号不能为空") - private Long orderId; - - @Schema(description = "订单流水号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2022111917190001") - @NotNull(message = "订单流水号不能为空") - private Long orderNo; - - @Schema(description = "订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "572") - @NotNull(message = "订单项编号不能为空") - private Long orderItemId; - - @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2888") - @NotNull(message = "商品 SPU 编号不能为空") - private Long spuId; - - @Schema(description = "商品 SPU 名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") - @NotNull(message = "商品 SPU 名称不能为空") - private String spuName; - - @Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15657") - @NotNull(message = "商品 SKU 编号不能为空") - private Long skuId; - - @Schema(description = "商品图片", example = "https://www.iocoder.cn/2.png") - private String picUrl; - - @Schema(description = "购买数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20012") - @NotNull(message = "购买数量不能为空") - private Integer count; - - @Schema(description = "审批时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime auditTime; - - @Schema(description = "审批人", example = "30835") - private Long auditUserId; - - @Schema(description = "审批备注", example = "不香") - private String auditReason; - - @Schema(description = "退款金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "18077") - @NotNull(message = "退款金额,单位:分不能为空") - private Integer refundPrice; - - @Schema(description = "支付退款编号", example = "10271") - private Long payRefundId; - - @Schema(description = "退款时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime refundTime; - - @Schema(description = "退货物流公司编号", example = "10") - private Long logisticsId; - - @Schema(description = "退货物流单号", example = "610003952009") - private String logisticsNo; - - @Schema(description = "退货时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime deliveryTime; - - @Schema(description = "收货时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime receiveTime; - - @Schema(description = "收货备注", example = "不喜欢") - private String receiveReason; - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleDetailRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleDetailRespVO.java deleted file mode 100644 index af6db85..0000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleDetailRespVO.java +++ /dev/null @@ -1,51 +0,0 @@ -package cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo; - -import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.log.TradeAfterSaleLogRespVO; -import cn.iocoder.yudao.module.trade.controller.admin.base.member.user.MemberUserRespVO; -import cn.iocoder.yudao.module.trade.controller.admin.base.product.property.ProductPropertyValueDetailRespVO; -import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderBaseVO; -import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderItemBaseVO; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.util.List; - -@Schema(description = "管理后台 - 售后订单的详情 Response VO") -@Data -public class TradeAfterSaleDetailRespVO extends TradeAfterSaleBaseVO { - - @Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Long id; - - /** - * 订单项列表 - */ - private List items; - - /** - * 订单基本信息 - */ - private TradeOrderBaseVO order; - - /** - * 用户信息 - */ - private MemberUserRespVO user; - - /** - * 售后日志 - */ - private List logs; - - @Schema(description = "管理后台 - 交易订单的详情的订单项目") - @Data - public static class Item extends TradeOrderItemBaseVO { - - /** - * 属性数组 - */ - private List properties; - - } - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleDisagreeReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleDisagreeReqVO.java deleted file mode 100644 index 906728a..0000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleDisagreeReqVO.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; - -@Schema(description = "管理后台 - 交易售后拒绝 Request VO") -@Data -public class TradeAfterSaleDisagreeReqVO { - - @Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "售后编号不能为空") - private Long id; - - @Schema(description = "审批备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "你猜") - @NotEmpty(message = "审批备注不能为空") - private String auditReason; - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSalePageReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSalePageReqVO.java deleted file mode 100644 index 4c9431b..0000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSalePageReqVO.java +++ /dev/null @@ -1,49 +0,0 @@ -package cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import cn.iocoder.yudao.framework.common.validation.InEnum; -import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleStatusEnum; -import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleTypeEnum; -import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleWayEnum; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - 交易售后分页 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class TradeAfterSalePageReqVO extends PageParam { - - @Schema(description = "售后流水号", example = "202211190847450020500077") - private String no; - - @Schema(description = "售后状态", example = "10") - @InEnum(value = TradeAfterSaleStatusEnum.class, message = "售后状态必须是 {value}") - private Integer status; - - @Schema(description = "售后类型", example = "20") - @InEnum(value = TradeAfterSaleTypeEnum.class, message = "售后类型必须是 {value}") - private Integer type; - - @Schema(description = "售后方式", example = "10") - @InEnum(value = TradeAfterSaleWayEnum.class, message = "售后方式必须是 {value}") - private Integer way; - - @Schema(description = "订单编号", example = "18078") - private String orderNo; - - @Schema(description = "商品 SPU 名称", example = "李四") - private String spuName; - - @Schema(description = "创建时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime[] createTime; - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleRefuseReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleRefuseReqVO.java deleted file mode 100644 index e826100..0000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleRefuseReqVO.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import javax.validation.constraints.NotNull; - -@Schema(description = "管理后台 - 交易售后拒绝收货 Request VO") -@Data -public class TradeAfterSaleRefuseReqVO { - - @Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "售后编号不能为空") - private Long id; - - @Schema(description = "收货备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "你猜") - @NotNull(message = "收货备注不能为空") - private String refuseMemo; - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleRespPageItemVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleRespPageItemVO.java deleted file mode 100644 index b5af865..0000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleRespPageItemVO.java +++ /dev/null @@ -1,35 +0,0 @@ -package cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo; - -import cn.iocoder.yudao.module.trade.controller.admin.base.member.user.MemberUserRespVO; -import cn.iocoder.yudao.module.trade.controller.admin.base.product.property.ProductPropertyValueDetailRespVO; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -import java.time.LocalDateTime; -import java.util.List; - -@Schema(description = "管理后台 - 交易售后分页的每一条记录 Response VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class TradeAfterSaleRespPageItemVO extends TradeAfterSaleBaseVO { - - @Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "27630") - private Long id; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - private LocalDateTime createTime; - - /** - * 商品属性数组 - */ - private List properties; - - /** - * 用户信息 - */ - private MemberUserRespVO user; - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/log/AfterSaleLogRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/log/AfterSaleLogRespVO.java new file mode 100644 index 0000000..f33dcf3 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/log/AfterSaleLogRespVO.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.log; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 交易售后日志 Response VO") +@Data +public class AfterSaleLogRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20669") + private Long id; + + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "22634") + @NotNull(message = "用户编号不能为空") + private Long userId; + + @Schema(description = "用户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @NotNull(message = "用户类型不能为空") + private Integer userType; + + @Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3023") + @NotNull(message = "售后编号不能为空") + private Long afterSaleId; + + @Schema(description = "售后状态(之前)", example = "2") + private Integer beforeStatus; + + @Schema(description = "售后状态(之后)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "售后状态(之后)不能为空") + private Integer afterStatus; + + @Schema(description = "操作明细", requiredMode = Schema.RequiredMode.REQUIRED, example = "维权完成,退款金额:¥37776.00") + @NotNull(message = "操作明细不能为空") + private String content; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/log/TradeAfterSaleLogRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/log/TradeAfterSaleLogRespVO.java deleted file mode 100644 index d7a1940..0000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/log/TradeAfterSaleLogRespVO.java +++ /dev/null @@ -1,50 +0,0 @@ -package cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.log; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import javax.validation.constraints.NotNull; -import java.time.LocalDateTime; - -@Schema(description = "管理后台 - 交易售后日志 Response VO") -@Data -public class TradeAfterSaleLogRespVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20669") - private Long id; - - @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "22634") - @NotNull(message = "用户编号不能为空") - private Long userId; - - @Schema(description = "用户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") - @NotNull(message = "用户类型不能为空") - private Integer userType; - - @Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3023") - @NotNull(message = "售后编号不能为空") - private Long afterSaleId; - - @Schema(description = "订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25870") - @NotNull(message = "订单编号不能为空") - private Long orderId; - - @Schema(description = "订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23154") - @NotNull(message = "订单项编号不能为空") - private Long orderItemId; - - @Schema(description = "售后状态(之前)", example = "2") - private Integer beforeStatus; - - @Schema(description = "售后状态(之后)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "售后状态(之后)不能为空") - private Integer afterStatus; - - @Schema(description = "操作明细", requiredMode = Schema.RequiredMode.REQUIRED, example = "维权完成,退款金额:¥37776.00") - @NotNull(message = "操作明细不能为空") - private String content; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - private LocalDateTime createTime; - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/AppAfterSaleController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/AppAfterSaleController.java new file mode 100644 index 0000000..06eabbb --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/AppAfterSaleController.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.trade.controller.app.aftersale; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSaleCreateReqVO; +import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSaleDeliveryReqVO; +import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSaleRespVO; +import cn.iocoder.yudao.module.trade.convert.aftersale.AfterSaleConvert; +import cn.iocoder.yudao.module.trade.service.aftersale.AfterSaleService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +@Tag(name = "用户 App - 交易售后") +@RestController +@RequestMapping("/trade/after-sale") +@Validated +@Slf4j +public class AppAfterSaleController { + + @Resource + private AfterSaleService afterSaleService; + + @GetMapping(value = "/page") + @Operation(summary = "获得售后分页") + public CommonResult> getAfterSalePage(PageParam pageParam) { + return success(AfterSaleConvert.INSTANCE.convertPage02( + afterSaleService.getAfterSalePage(getLoginUserId(), pageParam))); + } + + @GetMapping(value = "/get") + @Operation(summary = "获得售后订单") + @Parameter(name = "id", description = "售后编号", required = true, example = "1") + public CommonResult getAfterSale(@RequestParam("id") Long id) { + return success(AfterSaleConvert.INSTANCE.convert(afterSaleService.getAfterSale(getLoginUserId(), id))); + } + + @GetMapping(value = "/get-applying-count") + @Operation(summary = "获得进行中的售后订单数量") + public CommonResult getApplyingAfterSaleCount() { + return success(afterSaleService.getApplyingAfterSaleCount(getLoginUserId())); + } + + @PostMapping(value = "/create") + @Operation(summary = "申请售后") + public CommonResult createAfterSale(@RequestBody AppAfterSaleCreateReqVO createReqVO) { + return success(afterSaleService.createAfterSale(getLoginUserId(), createReqVO)); + } + + @PutMapping(value = "/delivery") + @Operation(summary = "退回货物") + public CommonResult deliveryAfterSale(@RequestBody AppAfterSaleDeliveryReqVO deliveryReqVO) { + afterSaleService.deliveryAfterSale(getLoginUserId(), deliveryReqVO); + return success(true); + } + + @DeleteMapping(value = "/cancel") + @Operation(summary = "取消售后") + @Parameter(name = "id", description = "售后编号", required = true, example = "1") + public CommonResult cancelAfterSale(@RequestParam("id") Long id) { + afterSaleService.cancelAfterSale(getLoginUserId(), id); + return success(true); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/AppTradeAfterSaleController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/AppTradeAfterSaleController.java deleted file mode 100644 index eaf6a1b..0000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/AppTradeAfterSaleController.java +++ /dev/null @@ -1,81 +0,0 @@ -package cn.iocoder.yudao.module.trade.controller.app.aftersale; - -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleCreateReqVO; -import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleDeliveryReqVO; -import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleRespVO; -import cn.iocoder.yudao.module.trade.convert.aftersale.TradeAfterSaleConvert; -import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleOperateTypeEnum; -import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleStatusEnum; -import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.annotations.AfterSaleLog; -import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.util.AfterSaleLogUtils; -import cn.iocoder.yudao.module.trade.service.aftersale.TradeAfterSaleService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.extern.slf4j.Slf4j; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import javax.annotation.Resource; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; - -@Tag(name = "用户 App - 交易售后") -@RestController -@RequestMapping("/trade/after-sale") -@Validated -@Slf4j -public class AppTradeAfterSaleController { - - @Resource - private TradeAfterSaleService afterSaleService; - - @GetMapping(value = "/page") - @Operation(summary = "获得售后分页") - public CommonResult> getAfterSalePage(PageParam pageParam) { - return success(TradeAfterSaleConvert.INSTANCE.convertPage02( - afterSaleService.getAfterSalePage(getLoginUserId(), pageParam))); - } - - @GetMapping(value = "/get") - @Operation(summary = "获得售后订单") - @Parameter(name = "id", description = "售后编号", required = true, example = "1") - public CommonResult getAfterSale(@RequestParam("id") Long id) { - return success(TradeAfterSaleConvert.INSTANCE.convert(afterSaleService.getAfterSale(getLoginUserId(), id))); - } - - @GetMapping(value = "/get-applying-count") - @Operation(summary = "获得进行中的售后订单数量") - public CommonResult getApplyingAfterSaleCount() { - return success(afterSaleService.getApplyingAfterSaleCount(getLoginUserId())); - } - - @PostMapping(value = "/create") - @Operation(summary = "申请售后") - @AfterSaleLog(id = "#info.data", content = "'申请售后:售后编号['+#info.data+'],订单编号['+#createReqVO.orderItemId+'], '", operateType = AfterSaleOperateTypeEnum.MEMBER_CREATE) - public CommonResult createAfterSale(@RequestBody AppTradeAfterSaleCreateReqVO createReqVO) { - AfterSaleLogUtils.setBeforeStatus(0); - AfterSaleLogUtils.setAfterStatus(TradeAfterSaleStatusEnum.APPLY.getStatus()); - return success(afterSaleService.createAfterSale(getLoginUserId(), createReqVO)); - } - - @PutMapping(value = "/delivery") - @Operation(summary = "退回货物") - public CommonResult deliveryAfterSale(@RequestBody AppTradeAfterSaleDeliveryReqVO deliveryReqVO) { - afterSaleService.deliveryAfterSale(getLoginUserId(), deliveryReqVO); - return success(true); - } - - @DeleteMapping(value = "/cancel") - @Operation(summary = "取消售后") - @Parameter(name = "id", description = "售后编号", required = true, example = "1") - public CommonResult cancelAfterSale(@RequestParam("id") Long id) { - afterSaleService.cancelAfterSale(getLoginUserId(), id); - return success(true); - } - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppAfterSaleCreateReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppAfterSaleCreateReqVO.java new file mode 100644 index 0000000..253db62 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppAfterSaleCreateReqVO.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.trade.controller.app.aftersale.vo; + +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleWayEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import java.util.List; + +@Schema(description = "用户 App - 交易售后创建 Request VO") +@Data +public class AppAfterSaleCreateReqVO { + + @Schema(description = "订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotNull(message = "订单项编号不能为空") + private Long orderItemId; + + @Schema(description = "售后方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "售后方式不能为空") + @InEnum(value = AfterSaleWayEnum.class, message = "售后方式必须是 {value}") + private Integer way; + + @Schema(description = "退款金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @NotNull(message = "退款金额不能为空") + @Min(value = 1, message = "退款金额必须大于 0") + private Integer refundPrice; + + @Schema(description = "申请原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "申请原因不能为空") + private String applyReason; + + @Schema(description = "补充描述", example = "商品质量不好") + private String applyDescription; + + @Schema(description = "补充凭证图片", example = "https://www.iocoder.cn/1.png, https://www.iocoder.cn/2.png") + private List applyPicUrls; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppAfterSaleDeliveryReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppAfterSaleDeliveryReqVO.java new file mode 100644 index 0000000..83b88d1 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppAfterSaleDeliveryReqVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.trade.controller.app.aftersale.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +@Schema(description = "用户 App - 交易售后退回货物 Request VO") +@Data +public class AppAfterSaleDeliveryReqVO { + + @Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotNull(message = "售后编号不能为空") + private Long id; + + @Schema(description = "退货物流公司编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "退货物流公司编号不能为空") + private Long logisticsId; + + @Schema(description = "退货物流单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "SF123456789") + @NotNull(message = "退货物流单号不能为空") + private String logisticsNo; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppAfterSaleRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppAfterSaleRespVO.java new file mode 100644 index 0000000..55ae73a --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppAfterSaleRespVO.java @@ -0,0 +1,103 @@ +package cn.iocoder.yudao.module.trade.controller.app.aftersale.vo; + +import cn.iocoder.yudao.module.trade.controller.app.base.property.AppProductPropertyValueDetailRespVO; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "用户 App - 交易售后 Response VO") +@Data +public class AppAfterSaleRespVO { + + @Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "售后流水号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1146347329394184195") + private String no; + + @Schema(description = "售后状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer status; + + @Schema(description = "售后方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer way; + + @Schema(description = "售后类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer type; + + @Schema(description = "申请原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private String applyReason; + + @Schema(description = "补充描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private String applyDescription; + + @Schema(description = "补充凭证图片", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private List applyPicUrls; + + // ========== 交易订单相关 ========== + + @Schema(description = "交易订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long orderId; + + @Schema(description = "交易订单流水号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private String orderNo; + + @Schema(description = "交易订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long orderItemId; + + @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long spuId; + + @Schema(description = "商品 SPU 名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private String spuName; + + @Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long skuId; + + /** + * 属性数组 + */ + private List properties; + + @Schema(description = "商品图片", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/01.jpg") + private String picUrl; + + @Schema(description = "退货商品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer count; + + // ========== 审批相关 ========== + + /** + * 审批备注 + * + * 注意,只有审批不通过才会填写 + */ + private String auditReason; + + // ========== 退款相关 ========== + + @Schema(description = "退款金额,单位:分", example = "100") + private Integer refundPrice; + + @Schema(description = "退款时间") + private LocalDateTime refundTime; + + // ========== 退货相关 ========== + + @Schema(description = "退货物流公司编号", example = "1") + private Long logisticsId; + + @Schema(description = "退货物流单号", example = "SF123456789") + private String logisticsNo; + + @Schema(description = "退货时间") + private LocalDateTime deliveryTime; + + @Schema(description = "收货时间") + private LocalDateTime receiveTime; + + @Schema(description = "收货备注") + private String receiveReason; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppTradeAfterSaleCreateReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppTradeAfterSaleCreateReqVO.java deleted file mode 100644 index 3bf8dd9..0000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppTradeAfterSaleCreateReqVO.java +++ /dev/null @@ -1,40 +0,0 @@ -package cn.iocoder.yudao.module.trade.controller.app.aftersale.vo; - -import cn.iocoder.yudao.framework.common.validation.InEnum; -import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleWayEnum; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import javax.validation.constraints.Min; -import javax.validation.constraints.NotNull; -import java.util.List; - -@Schema(description = "用户 App - 交易售后创建 Request VO") -@Data -public class AppTradeAfterSaleCreateReqVO { - - @Schema(description = "订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "订单项编号不能为空") - private Long orderItemId; - - @Schema(description = "售后方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "售后方式不能为空") - @InEnum(value = TradeAfterSaleWayEnum.class, message = "售后方式必须是 {value}") - private Integer way; - - @Schema(description = "退款金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") - @NotNull(message = "退款金额不能为空") - @Min(value = 1, message = "退款金额必须大于 0") - private Integer refundPrice; - - @Schema(description = "申请原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "申请原因不能为空") - private String applyReason; - - @Schema(description = "补充描述", example = "商品质量不好") - private String applyDescription; - - @Schema(description = "补充凭证图片", example = "https://www.iocoder.cn/1.png, https://www.iocoder.cn/2.png") - private List applyPicUrls; - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppTradeAfterSaleDeliveryReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppTradeAfterSaleDeliveryReqVO.java deleted file mode 100644 index dc5180c..0000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppTradeAfterSaleDeliveryReqVO.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.iocoder.yudao.module.trade.controller.app.aftersale.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import javax.validation.constraints.NotNull; - -@Schema(description = "用户 App - 交易售后退回货物 Request VO") -@Data -public class AppTradeAfterSaleDeliveryReqVO { - - @Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "售后编号不能为空") - private Long id; - - @Schema(description = "退货物流公司编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "退货物流公司编号不能为空") - private Long logisticsId; - - @Schema(description = "退货物流单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "SF123456789") - @NotNull(message = "退货物流单号不能为空") - private String logisticsNo; - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppTradeAfterSaleRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppTradeAfterSaleRespVO.java deleted file mode 100644 index 90ccb4d..0000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppTradeAfterSaleRespVO.java +++ /dev/null @@ -1,103 +0,0 @@ -package cn.iocoder.yudao.module.trade.controller.app.aftersale.vo; - -import cn.iocoder.yudao.module.trade.controller.app.base.property.AppProductPropertyValueDetailRespVO; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; -import java.util.List; - -@Schema(description = "用户 App - 交易售后 Response VO") -@Data -public class AppTradeAfterSaleRespVO { - - @Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Long id; - - @Schema(description = "售后流水号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1146347329394184195") - private String no; - - @Schema(description = "售后状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Integer status; - - @Schema(description = "售后方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Integer way; - - @Schema(description = "售后类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Integer type; - - @Schema(description = "申请原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private String applyReason; - - @Schema(description = "补充描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private String applyDescription; - - @Schema(description = "补充凭证图片", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private List applyPicUrls; - - // ========== 交易订单相关 ========== - - @Schema(description = "交易订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Long orderId; - - @Schema(description = "交易订单流水号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private String orderNo; - - @Schema(description = "交易订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Long orderItemId; - - @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Long spuId; - - @Schema(description = "商品 SPU 名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private String spuName; - - @Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Long skuId; - - /** - * 属性数组 - */ - private List properties; - - @Schema(description = "商品图片", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/01.jpg") - private String picUrl; - - @Schema(description = "退货商品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Integer count; - - // ========== 审批相关 ========== - - /** - * 审批备注 - * - * 注意,只有审批不通过才会填写 - */ - private String auditReason; - - // ========== 退款相关 ========== - - @Schema(description = "退款金额,单位:分", example = "100") - private Integer refundPrice; - - @Schema(description = "退款时间") - private LocalDateTime refundTime; - - // ========== 退货相关 ========== - - @Schema(description = "退货物流公司编号", example = "1") - private Long logisticsId; - - @Schema(description = "退货物流单号", example = "SF123456789") - private String logisticsNo; - - @Schema(description = "退货时间") - private LocalDateTime deliveryTime; - - @Schema(description = "收货时间") - private LocalDateTime receiveTime; - - @Schema(description = "收货备注") - private String receiveReason; - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/AfterSaleConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/AfterSaleConvert.java new file mode 100644 index 0000000..fd759c6 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/AfterSaleConvert.java @@ -0,0 +1,88 @@ +package cn.iocoder.yudao.module.trade.convert.aftersale; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; +import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO; +import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO; +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.AfterSaleDetailRespVO; +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.AfterSaleRespPageItemVO; +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.log.AfterSaleLogRespVO; +import cn.iocoder.yudao.module.trade.controller.admin.base.member.user.MemberUserRespVO; +import cn.iocoder.yudao.module.trade.controller.admin.base.product.property.ProductPropertyValueDetailRespVO; +import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderBaseVO; +import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSaleCreateReqVO; +import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSaleRespVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleLogDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; +import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +import java.util.List; +import java.util.Map; + +@Mapper +public interface AfterSaleConvert { + + AfterSaleConvert INSTANCE = Mappers.getMapper(AfterSaleConvert.class); + + @Mappings({ + @Mapping(target = "id", ignore = true), + @Mapping(target = "createTime", ignore = true), + @Mapping(target = "updateTime", ignore = true), + @Mapping(target = "creator", ignore = true), + @Mapping(target = "updater", ignore = true), + }) + AfterSaleDO convert(AppAfterSaleCreateReqVO createReqVO, TradeOrderItemDO tradeOrderItem); + + @Mappings({ + @Mapping(source = "afterSale.orderId", target = "merchantOrderId"), + @Mapping(source = "afterSale.id", target = "merchantRefundId"), + @Mapping(source = "afterSale.applyReason", target = "reason"), + @Mapping(source = "afterSale.refundPrice", target = "price") + }) + PayRefundCreateReqDTO convert(String userIp, AfterSaleDO afterSale, + TradeOrderProperties orderProperties); + + MemberUserRespVO convert(MemberUserRespDTO bean); + + PageResult convertPage(PageResult page); + + default PageResult convertPage(PageResult pageResult, + Map memberUsers) { + PageResult voPageResult = convertPage(pageResult); + // 处理会员 + voPageResult.getList().forEach(afterSale -> afterSale.setUser( + convert(memberUsers.get(afterSale.getUserId())))); + return voPageResult; + } + + ProductPropertyValueDetailRespVO convert(ProductPropertyValueDetailRespDTO bean); + + AppAfterSaleRespVO convert(AfterSaleDO bean); + + PageResult convertPage02(PageResult page); + + default AfterSaleDetailRespVO convert(AfterSaleDO afterSale, TradeOrderDO order, TradeOrderItemDO orderItem, + MemberUserRespDTO user, List logs) { + AfterSaleDetailRespVO respVO = convert02(afterSale); + // 处理用户信息 + respVO.setUser(convert(user)); + // 处理订单信息 + respVO.setOrder(convert(order)); + respVO.setOrderItem(convert02(orderItem)); + // 处理售后日志 + respVO.setLogs(convertList1(logs)); + return respVO; + } + + List convertList1(List list); + AfterSaleDetailRespVO convert02(AfterSaleDO bean); + AfterSaleDetailRespVO.OrderItem convert02(TradeOrderItemDO bean); + TradeOrderBaseVO convert(TradeOrderDO bean); + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/AfterSaleLogConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/AfterSaleLogConvert.java new file mode 100644 index 0000000..e8960c4 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/AfterSaleLogConvert.java @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.module.trade.convert.aftersale; + +import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleLogDO; +import cn.iocoder.yudao.module.trade.service.aftersale.bo.AfterSaleLogCreateReqBO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface AfterSaleLogConvert { + + AfterSaleLogConvert INSTANCE = Mappers.getMapper(AfterSaleLogConvert.class); + + AfterSaleLogDO convert(AfterSaleLogCreateReqBO bean); + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/TradeAfterSaleConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/TradeAfterSaleConvert.java deleted file mode 100644 index 9faaefb..0000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/TradeAfterSaleConvert.java +++ /dev/null @@ -1,89 +0,0 @@ -package cn.iocoder.yudao.module.trade.convert.aftersale; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; -import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO; -import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO; -import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleDetailRespVO; -import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleRespPageItemVO; -import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.log.TradeAfterSaleLogRespVO; -import cn.iocoder.yudao.module.trade.controller.admin.base.member.user.MemberUserRespVO; -import cn.iocoder.yudao.module.trade.controller.admin.base.product.property.ProductPropertyValueDetailRespVO; -import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderBaseVO; -import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleCreateReqVO; -import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleRespVO; -import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO; -import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleLogDO; -import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; -import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; -import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.Mappings; -import org.mapstruct.factory.Mappers; - -import java.util.List; -import java.util.Map; - -@Mapper -public interface TradeAfterSaleConvert { - - TradeAfterSaleConvert INSTANCE = Mappers.getMapper(TradeAfterSaleConvert.class); - - @Mappings({ - @Mapping(target = "id", ignore = true), - @Mapping(target = "createTime", ignore = true), - @Mapping(target = "updateTime", ignore = true), - @Mapping(target = "creator", ignore = true), - @Mapping(target = "updater", ignore = true), - }) - TradeAfterSaleDO convert(AppTradeAfterSaleCreateReqVO createReqVO, TradeOrderItemDO tradeOrderItem); - - @Mappings({ - @Mapping(source = "afterSale.orderId", target = "merchantOrderId"), - @Mapping(source = "afterSale.id", target = "merchantRefundId"), - @Mapping(source = "afterSale.applyReason", target = "reason"), - @Mapping(source = "afterSale.refundPrice", target = "price") - }) - PayRefundCreateReqDTO convert(String userIp, TradeAfterSaleDO afterSale, - TradeOrderProperties orderProperties); - - MemberUserRespVO convert(MemberUserRespDTO bean); - - PageResult convertPage(PageResult page); - - default PageResult convertPage(PageResult pageResult, - Map memberUsers) { - PageResult voPageResult = convertPage(pageResult); - // 处理会员 - voPageResult.getList().forEach(afterSale -> afterSale.setUser( - convert(memberUsers.get(afterSale.getUserId())))); - return voPageResult; - } - - ProductPropertyValueDetailRespVO convert(ProductPropertyValueDetailRespDTO bean); - - AppTradeAfterSaleRespVO convert(TradeAfterSaleDO bean); - - PageResult convertPage02(PageResult page); - - List convertList(List list); - - default TradeAfterSaleDetailRespVO convert(TradeAfterSaleDO afterSale, TradeOrderDO order, List orderItems, - MemberUserRespDTO user, List logs) { - TradeAfterSaleDetailRespVO respVO = convert(afterSale, orderItems); - // 处理用户信息 - respVO.setUser(convert(user)); - // 处理订单信息 - respVO.setOrder(convert(order)); - // 处理售后日志 - respVO.setLogs(convertList1(logs)); - return respVO; - } - - List convertList1(List list); - @Mapping(target = "id", source = "afterSale.id") - TradeAfterSaleDetailRespVO convert(TradeAfterSaleDO afterSale, List orderItems); - TradeOrderBaseVO convert(TradeOrderDO order); - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderLogConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderLogConvert.java index 5ab3692..df76f32 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderLogConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderLogConvert.java @@ -10,6 +10,6 @@ public interface TradeOrderLogConvert { TradeOrderLogConvert INSTANCE = Mappers.getMapper(TradeOrderLogConvert.class); - TradeOrderLogDO convert(TradeOrderLogCreateReqBO createReqBO); + TradeOrderLogDO convert(TradeOrderLogCreateReqBO bean); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/AfterSaleDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/AfterSaleDO.java new file mode 100644 index 0000000..214592b --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/AfterSaleDO.java @@ -0,0 +1,201 @@ +package cn.iocoder.yudao.module.trade.dal.dataobject.aftersale; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; +import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleStatusEnum; +import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleTypeEnum; +import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleWayEnum; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 售后订单,用于处理 {@link TradeOrderDO} 交易订单的退款退货流程 + * + * @author 芋道源码 + */ +@TableName(value = "trade_after_sale", autoResultMap = true) +@Data +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +public class AfterSaleDO extends BaseDO { + + /** + * 售后编号,主键自增 + */ + private Long id; + /** + * 售后单号 + * + * 例如说,1146347329394184195 + */ + private String no; + /** + * 退款状态 + * + * 枚举 {@link AfterSaleStatusEnum} + */ + private Integer status; + /** + * 售后方式 + * + * 枚举 {@link AfterSaleWayEnum} + */ + private Integer way; + /** + * 售后类型 + * + * 枚举 {@link AfterSaleTypeEnum} + */ + private Integer type; + /** + * 用户编号 + * + * 关联 MemberUserDO 的 id 编号 + */ + private Long userId; + /** + * 申请原因 + * + * type = 退款,对应 trade_after_sale_refund_reason 类型 + * type = 退货退款,对应 trade_after_sale_refund_and_return_reason 类型 + */ + private String applyReason; + /** + * 补充描述 + */ + private String applyDescription; + /** + * 补充凭证图片 + * + * 数组,以逗号分隔 + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private List applyPicUrls; + + // ========== 交易订单相关 ========== + /** + * 交易订单编号 + * + * 关联 {@link TradeOrderDO#getId()} + */ + private Long orderId; + /** + * 订单流水号 + * + * 冗余 {@link TradeOrderDO#getNo()} + */ + private String orderNo; + /** + * 交易订单项编号 + * + * 关联 {@link TradeOrderItemDO#getId()} + */ + private Long orderItemId; + /** + * 商品 SPU 编号 + * + * 关联 ProductSpuDO 的 id 字段 + * 冗余 {@link TradeOrderItemDO#getSpuId()} + */ + private Long spuId; + /** + * 商品 SPU 名称 + * + * 关联 ProductSkuDO 的 name 字段 + * 冗余 {@link TradeOrderItemDO#getSpuName()} + */ + private String spuName; + /** + * 商品 SKU 编号 + * + * 关联 ProductSkuDO 的编号 + */ + private Long skuId; + /** + * 属性数组,JSON 格式 + * + * 冗余 {@link TradeOrderItemDO#getProperties()} + */ + @TableField(typeHandler = TradeOrderItemDO.PropertyTypeHandler.class) + private List properties; + /** + * 商品图片 + * + * 冗余 {@link TradeOrderItemDO#getPicUrl()} + */ + private String picUrl; + /** + * 退货商品数量 + */ + private Integer count; + + // ========== 审批相关 ========== + + /** + * 审批时间 + */ + private LocalDateTime auditTime; + /** + * 审批人 + * + * 关联 AdminUserDO 的 id 编号 + */ + private Long auditUserId; + /** + * 审批备注 + * + * 注意,只有审批不通过才会填写 + */ + private String auditReason; + + // ========== 退款相关 ========== + /** + * 退款金额,单位:分。 + */ + private Integer refundPrice; + /** + * 支付退款编号 + * + * 对接 pay-module-biz 支付服务的退款订单编号,即 PayRefundDO 的 id 编号 + */ + private Long payRefundId; + /** + * 退款时间 + */ + private LocalDateTime refundTime; + + // ========== 退货相关 ========== + /** + * 退货物流公司编号 + * + * 关联 LogisticsDO 的 id 编号 + */ + private Long logisticsId; + /** + * 退货物流单号 + */ + private String logisticsNo; + /** + * 退货时间 + */ + private LocalDateTime deliveryTime; + /** + * 收货时间 + */ + private LocalDateTime receiveTime; + /** + * 收货备注 + * + * 注意,只有拒绝收货才会填写 + */ + private String receiveReason; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/AfterSaleLogDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/AfterSaleLogDO.java new file mode 100644 index 0000000..2820f23 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/AfterSaleLogDO.java @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.trade.dal.dataobject.aftersale; + +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleOperateTypeEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 交易售后日志 DO + * + * @author 芋道源码 + */ +@TableName("trade_after_sale_log") +@KeySequence("trade_after_sale_log_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class AfterSaleLogDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 用户编号 + * + * 关联 1:AdminUserDO 的 id 字段 + * 关联 2:MemberUserDO 的 id 字段 + */ + private Long userId; + /** + * 用户类型 + * + * 枚举 {@link UserTypeEnum} + */ + private Integer userType; + + /** + * 售后编号 + * + * 关联 {@link AfterSaleDO#getId()} + */ + private Long afterSaleId; + /** + * 操作前状态 + */ + private Integer beforeStatus; + /** + * 操作后状态 + */ + private Integer afterStatus; + + /** + * 操作类型 + * + * 枚举 {@link AfterSaleOperateTypeEnum} + */ + private Integer operateType; + /** + * 操作明细 + */ + private String content; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/TradeAfterSaleDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/TradeAfterSaleDO.java deleted file mode 100644 index 9916f3e..0000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/TradeAfterSaleDO.java +++ /dev/null @@ -1,201 +0,0 @@ -package cn.iocoder.yudao.module.trade.dal.dataobject.aftersale; - -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; -import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; -import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleStatusEnum; -import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleTypeEnum; -import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleWayEnum; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.experimental.Accessors; - -import java.time.LocalDateTime; -import java.util.List; - -/** - * 售后订单,用于处理 {@link TradeOrderDO} 交易订单的退款退货流程 - * - * @author 芋道源码 - */ -@TableName(value = "trade_after_sale", autoResultMap = true) -@Data -@EqualsAndHashCode(callSuper = true) -@Accessors(chain = true) -public class TradeAfterSaleDO extends BaseDO { - - /** - * 售后编号,主键自增 - */ - private Long id; - /** - * 售后单号 - * - * 例如说,1146347329394184195 - */ - private String no; - /** - * 退款状态 - * - * 枚举 {@link TradeAfterSaleStatusEnum} - */ - private Integer status; - /** - * 售后方式 - * - * 枚举 {@link TradeAfterSaleWayEnum} - */ - private Integer way; - /** - * 售后类型 - * - * 枚举 {@link TradeAfterSaleTypeEnum} - */ - private Integer type; - /** - * 用户编号 - * - * 关联 MemberUserDO 的 id 编号 - */ - private Long userId; - /** - * 申请原因 - * - * type = 退款,对应 trade_after_sale_refund_reason 类型 - * type = 退货退款,对应 trade_after_sale_refund_and_return_reason 类型 - */ - private String applyReason; - /** - * 补充描述 - */ - private String applyDescription; - /** - * 补充凭证图片 - * - * 数组,以逗号分隔 - */ - @TableField(typeHandler = JacksonTypeHandler.class) - private List applyPicUrls; - - // ========== 交易订单相关 ========== - /** - * 交易订单编号 - * - * 关联 {@link TradeOrderDO#getId()} - */ - private Long orderId; - /** - * 订单流水号 - * - * 冗余 {@link TradeOrderDO#getNo()} - */ - private String orderNo; - /** - * 交易订单项编号 - * - * 关联 {@link TradeOrderItemDO#getId()} - */ - private Long orderItemId; - /** - * 商品 SPU 编号 - * - * 关联 ProductSpuDO 的 id 字段 - * 冗余 {@link TradeOrderItemDO#getSpuId()} - */ - private Long spuId; - /** - * 商品 SPU 名称 - * - * 关联 ProductSkuDO 的 name 字段 - * 冗余 {@link TradeOrderItemDO#getSpuName()} - */ - private String spuName; - /** - * 商品 SKU 编号 - * - * 关联 ProductSkuDO 的编号 - */ - private Long skuId; - /** - * 属性数组,JSON 格式 - * - * 冗余 {@link TradeOrderItemDO#getProperties()} - */ - @TableField(typeHandler = TradeOrderItemDO.PropertyTypeHandler.class) - private List properties; - /** - * 商品图片 - * - * 冗余 {@link TradeOrderItemDO#getPicUrl()} - */ - private String picUrl; - /** - * 退货商品数量 - */ - private Integer count; - - // ========== 审批相关 ========== - - /** - * 审批时间 - */ - private LocalDateTime auditTime; - /** - * 审批人 - * - * 关联 AdminUserDO 的 id 编号 - */ - private Long auditUserId; - /** - * 审批备注 - * - * 注意,只有审批不通过才会填写 - */ - private String auditReason; - - // ========== 退款相关 ========== - /** - * 退款金额,单位:分。 - */ - private Integer refundPrice; - /** - * 支付退款编号 - * - * 对接 pay-module-biz 支付服务的退款订单编号,即 PayRefundDO 的 id 编号 - */ - private Long payRefundId; - /** - * 退款时间 - */ - private LocalDateTime refundTime; - - // ========== 退货相关 ========== - /** - * 退货物流公司编号 - * - * 关联 LogisticsDO 的 id 编号 - */ - private Long logisticsId; - /** - * 退货物流单号 - */ - private String logisticsNo; - /** - * 退货时间 - */ - private LocalDateTime deliveryTime; - /** - * 收货时间 - */ - private LocalDateTime receiveTime; - /** - * 收货备注 - * - * 注意,只有拒绝收货才会填写 - */ - private String receiveReason; - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/TradeAfterSaleLogDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/TradeAfterSaleLogDO.java deleted file mode 100644 index 56a0f0f..0000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/TradeAfterSaleLogDO.java +++ /dev/null @@ -1,64 +0,0 @@ -package cn.iocoder.yudao.module.trade.dal.dataobject.aftersale; - -import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleOperateTypeEnum; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.*; - -/** - * 交易售后日志 DO - * - * // TODO 可优化:参考淘宝或者有赞:1)增加 action 表示什么操作;2)content 记录每个操作的明细 - * - * @author 芋道源码 - */ -@TableName("trade_after_sale_log") -@KeySequence("trade_after_sale_log_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class TradeAfterSaleLogDO extends BaseDO { - - /** - * 编号 - */ - @TableId - private Long id; - /** - * 用户编号 - * - * 关联 1:AdminUserDO 的 id 字段 - * 关联 2:MemberUserDO 的 id 字段 - */ - private Long userId; - /** - * 用户类型 - * - * 枚举 {@link UserTypeEnum} - */ - private Integer userType; - /** - * 售后编号 - * - * 关联 {@link TradeAfterSaleDO#getId()} - */ - private Long afterSaleId; - // todo @CHENCHEN: 改成 Integer 哈;主要未来改文案,不好洗 log 存的字段; - /** - * 操作类型 - * - * 枚举 {@link AfterSaleOperateTypeEnum} - */ - private String operateType; - /** - * 操作明细 - */ - private String content; - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderItemDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderItemDO.java index deb895e..10b07ce 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderItemDO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderItemDO.java @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.trade.dal.dataobject.order; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleDO; import cn.iocoder.yudao.module.trade.dal.dataobject.cart.CartDO; import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum; import com.baomidou.mybatisplus.annotation.TableField; @@ -166,7 +166,7 @@ public class TradeOrderItemDO extends BaseDO { /** * 售后单编号 * - * 关联 {@link TradeAfterSaleDO#getId()} 字段 + * 关联 {@link AfterSaleDO#getId()} 字段 */ private Long afterSaleId; /** diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/AfterSaleLogMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/AfterSaleLogMapper.java new file mode 100644 index 0000000..c0ec91c --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/AfterSaleLogMapper.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.trade.dal.mysql.aftersale; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleLogDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +@Mapper +public interface AfterSaleLogMapper extends BaseMapperX { + + default List selectListByAfterSaleId(Long afterSaleId) { + return selectList(AfterSaleLogDO::getAfterSaleId, afterSaleId); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/AfterSaleMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/AfterSaleMapper.java new file mode 100644 index 0000000..68a09a8 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/AfterSaleMapper.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.trade.dal.mysql.aftersale; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.AfterSalePageReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; + +@Mapper +public interface AfterSaleMapper extends BaseMapperX { + + default PageResult selectPage(AfterSalePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(AfterSaleDO::getNo, reqVO.getNo()) + .eqIfPresent(AfterSaleDO::getStatus, reqVO.getStatus()) + .eqIfPresent(AfterSaleDO::getType, reqVO.getType()) + .eqIfPresent(AfterSaleDO::getWay, reqVO.getWay()) + .likeIfPresent(AfterSaleDO::getOrderNo, reqVO.getOrderNo()) + .likeIfPresent(AfterSaleDO::getSpuName, reqVO.getSpuName()) + .betweenIfPresent(AfterSaleDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(AfterSaleDO::getId)); + } + + default PageResult selectPage(Long userId, PageParam pageParam) { + return selectPage(pageParam, new LambdaQueryWrapperX() + .eqIfPresent(AfterSaleDO::getUserId, userId) + .orderByDesc(AfterSaleDO::getId)); + } + + default int updateByIdAndStatus(Long id, Integer status, AfterSaleDO update) { + return update(update, new LambdaUpdateWrapper() + .eq(AfterSaleDO::getId, id).eq(AfterSaleDO::getStatus, status)); + } + + default AfterSaleDO selectByIdAndUserId(Long id, Long userId) { + return selectOne(AfterSaleDO::getId, id, + AfterSaleDO::getUserId, userId); + } + + default Long selectCountByUserIdAndStatus(Long userId, Collection statuses) { + return selectCount(new LambdaQueryWrapperX() + .eq(AfterSaleDO::getUserId, userId) + .in(AfterSaleDO::getStatus, statuses)); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/TradeAfterSaleLogMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/TradeAfterSaleLogMapper.java deleted file mode 100644 index b92ce07..0000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/TradeAfterSaleLogMapper.java +++ /dev/null @@ -1,9 +0,0 @@ -package cn.iocoder.yudao.module.trade.dal.mysql.aftersale; - -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleLogDO; -import org.apache.ibatis.annotations.Mapper; - -@Mapper -public interface TradeAfterSaleLogMapper extends BaseMapperX { -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/TradeAfterSaleMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/TradeAfterSaleMapper.java deleted file mode 100644 index 1206a98..0000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/TradeAfterSaleMapper.java +++ /dev/null @@ -1,51 +0,0 @@ -package cn.iocoder.yudao.module.trade.dal.mysql.aftersale; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSalePageReqVO; -import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO; -import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; -import org.apache.ibatis.annotations.Mapper; - -import java.util.Collection; - -@Mapper -public interface TradeAfterSaleMapper extends BaseMapperX { - - default PageResult selectPage(TradeAfterSalePageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .likeIfPresent(TradeAfterSaleDO::getNo, reqVO.getNo()) - .eqIfPresent(TradeAfterSaleDO::getStatus, reqVO.getStatus()) - .eqIfPresent(TradeAfterSaleDO::getType, reqVO.getType()) - .eqIfPresent(TradeAfterSaleDO::getWay, reqVO.getWay()) - .likeIfPresent(TradeAfterSaleDO::getOrderNo, reqVO.getOrderNo()) - .likeIfPresent(TradeAfterSaleDO::getSpuName, reqVO.getSpuName()) - .betweenIfPresent(TradeAfterSaleDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(TradeAfterSaleDO::getId)); - } - - default PageResult selectPage(Long userId, PageParam pageParam) { - return selectPage(pageParam, new LambdaQueryWrapperX() - .eqIfPresent(TradeAfterSaleDO::getUserId, userId) - .orderByDesc(TradeAfterSaleDO::getId)); - } - - default int updateByIdAndStatus(Long id, Integer status, TradeAfterSaleDO update) { - return update(update, new LambdaUpdateWrapper() - .eq(TradeAfterSaleDO::getId, id).eq(TradeAfterSaleDO::getStatus, status)); - } - - default TradeAfterSaleDO selectByIdAndUserId(Long id, Long userId) { - return selectOne(TradeAfterSaleDO::getId, id, - TradeAfterSaleDO::getUserId, userId); - } - - default Long selectCountByUserIdAndStatus(Long userId, Collection statuses) { - return selectCount(new LambdaQueryWrapperX() - .eq(TradeAfterSaleDO::getUserId, userId) - .in(TradeAfterSaleDO::getStatus, statuses)); - } - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/redis/RedisKeyConstants.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/redis/RedisKeyConstants.java new file mode 100644 index 0000000..f9b7d8f --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/redis/RedisKeyConstants.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.trade.dal.redis; + +/** + * 交易 Redis Key 枚举类 + * + * @author 芋道源码 + */ +public interface RedisKeyConstants { + + /** + * 交易序号的缓存 + * + * KEY 格式:trade_no:{prefix} + * VALUE 数据格式:编号自增 + */ + String TRADE_NO = "trade_no:"; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/redis/no/TradeNoRedisDAO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/redis/no/TradeNoRedisDAO.java new file mode 100644 index 0000000..8b76f19 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/redis/no/TradeNoRedisDAO.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.trade.dal.redis.no; + +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateUtil; +import cn.iocoder.yudao.module.trade.dal.redis.RedisKeyConstants; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Repository; + +import javax.annotation.Resource; +import java.time.Duration; +import java.time.LocalDateTime; + +/** + * 订单序号的 Redis DAO + * + * @author HUIHUI + */ +@Repository +public class TradeNoRedisDAO { + + public static final String TRADE_ORDER_NO_PREFIX = "o"; + + public static final String AFTER_SALE_NO_PREFIX = "r"; + + @Resource + private StringRedisTemplate stringRedisTemplate; + + /** + * 生成序号 + * + * @param prefix 前缀 + * @return 序号 + */ + public String generate(String prefix) { + // 递增序号 + String noPrefix = prefix + DateUtil.format(LocalDateTime.now(), DatePattern.PURE_DATETIME_PATTERN); + String key = RedisKeyConstants.TRADE_NO + noPrefix; + Long no = stringRedisTemplate.opsForValue().increment(key); + // 设置过期时间 + stringRedisTemplate.expire(key, Duration.ofMinutes(1L)); + return noPrefix + no; + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/redis/no/TradeOrderNoRedisDAO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/redis/no/TradeOrderNoRedisDAO.java deleted file mode 100644 index 8ad6192..0000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/redis/no/TradeOrderNoRedisDAO.java +++ /dev/null @@ -1,36 +0,0 @@ -package cn.iocoder.yudao.module.trade.dal.redis.no; - -import cn.hutool.core.date.DatePattern; -import cn.hutool.core.date.DateUtil; -import org.springframework.data.redis.core.StringRedisTemplate; -import org.springframework.stereotype.Repository; - -import javax.annotation.Resource; -import java.time.LocalDateTime; - -/** - * 订单序号的 Redis DAO - * - * @author HUIHUI - */ -@Repository -public class TradeOrderNoRedisDAO { - - public static final String TRADE_ORDER_NO_PREFIX = "O"; - - @Resource - private StringRedisTemplate stringRedisTemplate; - - /** - * 生成序号 - * - * @param prefix 前缀 - * @return 序号 - */ - public String generate(String prefix) { - String noPrefix = prefix + DateUtil.format(LocalDateTime.now(), DatePattern.PURE_DATETIME_PATTERN); - Long no = stringRedisTemplate.opsForValue().increment(noPrefix); - return noPrefix + no; - } - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersale/config/AfterSaleLogConfiguration.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersale/config/AfterSaleLogConfiguration.java new file mode 100644 index 0000000..1c26137 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersale/config/AfterSaleLogConfiguration.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.trade.framework.aftersale.config; + +import cn.iocoder.yudao.module.trade.framework.aftersale.core.aop.AfterSaleLogAspect; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +// TODO @chenchen:改成 aftersale 好点哈; +/** + * trade 模块的 afterSaleLog 组件的 Configuration + * + * @author 陈賝 + * @since 2023/6/18 11:09 + */ +@Configuration(proxyBeanMethods = false) +public class AfterSaleLogConfiguration { + + @Bean + public AfterSaleLogAspect afterSaleLogAspect() { + return new AfterSaleLogAspect(); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersale/core/annotations/AfterSaleLog.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersale/core/annotations/AfterSaleLog.java new file mode 100644 index 0000000..bc41bf9 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersale/core/annotations/AfterSaleLog.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.trade.framework.aftersale.core.annotations; + +import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleOperateTypeEnum; +import cn.iocoder.yudao.module.trade.framework.aftersale.core.aop.AfterSaleLogAspect; + +import java.lang.annotation.*; + +/** + * 售后日志的注解 + * + * 写在方法上时,会自动记录售后日志 + * + * @author 陈賝 + * @since 2023/6/8 17:04 + * @see AfterSaleLogAspect + */ +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface AfterSaleLog { + + /** + * 操作类型 + */ + AfterSaleOperateTypeEnum operateType(); + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersale/core/aop/AfterSaleLogAspect.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersale/core/aop/AfterSaleLogAspect.java new file mode 100644 index 0000000..f7b3f7e --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersale/core/aop/AfterSaleLogAspect.java @@ -0,0 +1,133 @@ +package cn.iocoder.yudao.module.trade.framework.aftersale.core.aop; + +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderLogDO; +import cn.iocoder.yudao.module.trade.framework.aftersale.core.annotations.AfterSaleLog; +import cn.iocoder.yudao.module.trade.service.aftersale.AfterSaleLogService; +import cn.iocoder.yudao.module.trade.service.aftersale.bo.AfterSaleLogCreateReqBO; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.AfterReturning; +import org.aspectj.lang.annotation.Aspect; + +import javax.annotation.Resource; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; +import static java.util.Collections.emptyMap; + +/** + * 售后订单的操作记录的 AOP 切面 + * + * @author 陈賝 + * @since 2023/6/13 13:54 + */ +@Slf4j +@Aspect +public class AfterSaleLogAspect { + + /** + * 用户编号 + * + * 目前的使用场景:支付回调时,需要强制设置下用户编号 + */ + private static final ThreadLocal USER_ID = new ThreadLocal<>(); + /** + * 用户类型 + */ + private static final ThreadLocal USER_TYPE = new ThreadLocal<>(); + /** + * 订单编号 + */ + private static final ThreadLocal AFTER_SALE_ID = new ThreadLocal<>(); + /** + * 操作前的状态 + */ + private static final ThreadLocal BEFORE_STATUS = new ThreadLocal<>(); + /** + * 操作后的状态 + */ + private static final ThreadLocal AFTER_STATUS = new ThreadLocal<>(); + /** + * 拓展参数 Map,用于格式化操作内容 + */ + private static final ThreadLocal> EXTS = new ThreadLocal<>(); + + @Resource + private AfterSaleLogService afterSaleLogService; + + @AfterReturning(pointcut = "@annotation(afterSaleLog)") + public void doAfterReturning(JoinPoint joinPoint, AfterSaleLog afterSaleLog) { + try { + // 1.1 操作用户 + Integer userType = getUserType(); + Long userId = getUserId(); + // 1.2 售后信息 + Long afterSaleId = AFTER_SALE_ID.get(); + if (afterSaleId == null) { // 如果未设置,只有注解,说明不需要记录日志 + return; + } + Integer beforeStatus = BEFORE_STATUS.get(); + Integer afterStatus = AFTER_STATUS.get(); + Map exts = ObjectUtil.defaultIfNull(EXTS.get(), emptyMap()); + String content = StrUtil.format(afterSaleLog.operateType().getContent(), exts); + + // 2. 记录日志 + AfterSaleLogCreateReqBO createBO = new AfterSaleLogCreateReqBO() + .setUserId(userId).setUserType(userType) + .setAfterSaleId(afterSaleId).setBeforeStatus(beforeStatus).setAfterStatus(afterStatus) + .setOperateType(afterSaleLog.operateType().getType()).setContent(content); + afterSaleLogService.createAfterSaleLog(createBO); + } catch (Exception exception) { + log.error("[doAfterReturning][afterSaleLog({}) 日志记录错误]", toJsonString(afterSaleLog), exception); + } finally { + clear(); + } + } + + /** + * 获得用户类型 + * + * 如果没有,则约定为 {@link TradeOrderLogDO#getUserType()} 系统 + * + * @return 用户类型 + */ + private static Integer getUserType() { + return ObjectUtil.defaultIfNull(WebFrameworkUtils.getLoginUserType(), TradeOrderLogDO.USER_TYPE_SYSTEM); + } + + /** + * 获得用户编号 + * + * 如果没有,则约定为 {@link TradeOrderLogDO#getUserId()} 系统 + * + * @return 用户类型 + */ + private static Long getUserId() { + return ObjectUtil.defaultIfNull(WebFrameworkUtils.getLoginUserId(), TradeOrderLogDO.USER_ID_SYSTEM); + } + + public static void setAfterSale(Long id, Integer beforeStatus, Integer afterStatus, Map exts) { + AFTER_SALE_ID.set(id); + BEFORE_STATUS.set(beforeStatus); + AFTER_STATUS.set(afterStatus); + EXTS.set(exts); + } + + public static void setUserInfo(Long userId, Integer userType) { + USER_ID.set(userId); + USER_TYPE.set(userType); + } + + private static void clear() { + USER_ID.remove(); + USER_TYPE.remove(); + AFTER_SALE_ID.remove(); + BEFORE_STATUS.remove(); + AFTER_STATUS.remove(); + EXTS.remove(); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersale/core/utils/AfterSaleLogUtils.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersale/core/utils/AfterSaleLogUtils.java new file mode 100644 index 0000000..3f9fc5d --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersale/core/utils/AfterSaleLogUtils.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.trade.framework.aftersale.core.utils; + + +import cn.iocoder.yudao.module.trade.framework.aftersale.core.aop.AfterSaleLogAspect; + +import java.util.Map; + +/** + * 操作日志工具类 + * 目前主要的作用,是提供给业务代码,记录操作明细和拓展字段 + * + * @author 芋道源码 + */ +public class AfterSaleLogUtils { + + public static void setAfterSaleInfo(Long id, Integer beforeStatus, Integer afterStatus) { + setAfterSaleInfo(id, beforeStatus, afterStatus, null); + } + + public static void setAfterSaleInfo(Long id, Integer beforeStatus, Integer afterStatus, + Map exts) { + AfterSaleLogAspect.setAfterSale(id, beforeStatus, afterStatus, exts); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/config/AfterSaleLogConfiguration.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/config/AfterSaleLogConfiguration.java deleted file mode 100644 index 1c382d2..0000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/config/AfterSaleLogConfiguration.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.iocoder.yudao.module.trade.framework.aftersalelog.config; - -import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.aop.AfterSaleLogAspect; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -// TODO @chenchen:改成 aftersale 好点哈; -/** - * trade 模块的 afterSaleLog 组件的 Configuration - * - * @author 陈賝 - * @since 2023/6/18 11:09 - */ -@Configuration(proxyBeanMethods = false) -public class AfterSaleLogConfiguration { - - @Bean - public AfterSaleLogAspect afterSaleLogAspect() { - return new AfterSaleLogAspect(); - } - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/annotations/AfterSaleLog.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/annotations/AfterSaleLog.java deleted file mode 100644 index 59c1169..0000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/annotations/AfterSaleLog.java +++ /dev/null @@ -1,38 +0,0 @@ -package cn.iocoder.yudao.module.trade.framework.aftersalelog.core.annotations; - -import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleOperateTypeEnum; - -import java.lang.annotation.*; - -/** - * 售后日志的注解 - * - * 写在方法上时,会自动记录售后日志 - * - * @author 陈賝 - * @since 2023/6/8 17:04 - * @see cn.iocoder.yudao.module.trade.framework.aftersalelog.core.aop.AfterSaleLogAspect - */ -@Target({ElementType.METHOD, ElementType.TYPE}) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface AfterSaleLog { - - /** - * 售后 ID - */ - @Deprecated - String id() default ""; - - /** - * 操作类型 - */ - AfterSaleOperateTypeEnum operateType(); - - /** - * 日志内容 - */ - @Deprecated - String content() default ""; - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/aop/AfterSaleLogAspect.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/aop/AfterSaleLogAspect.java deleted file mode 100644 index f341d2d..0000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/aop/AfterSaleLogAspect.java +++ /dev/null @@ -1,122 +0,0 @@ -package cn.iocoder.yudao.module.trade.framework.aftersalelog.core.aop; - -import cn.hutool.core.map.MapUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.iocoder.yudao.framework.common.util.spring.SpringExpressionUtils; -import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; -import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.annotations.AfterSaleLog; -import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.dto.TradeAfterSaleLogCreateReqDTO; -import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.service.AfterSaleLogService; -import com.google.common.collect.Maps; -import lombok.extern.slf4j.Slf4j; -import org.aspectj.lang.JoinPoint; -import org.aspectj.lang.annotation.AfterReturning; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.reflect.MethodSignature; - -import javax.annotation.Resource; -import java.util.HashMap; -import java.util.Map; - -import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; -import static java.util.Arrays.asList; - -/** - * 记录售后日志的 AOP 切面 - * - * @author 陈賝 - * @since 2023/6/13 13:54 - */ -@Slf4j -@Aspect -public class AfterSaleLogAspect { - - @Resource - private AfterSaleLogService afterSaleLogService; - /** - * 售前状态 - */ - private static final ThreadLocal BEFORE_STATUS = new ThreadLocal<>(); - /** - * 售后状态 - */ - private static final ThreadLocal AFTER_STATUS = new ThreadLocal<>(); - /** - * 操作类型 - */ - private final static String OPERATE_TYPE = "operateType"; - /** - * ID - */ - private final static String ID = "id"; - /** - * 操作明细 - */ - private final static String CONTENT = "content"; - - /** - * 切面存入日志 - */ - @AfterReturning(pointcut = "@annotation(afterSaleLog)", returning = "info") - public void doAfterReturning(JoinPoint joinPoint, AfterSaleLog afterSaleLog, Object info) { - try { - // 日志对象拼接 - Integer userType = WebFrameworkUtils.getLoginUserType(); - Long id = WebFrameworkUtils.getLoginUserId(); - Map formatObj = spelFormat(joinPoint, info); - TradeAfterSaleLogCreateReqDTO dto = new TradeAfterSaleLogCreateReqDTO() - .setUserId(id) - .setUserType(userType) - .setAfterSaleId(MapUtil.getLong(formatObj, ID)) - .setOperateType(MapUtil.getStr(formatObj, OPERATE_TYPE)) - .setBeforeStatus(BEFORE_STATUS.get()) - .setAfterStatus(AFTER_STATUS.get()) - .setContent(MapUtil.getStr(formatObj, CONTENT)); - // 异步存入数据库 - afterSaleLogService.createLog(dto); - } catch (Exception exception) { - log.error("[doAfterReturning][afterSaleLog({}) 日志记录错误]", toJsonString(afterSaleLog), exception); - }finally { - clearThreadLocal(); - } - } - - /** - * 获取描述信息 - */ - public static Map spelFormat(JoinPoint joinPoint, Object info) { - MethodSignature signature = (MethodSignature) joinPoint.getSignature(); - AfterSaleLog afterSaleLogPoint = signature.getMethod().getAnnotation(AfterSaleLog.class); - HashMap result = Maps.newHashMapWithExpectedSize(2); - Map spelMap = SpringExpressionUtils.parseExpression(joinPoint, info, - asList(afterSaleLogPoint.id(), afterSaleLogPoint.content())); - // TODO @chenchen:是不是抽成 3 个方法好点;毕竟 map 太抽象了;; - // 售后ID - String id = MapUtil.getStr(spelMap, afterSaleLogPoint.id()); - result.put(ID, id); - // 操作类型 - String operateType = afterSaleLogPoint.operateType().getContent(); - result.put(OPERATE_TYPE, operateType); - // 日志内容 - String content = MapUtil.getStr(spelMap, afterSaleLogPoint.content()); - if (ObjectUtil.isNotNull(afterSaleLogPoint.operateType())) { - content += operateType; - } - result.put(CONTENT, content); - return result; - } - - public static void setBeforeStatus(Integer beforestatus) { - BEFORE_STATUS.set(beforestatus); - } - - public static void setAfterStatus(Integer afterStatus) { - AFTER_STATUS.set(afterStatus); - } - - private static void clearThreadLocal() { - AFTER_STATUS.remove(); - BEFORE_STATUS.remove(); - } - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/dto/TradeAfterSaleLogCreateReqDTO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/dto/TradeAfterSaleLogCreateReqDTO.java deleted file mode 100644 index 19c1086..0000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/dto/TradeAfterSaleLogCreateReqDTO.java +++ /dev/null @@ -1,54 +0,0 @@ -package cn.iocoder.yudao.module.trade.framework.aftersalelog.core.dto; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 售后日志的创建 Request DTO - * - * @author 陈賝 - * @since 2023/6/19 09:54 - */ -@Data -@NoArgsConstructor -@AllArgsConstructor -public class TradeAfterSaleLogCreateReqDTO { - - /** - * 编号 - */ - private Long id; - /** - * 用户编号 - * - * 关联 1:AdminUserDO 的 id 字段 - * 关联 2:MemberUserDO 的 id 字段 - */ - private Long userId; - /** - * 用户类型 - */ - private Integer userType; - /** - * 售后编号 - */ - private Long afterSaleId; - /** - * 操作类型 - */ - private String operateType; - /** - * 操作明细 - */ - private String content; - /** - * 售前状态 - */ - private Integer beforeStatus; - /** - * 售后状态 - */ - private Integer afterStatus; - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/service/AfterSaleLogService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/service/AfterSaleLogService.java deleted file mode 100644 index 53019a3..0000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/service/AfterSaleLogService.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.yudao.module.trade.framework.aftersalelog.core.service; - - -import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.log.TradeAfterSaleLogRespVO; -import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.dto.TradeAfterSaleLogCreateReqDTO; - -import java.util.List; - -/** - * 交易售后日志 Service 接口 - * - * @author 陈賝 - * @since 2023/6/12 14:18 - */ -public interface AfterSaleLogService { - - /** - * 创建售后日志 - * - * @param logDTO 日志记录 - * @author 陈賝 - * @since 2023/6/12 14:18 - */ - void createLog(TradeAfterSaleLogCreateReqDTO logDTO); - - /** - * 获取售后日志 - * - * @param afterSaleId 售后编号 - * @return 售后日志 - */ - List getLog(Long afterSaleId); - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/util/AfterSaleLogUtils.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/util/AfterSaleLogUtils.java deleted file mode 100644 index 44f829d..0000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/util/AfterSaleLogUtils.java +++ /dev/null @@ -1,33 +0,0 @@ -package cn.iocoder.yudao.module.trade.framework.aftersalelog.core.util; - - -import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.aop.AfterSaleLogAspect; - -import java.util.Map; - -/** - * 操作日志工具类 - * 目前主要的作用,是提供给业务代码,记录操作明细和拓展字段 - * - * @author 芋道源码 - */ -public class AfterSaleLogUtils { - - public static void setBeforeStatus(Integer status) { - AfterSaleLogAspect.setBeforeStatus(status); - } - - public static void setAfterStatus(Integer status) { - AfterSaleLogAspect.setAfterStatus(status); - } - - public static void setAfterSaleInfo(Long id, Integer beforeStatus, Integer afterStatus) { - setAfterSaleInfo(id, beforeStatus, afterStatus, null); - } - - public static void setAfterSaleInfo(Long id, Integer beforeStatus, Integer afterStatus, - Map exts) { - // TODO 待实现 - } - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/core/annotations/TradeOrderLog.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/core/annotations/TradeOrderLog.java index b793879..cc023c1 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/core/annotations/TradeOrderLog.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/core/annotations/TradeOrderLog.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.trade.framework.order.core.annotations; import cn.iocoder.yudao.module.trade.enums.order.TradeOrderOperateTypeEnum; +import cn.iocoder.yudao.module.trade.framework.order.core.aop.TradeOrderLogAspect; import java.lang.annotation.Documented; import java.lang.annotation.Retention; @@ -15,6 +16,7 @@ import static java.lang.annotation.ElementType.METHOD; * * @author 陈賝 * @since 2023/7/6 15:37 + * @see TradeOrderLogAspect */ @Target({METHOD, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/core/aop/TradeOrderLogAspect.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/core/aop/TradeOrderLogAspect.java index c40d3e6..b1ac371 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/core/aop/TradeOrderLogAspect.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/core/aop/TradeOrderLogAspect.java @@ -73,7 +73,7 @@ public class TradeOrderLogAspect { Long userId = getUserId(); // 1.2 订单信息 Long orderId = ORDER_ID.get(); - if (orderId == null) { // 如果未设置,只有注解,说明不需要记录订单日志 + if (orderId == null) { // 如果未设置,只有注解,说明不需要记录日志 return; } Integer beforeStatus = BEFORE_STATUS.get(); @@ -81,7 +81,7 @@ public class TradeOrderLogAspect { Map exts = ObjectUtil.defaultIfNull(EXTS.get(), emptyMap()); String content = StrUtil.format(orderLog.operateType().getContent(), exts); - // 2.1 记录日志 + // 2. 记录日志 TradeOrderLogCreateReqBO createBO = new TradeOrderLogCreateReqBO() .setUserId(userId).setUserType(userType) .setOrderId(orderId).setBeforeStatus(beforeStatus).setAfterStatus(afterStatus) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleLogService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleLogService.java new file mode 100644 index 0000000..2620ca0 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleLogService.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.trade.service.aftersale; + + +import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleLogDO; +import cn.iocoder.yudao.module.trade.service.aftersale.bo.AfterSaleLogCreateReqBO; + +import java.util.List; + +/** + * 交易售后日志 Service 接口 + * + * @author 陈賝 + * @since 2023/6/12 14:18 + */ +public interface AfterSaleLogService { + + /** + * 创建售后日志 + * + * @param createReqBO 日志记录 + * @author 陈賝 + * @since 2023/6/12 14:18 + */ + void createAfterSaleLog(AfterSaleLogCreateReqBO createReqBO); + + /** + * 获取售后日志 + * + * @param afterSaleId 售后编号 + * @return 售后日志 + */ + List getAfterSaleLogList(Long afterSaleId); + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleLogServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleLogServiceImpl.java new file mode 100644 index 0000000..280af92 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleLogServiceImpl.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.trade.service.aftersale; + +import cn.iocoder.yudao.module.trade.convert.aftersale.AfterSaleLogConvert; +import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleLogDO; +import cn.iocoder.yudao.module.trade.dal.mysql.aftersale.AfterSaleLogMapper; +import cn.iocoder.yudao.module.trade.service.aftersale.bo.AfterSaleLogCreateReqBO; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 交易售后日志 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class AfterSaleLogServiceImpl implements AfterSaleLogService { + + @Resource + private AfterSaleLogMapper afterSaleLogMapper; + + @Override + public void createAfterSaleLog(AfterSaleLogCreateReqBO createReqBO) { + AfterSaleLogDO afterSaleLog = AfterSaleLogConvert.INSTANCE.convert(createReqBO); + afterSaleLogMapper.insert(afterSaleLog); + } + + @Override + public List getAfterSaleLogList(Long afterSaleId) { + return afterSaleLogMapper.selectListByAfterSaleId(afterSaleId); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleService.java new file mode 100644 index 0000000..bf26800 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleService.java @@ -0,0 +1,127 @@ +package cn.iocoder.yudao.module.trade.service.aftersale; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.AfterSaleDisagreeReqVO; +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.AfterSalePageReqVO; +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.AfterSaleRefuseReqVO; +import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSaleCreateReqVO; +import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSaleDeliveryReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleDO; + +/** + * 售后订单 Service 接口 + * + * @author 芋道源码 + */ +public interface AfterSaleService { + + /** + * 【管理员】获得售后订单分页 + * + * @param pageReqVO 分页查询 + * @return 售后订单分页 + */ + PageResult getAfterSalePage(AfterSalePageReqVO pageReqVO); + + /** + * 【会员】获得售后订单分页 + * + * @param userId 用户编号 + * @param pageParam 分页参数 + * @return 售后订单分页 + */ + PageResult getAfterSalePage(Long userId, PageParam pageParam); + + /** + * 【会员】获得售后单 + * + * @param userId 用户编号 + * @param id 售后编号 + * @return 售后订单 + */ + AfterSaleDO getAfterSale(Long userId, Long id); + + /** + * 【管理员】获得售后单 + * + * @param id 售后编号 + * @return 售后订单 + */ + AfterSaleDO getAfterSale(Long id); + + /** + * 【会员】创建售后订单 + * + * @param userId 会员用户编号 + * @param createReqVO 创建 Request 信息 + * @return 售后编号 + */ + Long createAfterSale(Long userId, AppAfterSaleCreateReqVO createReqVO); + + /** + * 【管理员】同意售后订单 + * + * @param userId 管理员用户编号 + * @param id 售后编号 + */ + void agreeAfterSale(Long userId, Long id); + + /** + * 【管理员】拒绝售后订单 + * + * @param userId 管理员用户编号 + * @param auditReqVO 审批 Request 信息 + */ + void disagreeAfterSale(Long userId, AfterSaleDisagreeReqVO auditReqVO); + + /** + * 【会员】退回货物 + * + * @param userId 会员用户编号 + * @param deliveryReqVO 退货 Request 信息 + */ + void deliveryAfterSale(Long userId, AppAfterSaleDeliveryReqVO deliveryReqVO); + + /** + * 【管理员】确认收货 + * + * @param userId 管理员编号 + * @param id 售后编号 + */ + void receiveAfterSale(Long userId, Long id); + + /** + * 【管理员】拒绝收货 + * + * @param userId 管理员用户编号 + * @param refuseReqVO 拒绝收货 Request 信息 + */ + void refuseAfterSale(Long userId, AfterSaleRefuseReqVO refuseReqVO); + + /** + * 【管理员】确认退款 + * + * @param userId 管理员用户编号 + * @param userIp 管理员用户 IP + * @param id 售后编号 + */ + void refundAfterSale(Long userId, String userIp, Long id); + + /** + * 【会员】取消售后 + * + * @param userId 会员用户编号 + * @param id 售后编号 + */ + void cancelAfterSale(Long userId, Long id); + + /** + * 【会员】获得正在进行中的售后订单数量 + * + * @param userId 用户编号 + * @return 数量 + */ + Long getApplyingAfterSaleCount(Long userId); + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleServiceImpl.java new file mode 100644 index 0000000..19248d1 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleServiceImpl.java @@ -0,0 +1,413 @@ +package cn.iocoder.yudao.module.trade.service.aftersale; + +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.module.pay.api.refund.PayRefundApi; +import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO; +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.AfterSaleDisagreeReqVO; +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.AfterSalePageReqVO; +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.AfterSaleRefuseReqVO; +import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSaleCreateReqVO; +import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSaleDeliveryReqVO; +import cn.iocoder.yudao.module.trade.convert.aftersale.AfterSaleConvert; +import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; +import cn.iocoder.yudao.module.trade.dal.mysql.aftersale.AfterSaleMapper; +import cn.iocoder.yudao.module.trade.dal.redis.no.TradeNoRedisDAO; +import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleOperateTypeEnum; +import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleStatusEnum; +import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleTypeEnum; +import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleWayEnum; +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum; +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; +import cn.iocoder.yudao.module.trade.framework.aftersale.core.annotations.AfterSaleLog; +import cn.iocoder.yudao.module.trade.framework.aftersale.core.utils.AfterSaleLogUtils; +import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; +import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService; +import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService; +import cn.iocoder.yudao.module.trade.service.order.TradeOrderUpdateService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.transaction.support.TransactionSynchronization; +import org.springframework.transaction.support.TransactionSynchronizationManager; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*; + +/** + * 售后订单 Service 实现类 + * + * @author 芋道源码 + */ +@Slf4j +@Service +@Validated +public class AfterSaleServiceImpl implements AfterSaleService { + + @Resource + private TradeOrderUpdateService tradeOrderUpdateService; + @Resource + private TradeOrderQueryService tradeOrderQueryService; + @Resource + private DeliveryExpressService deliveryExpressService; + + @Resource + private AfterSaleMapper tradeAfterSaleMapper; + @Resource + private TradeNoRedisDAO tradeNoRedisDAO; + + @Resource + private PayRefundApi payRefundApi; + + @Resource + private TradeOrderProperties tradeOrderProperties; + + @Override + public PageResult getAfterSalePage(AfterSalePageReqVO pageReqVO) { + return tradeAfterSaleMapper.selectPage(pageReqVO); + } + + @Override + public PageResult getAfterSalePage(Long userId, PageParam pageParam) { + return tradeAfterSaleMapper.selectPage(userId, pageParam); + } + + @Override + public AfterSaleDO getAfterSale(Long userId, Long id) { + return tradeAfterSaleMapper.selectByIdAndUserId(id, userId); + } + + @Override + public AfterSaleDO getAfterSale(Long id) { + return tradeAfterSaleMapper.selectById(id); + } + + @Override + @Transactional(rollbackFor = Exception.class) + @AfterSaleLog(operateType = AfterSaleOperateTypeEnum.MEMBER_CREATE) + public Long createAfterSale(Long userId, AppAfterSaleCreateReqVO createReqVO) { + // 第一步,前置校验 + TradeOrderItemDO tradeOrderItem = validateOrderItemApplicable(userId, createReqVO); + + // 第二步,存储售后订单 + AfterSaleDO afterSale = createAfterSale(createReqVO, tradeOrderItem); + return afterSale.getId(); + } + + /** + * 校验交易订单项是否可以申请售后 + * + * @param userId 用户编号 + * @param createReqVO 售后创建信息 + * @return 交易订单项 + */ + private TradeOrderItemDO validateOrderItemApplicable(Long userId, AppAfterSaleCreateReqVO createReqVO) { + // 校验订单项存在 + TradeOrderItemDO orderItem = tradeOrderQueryService.getOrderItem(userId, createReqVO.getOrderItemId()); + if (orderItem == null) { + throw exception(ORDER_ITEM_NOT_FOUND); + } + // 已申请售后,不允许再发起售后申请 + if (!TradeOrderItemAfterSaleStatusEnum.isNone(orderItem.getAfterSaleStatus())) { + throw exception(AFTER_SALE_CREATE_FAIL_ORDER_ITEM_APPLIED); + } + // 申请的退款金额,不能超过商品的价格 + if (createReqVO.getRefundPrice() > orderItem.getPayPrice()) { + throw exception(AFTER_SALE_CREATE_FAIL_REFUND_PRICE_ERROR); + } + + // 校验订单存在 + TradeOrderDO order = tradeOrderQueryService.getOrder(userId, orderItem.getOrderId()); + if (order == null) { + throw exception(ORDER_NOT_FOUND); + } + // TODO 芋艿:超过一定时间,不允许售后 + // 已取消,无法发起售后 + if (TradeOrderStatusEnum.isCanceled(order.getStatus())) { + throw exception(AFTER_SALE_CREATE_FAIL_ORDER_STATUS_CANCELED); + } + // 未支付,无法发起售后 + if (!TradeOrderStatusEnum.havePaid(order.getStatus())) { + throw exception(AFTER_SALE_CREATE_FAIL_ORDER_STATUS_NO_PAID); + } + // 如果是【退货退款】的情况,需要额外校验是否发货 + if (createReqVO.getWay().equals(AfterSaleWayEnum.RETURN_AND_REFUND.getWay()) + && !TradeOrderStatusEnum.haveDelivered(order.getStatus())) { + throw exception(AFTER_SALE_CREATE_FAIL_ORDER_STATUS_NO_DELIVERED); + } + return orderItem; + } + + private AfterSaleDO createAfterSale(AppAfterSaleCreateReqVO createReqVO, + TradeOrderItemDO orderItem) { + // 创建售后单 + AfterSaleDO afterSale = AfterSaleConvert.INSTANCE.convert(createReqVO, orderItem); + afterSale.setNo(tradeNoRedisDAO.generate(TradeNoRedisDAO.AFTER_SALE_NO_PREFIX)); + afterSale.setStatus(AfterSaleStatusEnum.APPLY.getStatus()); + // 标记是售中还是售后 + TradeOrderDO order = tradeOrderQueryService.getOrder(orderItem.getUserId(), orderItem.getOrderId()); + afterSale.setOrderNo(order.getNo()); // 记录 orderNo 订单流水,方便后续检索 + afterSale.setType(TradeOrderStatusEnum.isCompleted(order.getStatus()) + ? AfterSaleTypeEnum.AFTER_SALE.getType() : AfterSaleTypeEnum.IN_SALE.getType()); + tradeAfterSaleMapper.insert(afterSale); + + // 更新交易订单项的售后状态 + tradeOrderUpdateService.updateOrderItemWhenAfterSaleCreate(orderItem.getId(), afterSale.getId()); + + // 记录售后日志 + AfterSaleLogUtils.setAfterSaleInfo(afterSale.getId(), null, + AfterSaleStatusEnum.APPLY.getStatus()); + + // TODO 发送售后消息 + return afterSale; + } + + @Override + @Transactional(rollbackFor = Exception.class) + @AfterSaleLog(operateType = AfterSaleOperateTypeEnum.ADMIN_AGREE_APPLY) + public void agreeAfterSale(Long userId, Long id) { + // 校验售后单存在,并状态未审批 + AfterSaleDO afterSale = validateAfterSaleAuditable(id); + + // 更新售后单的状态 + // 情况一:退款:标记为 WAIT_REFUND 状态。后续等退款发起成功后,在标记为 COMPLETE 状态 + // 情况二:退货退款:需要等用户退货后,才能发起退款 + Integer newStatus = afterSale.getWay().equals(AfterSaleWayEnum.REFUND.getWay()) ? + AfterSaleStatusEnum.WAIT_REFUND.getStatus() : AfterSaleStatusEnum.SELLER_AGREE.getStatus(); + updateAfterSaleStatus(afterSale.getId(), AfterSaleStatusEnum.APPLY.getStatus(), new AfterSaleDO() + .setStatus(newStatus).setAuditUserId(userId).setAuditTime(LocalDateTime.now())); + + // 记录售后日志 + AfterSaleLogUtils.setAfterSaleInfo(afterSale.getId(), afterSale.getStatus(), newStatus); + + // TODO 发送售后消息 + } + + @Override + @Transactional(rollbackFor = Exception.class) + @AfterSaleLog(operateType = AfterSaleOperateTypeEnum.ADMIN_DISAGREE_APPLY) + public void disagreeAfterSale(Long userId, AfterSaleDisagreeReqVO auditReqVO) { + // 校验售后单存在,并状态未审批 + AfterSaleDO afterSale = validateAfterSaleAuditable(auditReqVO.getId()); + + // 更新售后单的状态 + Integer newStatus = AfterSaleStatusEnum.SELLER_DISAGREE.getStatus(); + updateAfterSaleStatus(afterSale.getId(), AfterSaleStatusEnum.APPLY.getStatus(), new AfterSaleDO() + .setStatus(newStatus).setAuditUserId(userId).setAuditTime(LocalDateTime.now()) + .setAuditReason(auditReqVO.getAuditReason())); + + // 记录售后日志 + AfterSaleLogUtils.setAfterSaleInfo(afterSale.getId(), afterSale.getStatus(), newStatus); + + // TODO 发送售后消息 + + // 更新交易订单项的售后状态为【未申请】 + tradeOrderUpdateService.updateOrderItemWhenAfterSaleCancel(afterSale.getOrderItemId()); + } + + /** + * 校验售后单是否可审批(同意售后、拒绝售后) + * + * @param id 售后编号 + * @return 售后单 + */ + private AfterSaleDO validateAfterSaleAuditable(Long id) { + AfterSaleDO afterSale = tradeAfterSaleMapper.selectById(id); + if (afterSale == null) { + throw exception(AFTER_SALE_NOT_FOUND); + } + if (ObjectUtil.notEqual(afterSale.getStatus(), AfterSaleStatusEnum.APPLY.getStatus())) { + throw exception(AFTER_SALE_AUDIT_FAIL_STATUS_NOT_APPLY); + } + return afterSale; + } + + private void updateAfterSaleStatus(Long id, Integer status, AfterSaleDO updateObj) { + int updateCount = tradeAfterSaleMapper.updateByIdAndStatus(id, status, updateObj); + if (updateCount == 0) { + throw exception(AFTER_SALE_UPDATE_STATUS_FAIL); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + @AfterSaleLog(operateType = AfterSaleOperateTypeEnum.MEMBER_DELIVERY) + public void deliveryAfterSale(Long userId, AppAfterSaleDeliveryReqVO deliveryReqVO) { + // 校验售后单存在,并状态未退货 + AfterSaleDO afterSale = tradeAfterSaleMapper.selectById(deliveryReqVO.getId()); + if (afterSale == null) { + throw exception(AFTER_SALE_NOT_FOUND); + } + if (ObjectUtil.notEqual(afterSale.getStatus(), AfterSaleStatusEnum.SELLER_AGREE.getStatus())) { + throw exception(AFTER_SALE_DELIVERY_FAIL_STATUS_NOT_SELLER_AGREE); + } + DeliveryExpressDO express = deliveryExpressService.validateDeliveryExpress(deliveryReqVO.getLogisticsId()); + + // 更新售后单的物流信息 + updateAfterSaleStatus(afterSale.getId(), AfterSaleStatusEnum.SELLER_AGREE.getStatus(), new AfterSaleDO() + .setStatus(AfterSaleStatusEnum.BUYER_DELIVERY.getStatus()) + .setLogisticsId(deliveryReqVO.getLogisticsId()).setLogisticsNo(deliveryReqVO.getLogisticsNo()) + .setDeliveryTime(LocalDateTime.now())); + + // 记录售后日志 + AfterSaleLogUtils.setAfterSaleInfo(afterSale.getId(), afterSale.getStatus(), + AfterSaleStatusEnum.BUYER_DELIVERY.getStatus(), + MapUtil.builder().put("expressName", express.getName()) + .put("logisticsNo", deliveryReqVO.getLogisticsNo()).build()); + + // TODO 发送售后消息 + } + + @Override + @Transactional(rollbackFor = Exception.class) + @AfterSaleLog(operateType = AfterSaleOperateTypeEnum.ADMIN_AGREE_RECEIVE) + public void receiveAfterSale(Long userId, Long id) { + // 校验售后单存在,并状态为已退货 + AfterSaleDO afterSale = validateAfterSaleReceivable(id); + + // 更新售后单的状态 + updateAfterSaleStatus(afterSale.getId(), AfterSaleStatusEnum.BUYER_DELIVERY.getStatus(), new AfterSaleDO() + .setStatus(AfterSaleStatusEnum.WAIT_REFUND.getStatus()).setReceiveTime(LocalDateTime.now())); + + // 记录售后日志 + AfterSaleLogUtils.setAfterSaleInfo(afterSale.getId(), afterSale.getStatus(), + AfterSaleStatusEnum.WAIT_REFUND.getStatus()); + + // TODO 发送售后消息 + } + + @Override + @Transactional(rollbackFor = Exception.class) + @AfterSaleLog(operateType = AfterSaleOperateTypeEnum.ADMIN_DISAGREE_RECEIVE) + public void refuseAfterSale(Long userId, AfterSaleRefuseReqVO refuseReqVO) { + // 校验售后单存在,并状态为已退货 + AfterSaleDO afterSale = tradeAfterSaleMapper.selectById(refuseReqVO.getId()); + if (afterSale == null) { + throw exception(AFTER_SALE_NOT_FOUND); + } + if (ObjectUtil.notEqual(afterSale.getStatus(), AfterSaleStatusEnum.BUYER_DELIVERY.getStatus())) { + throw exception(AFTER_SALE_CONFIRM_FAIL_STATUS_NOT_BUYER_DELIVERY); + } + + // 更新售后单的状态 + updateAfterSaleStatus(afterSale.getId(), AfterSaleStatusEnum.BUYER_DELIVERY.getStatus(), new AfterSaleDO() + .setStatus(AfterSaleStatusEnum.SELLER_REFUSE.getStatus()).setReceiveTime(LocalDateTime.now()) + .setReceiveReason(refuseReqVO.getRefuseMemo())); + + // 记录售后日志 + AfterSaleLogUtils.setAfterSaleInfo(afterSale.getId(), afterSale.getStatus(), + AfterSaleStatusEnum.SELLER_REFUSE.getStatus(), + MapUtil.of("reason", refuseReqVO.getRefuseMemo())); + + // TODO 发送售后消息 + + // 更新交易订单项的售后状态为【未申请】 + tradeOrderUpdateService.updateOrderItemWhenAfterSaleCancel(afterSale.getOrderItemId()); + } + + /** + * 校验售后单是否可收货,即处于买家已发货 + * + * @param id 售后编号 + * @return 售后单 + */ + private AfterSaleDO validateAfterSaleReceivable(Long id) { + AfterSaleDO afterSale = tradeAfterSaleMapper.selectById(id); + if (afterSale == null) { + throw exception(AFTER_SALE_NOT_FOUND); + } + if (ObjectUtil.notEqual(afterSale.getStatus(), AfterSaleStatusEnum.BUYER_DELIVERY.getStatus())) { + throw exception(AFTER_SALE_CONFIRM_FAIL_STATUS_NOT_BUYER_DELIVERY); + } + return afterSale; + } + + @Override + @Transactional(rollbackFor = Exception.class) + @AfterSaleLog(operateType = AfterSaleOperateTypeEnum.ADMIN_REFUND) + public void refundAfterSale(Long userId, String userIp, Long id) { + // 校验售后单的状态,并状态待退款 + AfterSaleDO afterSale = tradeAfterSaleMapper.selectById(id); + if (afterSale == null) { + throw exception(AFTER_SALE_NOT_FOUND); + } + if (ObjectUtil.notEqual(afterSale.getStatus(), AfterSaleStatusEnum.WAIT_REFUND.getStatus())) { + throw exception(AFTER_SALE_REFUND_FAIL_STATUS_NOT_WAIT_REFUND); + } + + // 发起退款单。注意,需要在事务提交后,再进行发起,避免重复发起 + createPayRefund(userIp, afterSale); + + // 更新售后单的状态为【已完成】 + updateAfterSaleStatus(afterSale.getId(), AfterSaleStatusEnum.WAIT_REFUND.getStatus(), new AfterSaleDO() + .setStatus(AfterSaleStatusEnum.COMPLETE.getStatus()).setRefundTime(LocalDateTime.now())); + + // 记录售后日志 + AfterSaleLogUtils.setAfterSaleInfo(afterSale.getId(), afterSale.getStatus(), + AfterSaleStatusEnum.COMPLETE.getStatus()); + + // TODO 发送售后消息 + + // 更新交易订单项的售后状态为【已完成】 + tradeOrderUpdateService.updateOrderItemWhenAfterSaleSuccess(afterSale.getOrderItemId(), afterSale.getRefundPrice()); + } + + private void createPayRefund(String userIp, AfterSaleDO afterSale) { + TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { + + @Override + public void afterCommit() { + // 创建退款单 + PayRefundCreateReqDTO createReqDTO = AfterSaleConvert.INSTANCE.convert(userIp, afterSale, tradeOrderProperties); + Long payRefundId = payRefundApi.createRefund(createReqDTO); + // 更新售后单的退款单号 + tradeAfterSaleMapper.updateById(new AfterSaleDO().setId(afterSale.getId()).setPayRefundId(payRefundId)); + } + }); + } + + @Override + @Transactional(rollbackFor = Exception.class) + @AfterSaleLog(operateType = AfterSaleOperateTypeEnum.MEMBER_CANCEL) + public void cancelAfterSale(Long userId, Long id) { + // 校验售后单的状态,并状态待退款 + AfterSaleDO afterSale = tradeAfterSaleMapper.selectById(id); + if (afterSale == null) { + throw exception(AFTER_SALE_NOT_FOUND); + } + if (!ObjectUtils.equalsAny(afterSale.getStatus(), AfterSaleStatusEnum.APPLY.getStatus(), + AfterSaleStatusEnum.SELLER_AGREE.getStatus(), + AfterSaleStatusEnum.BUYER_DELIVERY.getStatus())) { + throw exception(AFTER_SALE_CANCEL_FAIL_STATUS_NOT_APPLY_OR_AGREE_OR_BUYER_DELIVERY); + } + + // 更新售后单的状态为【已取消】 + updateAfterSaleStatus(afterSale.getId(), afterSale.getStatus(), new AfterSaleDO() + .setStatus(AfterSaleStatusEnum.BUYER_CANCEL.getStatus())); + + // 记录售后日志 + AfterSaleLogUtils.setAfterSaleInfo(afterSale.getId(), afterSale.getStatus(), + AfterSaleStatusEnum.BUYER_CANCEL.getStatus()); + + // TODO 发送售后消息 + + // 更新交易订单项的售后状态为【未申请】 + tradeOrderUpdateService.updateOrderItemWhenAfterSaleCancel(afterSale.getOrderItemId()); + } + + @Override + public Long getApplyingAfterSaleCount(Long userId) { + return tradeAfterSaleMapper.selectCountByUserIdAndStatus(userId, AfterSaleStatusEnum.APPLYING_STATUSES); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleService.java deleted file mode 100644 index a7b2db6..0000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleService.java +++ /dev/null @@ -1,127 +0,0 @@ -package cn.iocoder.yudao.module.trade.service.aftersale; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleDisagreeReqVO; -import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSalePageReqVO; -import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleRefuseReqVO; -import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleCreateReqVO; -import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleDeliveryReqVO; -import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO; - -/** - * 售后订单 Service 接口 - * - * @author 芋道源码 - */ -public interface TradeAfterSaleService { - - /** - * 【管理员】获得售后订单分页 - * - * @param pageReqVO 分页查询 - * @return 售后订单分页 - */ - PageResult getAfterSalePage(TradeAfterSalePageReqVO pageReqVO); - - /** - * 【会员】获得售后订单分页 - * - * @param userId 用户编号 - * @param pageParam 分页参数 - * @return 售后订单分页 - */ - PageResult getAfterSalePage(Long userId, PageParam pageParam); - - /** - * 【会员】获得售后单 - * - * @param userId 用户编号 - * @param id 售后编号 - * @return 售后订单 - */ - TradeAfterSaleDO getAfterSale(Long userId, Long id); - - /** - * 【管理员】获得售后单 - * - * @param id 售后编号 - * @return 售后订单 - */ - TradeAfterSaleDO getAfterSale(Long id); - - /** - * 【会员】创建售后订单 - * - * @param userId 会员用户编号 - * @param createReqVO 创建 Request 信息 - * @return 售后编号 - */ - Long createAfterSale(Long userId, AppTradeAfterSaleCreateReqVO createReqVO); - - /** - * 【管理员】同意售后订单 - * - * @param userId 管理员用户编号 - * @param id 售后编号 - */ - void agreeAfterSale(Long userId, Long id); - - /** - * 【管理员】拒绝售后订单 - * - * @param userId 管理员用户编号 - * @param auditReqVO 审批 Request 信息 - */ - void disagreeAfterSale(Long userId, TradeAfterSaleDisagreeReqVO auditReqVO); - - /** - * 【会员】退回货物 - * - * @param userId 会员用户编号 - * @param deliveryReqVO 退货 Request 信息 - */ - void deliveryAfterSale(Long userId, AppTradeAfterSaleDeliveryReqVO deliveryReqVO); - - /** - * 【管理员】确认收货 - * - * @param userId 管理员编号 - * @param id 售后编号 - */ - void receiveAfterSale(Long userId, Long id); - - /** - * 【管理员】拒绝收货 - * - * @param userId 管理员用户编号 - * @param refuseReqVO 拒绝收货 Request 信息 - */ - void refuseAfterSale(Long userId, TradeAfterSaleRefuseReqVO refuseReqVO); - - /** - * 【管理员】确认退款 - * - * @param userId 管理员用户编号 - * @param userIp 管理员用户 IP - * @param id 售后编号 - */ - void refundAfterSale(Long userId, String userIp, Long id); - - /** - * 【会员】取消售后 - * - * @param userId 会员用户编号 - * @param id 售后编号 - */ - void cancelAfterSale(Long userId, Long id); - - /** - * 【会员】获得正在进行中的售后订单数量 - * - * @param userId - * @return 数量 - */ - Long getApplyingAfterSaleCount(Long userId); - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java deleted file mode 100644 index cce494e..0000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java +++ /dev/null @@ -1,466 +0,0 @@ -package cn.iocoder.yudao.module.trade.service.aftersale; - -import cn.hutool.core.map.MapUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.RandomUtil; -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; -import cn.iocoder.yudao.module.pay.api.refund.PayRefundApi; -import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO; -import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleDisagreeReqVO; -import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSalePageReqVO; -import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleRefuseReqVO; -import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.log.TradeAfterSaleLogRespVO; -import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleCreateReqVO; -import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleDeliveryReqVO; -import cn.iocoder.yudao.module.trade.convert.aftersale.TradeAfterSaleConvert; -import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO; -import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleLogDO; -import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; -import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; -import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; -import cn.iocoder.yudao.module.trade.dal.mysql.aftersale.TradeAfterSaleLogMapper; -import cn.iocoder.yudao.module.trade.dal.mysql.aftersale.TradeAfterSaleMapper; -import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleOperateTypeEnum; -import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleStatusEnum; -import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleTypeEnum; -import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleWayEnum; -import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum; -import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; -import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.annotations.AfterSaleLog; -import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.dto.TradeAfterSaleLogCreateReqDTO; -import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.service.AfterSaleLogService; -import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.util.AfterSaleLogUtils; -import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; -import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService; -import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService; -import cn.iocoder.yudao.module.trade.service.order.TradeOrderUpdateService; -import lombok.extern.slf4j.Slf4j; -import org.springframework.scheduling.annotation.Async; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.transaction.support.TransactionSynchronization; -import org.springframework.transaction.support.TransactionSynchronizationManager; -import org.springframework.validation.annotation.Validated; - -import javax.annotation.Resource; -import java.time.LocalDateTime; -import java.util.List; - -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; -import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*; - -/** - * 售后订单 Service 实现类 - * - * @author 芋道源码 - */ -@Slf4j -@Service -@Validated -public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSaleLogService { - - @Resource - private TradeOrderUpdateService tradeOrderUpdateService; - @Resource - private TradeOrderQueryService tradeOrderQueryService; - @Resource - private DeliveryExpressService deliveryExpressService; - - @Resource - private TradeAfterSaleMapper tradeAfterSaleMapper; - @Resource - private TradeAfterSaleLogMapper tradeAfterSaleLogMapper; - - @Resource - private PayRefundApi payRefundApi; - - @Resource - private TradeOrderProperties tradeOrderProperties; - - @Override - public PageResult getAfterSalePage(TradeAfterSalePageReqVO pageReqVO) { - return tradeAfterSaleMapper.selectPage(pageReqVO); - } - - @Override - public PageResult getAfterSalePage(Long userId, PageParam pageParam) { - return tradeAfterSaleMapper.selectPage(userId, pageParam); - } - - @Override - public TradeAfterSaleDO getAfterSale(Long userId, Long id) { - return tradeAfterSaleMapper.selectByIdAndUserId(id, userId); - } - - @Override - public TradeAfterSaleDO getAfterSale(Long id) { - return tradeAfterSaleMapper.selectById(id); - } - - @Override - @Transactional(rollbackFor = Exception.class) - @AfterSaleLog(operateType = AfterSaleOperateTypeEnum.MEMBER_CREATE) - public Long createAfterSale(Long userId, AppTradeAfterSaleCreateReqVO createReqVO) { - // 第一步,前置校验 - TradeOrderItemDO tradeOrderItem = validateOrderItemApplicable(userId, createReqVO); - - // 第二步,存储售后订单 - TradeAfterSaleDO afterSale = createAfterSale(createReqVO, tradeOrderItem); - return afterSale.getId(); - } - - /** - * 校验交易订单项是否可以申请售后 - * - * @param userId 用户编号 - * @param createReqVO 售后创建信息 - * @return 交易订单项 - */ - private TradeOrderItemDO validateOrderItemApplicable(Long userId, AppTradeAfterSaleCreateReqVO createReqVO) { - // 校验订单项存在 - TradeOrderItemDO orderItem = tradeOrderQueryService.getOrderItem(userId, createReqVO.getOrderItemId()); - if (orderItem == null) { - throw exception(ORDER_ITEM_NOT_FOUND); - } - // 已申请售后,不允许再发起售后申请 - if (!TradeOrderItemAfterSaleStatusEnum.isNone(orderItem.getAfterSaleStatus())) { - throw exception(AFTER_SALE_CREATE_FAIL_ORDER_ITEM_APPLIED); - } - // 申请的退款金额,不能超过商品的价格 - if (createReqVO.getRefundPrice() > orderItem.getPayPrice()) { - throw exception(AFTER_SALE_CREATE_FAIL_REFUND_PRICE_ERROR); - } - - // 校验订单存在 - TradeOrderDO order = tradeOrderQueryService.getOrder(userId, orderItem.getOrderId()); - if (order == null) { - throw exception(ORDER_NOT_FOUND); - } - // TODO 芋艿:超过一定时间,不允许售后 - // 已取消,无法发起售后 - if (TradeOrderStatusEnum.isCanceled(order.getStatus())) { - throw exception(AFTER_SALE_CREATE_FAIL_ORDER_STATUS_CANCELED); - } - // 未支付,无法发起售后 - if (!TradeOrderStatusEnum.havePaid(order.getStatus())) { - throw exception(AFTER_SALE_CREATE_FAIL_ORDER_STATUS_NO_PAID); - } - // 如果是【退货退款】的情况,需要额外校验是否发货 - if (createReqVO.getWay().equals(TradeAfterSaleWayEnum.RETURN_AND_REFUND.getWay()) - && !TradeOrderStatusEnum.haveDelivered(order.getStatus())) { - throw exception(AFTER_SALE_CREATE_FAIL_ORDER_STATUS_NO_DELIVERED); - } - return orderItem; - } - - private TradeAfterSaleDO createAfterSale(AppTradeAfterSaleCreateReqVO createReqVO, - TradeOrderItemDO orderItem) { - // 创建售后单 - TradeAfterSaleDO afterSale = TradeAfterSaleConvert.INSTANCE.convert(createReqVO, orderItem); - afterSale.setNo(RandomUtil.randomString(10)); // TODO 芋艿:优化 no 生成逻辑 - afterSale.setStatus(TradeAfterSaleStatusEnum.APPLY.getStatus()); - // 标记是售中还是售后 - TradeOrderDO order = tradeOrderQueryService.getOrder(orderItem.getUserId(), orderItem.getOrderId()); - afterSale.setOrderNo(order.getNo()); // 记录 orderNo 订单流水,方便后续检索 - afterSale.setType(TradeOrderStatusEnum.isCompleted(order.getStatus()) - ? TradeAfterSaleTypeEnum.AFTER_SALE.getType() : TradeAfterSaleTypeEnum.IN_SALE.getType()); - tradeAfterSaleMapper.insert(afterSale); - - // 更新交易订单项的售后状态 - tradeOrderUpdateService.updateOrderItemWhenAfterSaleCreate(orderItem.getId(), afterSale.getId()); - - // 记录售后日志 - AfterSaleLogUtils.setAfterSaleInfo(afterSale.getId(), null, - TradeAfterSaleStatusEnum.APPLY.getStatus()); - - // TODO 发送售后消息 - return afterSale; - } - - @Override - @Transactional(rollbackFor = Exception.class) - @AfterSaleLog(operateType = AfterSaleOperateTypeEnum.ADMIN_AGREE_APPLY) - public void agreeAfterSale(Long userId, Long id) { - // 校验售后单存在,并状态未审批 - TradeAfterSaleDO afterSale = validateAfterSaleAuditable(id); - - // 更新售后单的状态 - // 情况一:退款:标记为 WAIT_REFUND 状态。后续等退款发起成功后,在标记为 COMPLETE 状态 - // 情况二:退货退款:需要等用户退货后,才能发起退款 - Integer newStatus = afterSale.getWay().equals(TradeAfterSaleWayEnum.REFUND.getWay()) ? - TradeAfterSaleStatusEnum.WAIT_REFUND.getStatus() : TradeAfterSaleStatusEnum.SELLER_AGREE.getStatus(); - updateAfterSaleStatus(afterSale.getId(), TradeAfterSaleStatusEnum.APPLY.getStatus(), new TradeAfterSaleDO() - .setStatus(newStatus).setAuditUserId(userId).setAuditTime(LocalDateTime.now())); - - // 记录售后日志 - AfterSaleLogUtils.setAfterSaleInfo(afterSale.getId(), afterSale.getStatus(), newStatus); - - // TODO 发送售后消息 - } - - @Override - @Transactional(rollbackFor = Exception.class) - @AfterSaleLog(operateType = AfterSaleOperateTypeEnum.ADMIN_DISAGREE_APPLY) - public void disagreeAfterSale(Long userId, TradeAfterSaleDisagreeReqVO auditReqVO) { - // 校验售后单存在,并状态未审批 - TradeAfterSaleDO afterSale = validateAfterSaleAuditable(auditReqVO.getId()); - - // 更新售后单的状态 - Integer newStatus = TradeAfterSaleStatusEnum.SELLER_DISAGREE.getStatus(); - updateAfterSaleStatus(afterSale.getId(), TradeAfterSaleStatusEnum.APPLY.getStatus(), new TradeAfterSaleDO() - .setStatus(newStatus).setAuditUserId(userId).setAuditTime(LocalDateTime.now()) - .setAuditReason(auditReqVO.getAuditReason())); - - // 记录售后日志 - AfterSaleLogUtils.setAfterSaleInfo(afterSale.getId(), afterSale.getStatus(), newStatus); - - // TODO 发送售后消息 - - // 更新交易订单项的售后状态为【未申请】 - tradeOrderUpdateService.updateOrderItemWhenAfterSaleCancel(afterSale.getOrderItemId()); - } - - /** - * 校验售后单是否可审批(同意售后、拒绝售后) - * - * @param id 售后编号 - * @return 售后单 - */ - private TradeAfterSaleDO validateAfterSaleAuditable(Long id) { - TradeAfterSaleDO afterSale = tradeAfterSaleMapper.selectById(id); - if (afterSale == null) { - throw exception(AFTER_SALE_NOT_FOUND); - } - if (ObjectUtil.notEqual(afterSale.getStatus(), TradeAfterSaleStatusEnum.APPLY.getStatus())) { - throw exception(AFTER_SALE_AUDIT_FAIL_STATUS_NOT_APPLY); - } - return afterSale; - } - - private void updateAfterSaleStatus(Long id, Integer status, TradeAfterSaleDO updateObj) { - int updateCount = tradeAfterSaleMapper.updateByIdAndStatus(id, status, updateObj); - if (updateCount == 0) { - throw exception(AFTER_SALE_UPDATE_STATUS_FAIL); - } - } - - @Override - @Transactional(rollbackFor = Exception.class) - @AfterSaleLog(operateType = AfterSaleOperateTypeEnum.MEMBER_DELIVERY) - public void deliveryAfterSale(Long userId, AppTradeAfterSaleDeliveryReqVO deliveryReqVO) { - // 校验售后单存在,并状态未退货 - TradeAfterSaleDO afterSale = tradeAfterSaleMapper.selectById(deliveryReqVO.getId()); - if (afterSale == null) { - throw exception(AFTER_SALE_NOT_FOUND); - } - if (ObjectUtil.notEqual(afterSale.getStatus(), TradeAfterSaleStatusEnum.SELLER_AGREE.getStatus())) { - throw exception(AFTER_SALE_DELIVERY_FAIL_STATUS_NOT_SELLER_AGREE); - } - DeliveryExpressDO express = deliveryExpressService.validateDeliveryExpress(deliveryReqVO.getLogisticsId()); - - // 更新售后单的物流信息 - updateAfterSaleStatus(afterSale.getId(), TradeAfterSaleStatusEnum.SELLER_AGREE.getStatus(), new TradeAfterSaleDO() - .setStatus(TradeAfterSaleStatusEnum.BUYER_DELIVERY.getStatus()) - .setLogisticsId(deliveryReqVO.getLogisticsId()).setLogisticsNo(deliveryReqVO.getLogisticsNo()) - .setDeliveryTime(LocalDateTime.now())); - - // 记录售后日志 - AfterSaleLogUtils.setAfterSaleInfo(afterSale.getId(), afterSale.getStatus(), - TradeAfterSaleStatusEnum.BUYER_DELIVERY.getStatus(), - MapUtil.builder().put("expressName", express.getName()) - .put("logisticsNo", deliveryReqVO.getLogisticsNo()).build()); - - // TODO 发送售后消息 - } - - @Override - @Transactional(rollbackFor = Exception.class) - @AfterSaleLog(operateType = AfterSaleOperateTypeEnum.ADMIN_AGREE_RECEIVE) - public void receiveAfterSale(Long userId, Long id) { - // 校验售后单存在,并状态为已退货 - TradeAfterSaleDO afterSale = validateAfterSaleReceivable(id); - - // 更新售后单的状态 - updateAfterSaleStatus(afterSale.getId(), TradeAfterSaleStatusEnum.BUYER_DELIVERY.getStatus(), new TradeAfterSaleDO() - .setStatus(TradeAfterSaleStatusEnum.WAIT_REFUND.getStatus()).setReceiveTime(LocalDateTime.now())); - - // 记录售后日志 - AfterSaleLogUtils.setAfterSaleInfo(afterSale.getId(), afterSale.getStatus(), - TradeAfterSaleStatusEnum.WAIT_REFUND.getStatus()); - - // TODO 发送售后消息 - } - - @Override - @Transactional(rollbackFor = Exception.class) - @AfterSaleLog(operateType = AfterSaleOperateTypeEnum.ADMIN_DISAGREE_RECEIVE) - public void refuseAfterSale(Long userId, TradeAfterSaleRefuseReqVO refuseReqVO) { - // 校验售后单存在,并状态为已退货 - TradeAfterSaleDO afterSale = tradeAfterSaleMapper.selectById(refuseReqVO.getId()); - if (afterSale == null) { - throw exception(AFTER_SALE_NOT_FOUND); - } - if (ObjectUtil.notEqual(afterSale.getStatus(), TradeAfterSaleStatusEnum.BUYER_DELIVERY.getStatus())) { - throw exception(AFTER_SALE_CONFIRM_FAIL_STATUS_NOT_BUYER_DELIVERY); - } - - // 更新售后单的状态 - updateAfterSaleStatus(afterSale.getId(), TradeAfterSaleStatusEnum.BUYER_DELIVERY.getStatus(), new TradeAfterSaleDO() - .setStatus(TradeAfterSaleStatusEnum.SELLER_REFUSE.getStatus()).setReceiveTime(LocalDateTime.now()) - .setReceiveReason(refuseReqVO.getRefuseMemo())); - - // 记录售后日志 - AfterSaleLogUtils.setAfterSaleInfo(afterSale.getId(), afterSale.getStatus(), - TradeAfterSaleStatusEnum.SELLER_REFUSE.getStatus(), - MapUtil.of("reason", refuseReqVO.getRefuseMemo())); - - // TODO 发送售后消息 - - // 更新交易订单项的售后状态为【未申请】 - tradeOrderUpdateService.updateOrderItemWhenAfterSaleCancel(afterSale.getOrderItemId()); - } - - /** - * 校验售后单是否可收货,即处于买家已发货 - * - * @param id 售后编号 - * @return 售后单 - */ - private TradeAfterSaleDO validateAfterSaleReceivable(Long id) { - TradeAfterSaleDO afterSale = tradeAfterSaleMapper.selectById(id); - if (afterSale == null) { - throw exception(AFTER_SALE_NOT_FOUND); - } - if (ObjectUtil.notEqual(afterSale.getStatus(), TradeAfterSaleStatusEnum.BUYER_DELIVERY.getStatus())) { - throw exception(AFTER_SALE_CONFIRM_FAIL_STATUS_NOT_BUYER_DELIVERY); - } - return afterSale; - } - - @Override - @Transactional(rollbackFor = Exception.class) - @AfterSaleLog(operateType = AfterSaleOperateTypeEnum.ADMIN_REFUND) - public void refundAfterSale(Long userId, String userIp, Long id) { - // 校验售后单的状态,并状态待退款 - TradeAfterSaleDO afterSale = tradeAfterSaleMapper.selectById(id); - if (afterSale == null) { - throw exception(AFTER_SALE_NOT_FOUND); - } - if (ObjectUtil.notEqual(afterSale.getStatus(), TradeAfterSaleStatusEnum.WAIT_REFUND.getStatus())) { - throw exception(AFTER_SALE_REFUND_FAIL_STATUS_NOT_WAIT_REFUND); - } - - // 发起退款单。注意,需要在事务提交后,再进行发起,避免重复发起 - createPayRefund(userIp, afterSale); - - // 更新售后单的状态为【已完成】 - updateAfterSaleStatus(afterSale.getId(), TradeAfterSaleStatusEnum.WAIT_REFUND.getStatus(), new TradeAfterSaleDO() - .setStatus(TradeAfterSaleStatusEnum.COMPLETE.getStatus()).setRefundTime(LocalDateTime.now())); - - // 记录售后日志 - AfterSaleLogUtils.setAfterSaleInfo(afterSale.getId(), afterSale.getStatus(), - TradeAfterSaleStatusEnum.COMPLETE.getStatus()); - - // TODO 发送售后消息 - - // 更新交易订单项的售后状态为【已完成】 - tradeOrderUpdateService.updateOrderItemWhenAfterSaleSuccess(afterSale.getOrderItemId(), afterSale.getRefundPrice()); - } - - private void createPayRefund(String userIp, TradeAfterSaleDO afterSale) { - TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { - - @Override - public void afterCommit() { - // 创建退款单 - PayRefundCreateReqDTO createReqDTO = TradeAfterSaleConvert.INSTANCE.convert(userIp, afterSale, tradeOrderProperties); - Long payRefundId = payRefundApi.createRefund(createReqDTO); - // 更新售后单的退款单号 - tradeAfterSaleMapper.updateById(new TradeAfterSaleDO().setId(afterSale.getId()).setPayRefundId(payRefundId)); - } - }); - } - - @Override - @Transactional(rollbackFor = Exception.class) - @AfterSaleLog(operateType = AfterSaleOperateTypeEnum.MEMBER_CANCEL) - public void cancelAfterSale(Long userId, Long id) { - // 校验售后单的状态,并状态待退款 - TradeAfterSaleDO afterSale = tradeAfterSaleMapper.selectById(id); - if (afterSale == null) { - throw exception(AFTER_SALE_NOT_FOUND); - } - if (!ObjectUtils.equalsAny(afterSale.getStatus(), TradeAfterSaleStatusEnum.APPLY.getStatus(), - TradeAfterSaleStatusEnum.SELLER_AGREE.getStatus(), - TradeAfterSaleStatusEnum.BUYER_DELIVERY.getStatus())) { - throw exception(AFTER_SALE_CANCEL_FAIL_STATUS_NOT_APPLY_OR_AGREE_OR_BUYER_DELIVERY); - } - - // 更新售后单的状态为【已取消】 - updateAfterSaleStatus(afterSale.getId(), afterSale.getStatus(), new TradeAfterSaleDO() - .setStatus(TradeAfterSaleStatusEnum.BUYER_CANCEL.getStatus())); - - // 记录售后日志 - AfterSaleLogUtils.setAfterSaleInfo(afterSale.getId(), afterSale.getStatus(), - TradeAfterSaleStatusEnum.BUYER_CANCEL.getStatus()); - - // TODO 发送售后消息 - - // 更新交易订单项的售后状态为【未申请】 - tradeOrderUpdateService.updateOrderItemWhenAfterSaleCancel(afterSale.getOrderItemId()); - } - - @Override - public Long getApplyingAfterSaleCount(Long userId) { - return tradeAfterSaleMapper.selectCountByUserIdAndStatus(userId, TradeAfterSaleStatusEnum.APPLYING_STATUSES); - } - - @Deprecated - private void createAfterSaleLog(Long userId, Integer userType, TradeAfterSaleDO afterSale, - Integer beforeStatus, Integer afterStatus) { - TradeAfterSaleLogCreateReqDTO logDTO = new TradeAfterSaleLogCreateReqDTO() - .setUserId(userId) - .setUserType(userType) - .setAfterSaleId(afterSale.getId()) - .setOperateType(afterStatus.toString()); - // TODO 废弃,待删除 - this.createLog(logDTO); - } - - // TODO @CHENCHEN:这个注释,写在接口就好了,补充重复写哈;@date 应该是 @since - /** - * 日志记录 - * - * @param logDTO 日志记录 - * @author 陈賝 - * @date 2023/6/12 14:18 - */ - @Override - @Async - public void createLog(TradeAfterSaleLogCreateReqDTO logDTO) { - try { - TradeAfterSaleLogDO afterSaleLog = new TradeAfterSaleLogDO() - .setUserId(logDTO.getUserId()) - .setUserType(logDTO.getUserType()) - .setAfterSaleId(logDTO.getAfterSaleId()) - .setOperateType(logDTO.getOperateType()) - .setContent(logDTO.getContent()); - tradeAfterSaleLogMapper.insert(afterSaleLog); - // TODO @CHENCHEN:代码排版哈;空格要正确 - }catch (Exception exception){ - log.error("[createLog][request({}) 日志记录错误]", toJsonString(logDTO), exception); - } - } - - // TODO @puhui999:应该返回 do 哈。 - @Override - public List getLog(Long afterSaleId) { - // TODO 不熟悉流程先这么滴 - List saleLogDOs = tradeAfterSaleLogMapper.selectList(TradeAfterSaleLogDO::getAfterSaleId, afterSaleId); - return TradeAfterSaleConvert.INSTANCE.convertList(saleLogDOs); - } - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/bo/AfterSaleLogCreateReqBO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/bo/AfterSaleLogCreateReqBO.java new file mode 100644 index 0000000..5793fed --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/bo/AfterSaleLogCreateReqBO.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.trade.service.aftersale.bo; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +/** + * 售后日志的创建 Request BO + * + * @author 陈賝 + * @since 2023/6/19 09:54 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class AfterSaleLogCreateReqBO { + + /** + * 用户编号 + */ + @NotNull(message = "用户编号不能为空") + private Long userId; + /** + * 用户类型 + */ + @NotNull(message = "用户类型不能为空") + private Integer userType; + + /** + * 售后编号 + */ + @NotNull(message = "售后编号不能为空") + private Long afterSaleId; + /** + * 操作前状态 + */ + private Integer beforeStatus; + /** + * 操作后状态 + */ + @NotNull(message = "操作后的状态不能为空") + private Integer afterStatus; + + /** + * 操作类型 + */ + @NotNull(message = "操作类型不能为空") + private Integer operateType; + /** + * 操作明细 + */ + @NotEmpty(message = "操作明细不能为空") + private String content; +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryService.java index 6bd9b2b..442f83d 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryService.java @@ -94,12 +94,12 @@ public interface TradeOrderQueryService { TradeOrderItemDO getOrderItem(Long userId, Long itemId); /** - * 根据交易订单项编号数组,查询交易订单项 + * 获得交易订单项 * - * @param ids 交易订单项编号数组 - * @return 交易订单项数组 + * @param id 交易订单项编号 itemId + * @return 交易订单项 */ - List getOrderItemList(Collection ids); + TradeOrderItemDO getOrderItem(Long id); /** * 根据交易订单编号,查询交易订单项 @@ -119,5 +119,4 @@ public interface TradeOrderQueryService { */ List getOrderItemListByOrderId(Collection orderIds); - } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryServiceImpl.java index 501a925..c0dfbfd 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryServiceImpl.java @@ -156,8 +156,8 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService { } @Override - public List getOrderItemList(Collection ids) { - return tradeOrderItemMapper.selectBatchIds(ids); + public TradeOrderItemDO getOrderItem(Long id) { + return tradeOrderItemMapper.selectById(id); } @Override diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java index 66dc234..79f4a82 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java @@ -47,7 +47,7 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper; import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper; -import cn.iocoder.yudao.module.trade.dal.redis.no.TradeOrderNoRedisDAO; +import cn.iocoder.yudao.module.trade.dal.redis.no.TradeNoRedisDAO; import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; import cn.iocoder.yudao.module.trade.enums.order.*; @@ -97,7 +97,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @Resource private TradeOrderItemMapper tradeOrderItemMapper; @Resource - private TradeOrderNoRedisDAO orderNoRedisDAO; + private TradeNoRedisDAO tradeNoRedisDAO; @Resource private List tradeOrderHandlers; @@ -215,7 +215,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { TradePriceCalculateRespBO calculateRespBO) { TradeOrderDO order = TradeOrderConvert.INSTANCE.convert(userId, clientIp, createReqVO, calculateRespBO); order.setType(calculateRespBO.getType()); - order.setNo(orderNoRedisDAO.generate(TradeOrderNoRedisDAO.TRADE_ORDER_NO_PREFIX)); + order.setNo(tradeNoRedisDAO.generate(TradeNoRedisDAO.TRADE_ORDER_NO_PREFIX)); order.setStatus(TradeOrderStatusEnum.UNPAID.getStatus()); order.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus()); order.setProductCount(getSumValue(calculateRespBO.getItems(), TradePriceCalculateRespBO.OrderItem::getCount, Integer::sum)); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/logger/TradeOrderLogCreateReqBO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/logger/TradeOrderLogCreateReqBO.java index 3fd56d0..abfde6a 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/logger/TradeOrderLogCreateReqBO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/logger/TradeOrderLogCreateReqBO.java @@ -28,7 +28,7 @@ public class TradeOrderLogCreateReqBO { /** * 订单编号 */ - @NotNull(message = "订单编号") + @NotNull(message = "订单编号不能为空") private Long orderId; /** * 操作前状态 diff --git a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleServiceTest.java b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleServiceTest.java new file mode 100644 index 0000000..3f28bcc --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleServiceTest.java @@ -0,0 +1,156 @@ +package cn.iocoder.yudao.module.trade.service.aftersale; + +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.pay.api.refund.PayRefundApi; +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.AfterSalePageReqVO; +import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSaleCreateReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleLogDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; +import cn.iocoder.yudao.module.trade.dal.mysql.aftersale.AfterSaleLogMapper; +import cn.iocoder.yudao.module.trade.dal.mysql.aftersale.AfterSaleMapper; +import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleStatusEnum; +import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleTypeEnum; +import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleWayEnum; +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum; +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; +import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; +import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService; +import cn.iocoder.yudao.module.trade.service.order.TradeOrderUpdateService; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; + +import javax.annotation.Resource; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static java.util.Arrays.asList; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; + +/** + * {@link AfterSaleService} 的单元测试 + * + * @author 芋道源码 + */ +@Import(AfterSaleServiceImpl.class) +public class AfterSaleServiceTest extends BaseDbUnitTest { + + @Resource + private AfterSaleServiceImpl tradeAfterSaleService; + + @Resource + private AfterSaleMapper tradeAfterSaleMapper; + @Resource + private AfterSaleLogMapper tradeAfterSaleLogMapper; + + @MockBean + private TradeOrderUpdateService tradeOrderUpdateService; + @Resource + private TradeOrderQueryService tradeOrderQueryService; + + @MockBean + private PayRefundApi payRefundApi; + + @MockBean + private TradeOrderProperties tradeOrderProperties; + + @Test + public void testCreateAfterSale() { + // 准备参数 + Long userId = 1024L; + AppAfterSaleCreateReqVO createReqVO = new AppAfterSaleCreateReqVO() + .setOrderItemId(1L).setRefundPrice(100).setWay(AfterSaleWayEnum.RETURN_AND_REFUND.getWay()) + .setApplyReason("退钱").setApplyDescription("快退") + .setApplyPicUrls(asList("https://www.baidu.com/1.png", "https://www.baidu.com/2.png")); + // mock 方法(交易订单项) + TradeOrderItemDO orderItem = randomPojo(TradeOrderItemDO.class, o -> { + o.setOrderId(111L).setUserId(userId).setPayPrice(200); + o.setAfterSaleStatus(TradeOrderItemAfterSaleStatusEnum.NONE.getStatus()); + }); + when(tradeOrderQueryService.getOrderItem(eq(1024L), eq(1L))) + .thenReturn(orderItem); + // mock 方法(交易订单) + TradeOrderDO order = randomPojo(TradeOrderDO.class, o -> o.setStatus(TradeOrderStatusEnum.DELIVERED.getStatus()) + .setNo("202211301234")); + when(tradeOrderQueryService.getOrder(eq(1024L), eq(111L))).thenReturn(order); + + // 调用 + Long afterSaleId = tradeAfterSaleService.createAfterSale(userId, createReqVO); + // 断言(TradeAfterSaleDO) + AfterSaleDO afterSale = tradeAfterSaleMapper.selectById(afterSaleId); + assertNotNull(afterSale.getNo()); + assertEquals(afterSale.getStatus(), AfterSaleStatusEnum.APPLY.getStatus()); + assertEquals(afterSale.getType(), AfterSaleTypeEnum.IN_SALE.getType()); + assertPojoEquals(afterSale, createReqVO); + assertEquals(afterSale.getUserId(), 1024L); + assertPojoEquals(afterSale, orderItem, "id", "creator", "createTime", "updater", "updateTime"); + assertEquals(afterSale.getOrderNo(), "202211301234"); + assertNull(afterSale.getPayRefundId()); + assertNull(afterSale.getRefundTime()); + assertNull(afterSale.getLogisticsId()); + assertNull(afterSale.getLogisticsNo()); + assertNull(afterSale.getDeliveryTime()); + assertNull(afterSale.getReceiveReason()); + // 断言(TradeAfterSaleLogDO) + AfterSaleLogDO afterSaleLog = tradeAfterSaleLogMapper.selectList().get(0); + assertEquals(afterSaleLog.getUserId(), userId); + assertEquals(afterSaleLog.getUserType(), UserTypeEnum.MEMBER.getValue()); + assertEquals(afterSaleLog.getAfterSaleId(), afterSaleId); + assertPojoEquals(afterSale, orderItem, "id", "creator", "createTime", "updater", "updateTime"); + assertEquals(afterSaleLog.getContent(), AfterSaleStatusEnum.APPLY.getContent()); + } + + @Test + public void testGetAfterSalePage() { + // mock 数据 + AfterSaleDO dbAfterSale = randomPojo(AfterSaleDO.class, o -> { // 等会查询到 + o.setNo("202211190847450020500077"); + o.setStatus(AfterSaleStatusEnum.APPLY.getStatus()); + o.setWay(AfterSaleWayEnum.RETURN_AND_REFUND.getWay()); + o.setType(AfterSaleTypeEnum.IN_SALE.getType()); + o.setOrderNo("202211190847450020500011"); + o.setSpuName("芋艿"); + o.setCreateTime(buildTime(2022, 1, 15)); + }); + tradeAfterSaleMapper.insert(dbAfterSale); + // 测试 no 不匹配 + tradeAfterSaleMapper.insert(cloneIgnoreId(dbAfterSale, o -> o.setNo("202211190847450020500066"))); + // 测试 status 不匹配 + tradeAfterSaleMapper.insert(cloneIgnoreId(dbAfterSale, o -> o.setStatus(AfterSaleStatusEnum.SELLER_REFUSE.getStatus()))); + // 测试 way 不匹配 + tradeAfterSaleMapper.insert(cloneIgnoreId(dbAfterSale, o -> o.setWay(AfterSaleWayEnum.REFUND.getWay()))); + // 测试 type 不匹配 + tradeAfterSaleMapper.insert(cloneIgnoreId(dbAfterSale, o -> o.setType(AfterSaleTypeEnum.AFTER_SALE.getType()))); + // 测试 orderNo 不匹配 + tradeAfterSaleMapper.insert(cloneIgnoreId(dbAfterSale, o -> o.setOrderNo("202211190847450020500022"))); + // 测试 spuName 不匹配 + tradeAfterSaleMapper.insert(cloneIgnoreId(dbAfterSale, o -> o.setSpuName("土豆"))); + // 测试 createTime 不匹配 + tradeAfterSaleMapper.insert(cloneIgnoreId(dbAfterSale, o -> o.setCreateTime(buildTime(2022, 1, 20)))); + // 准备参数 + AfterSalePageReqVO reqVO = new AfterSalePageReqVO(); + reqVO.setNo("20221119084745002050007"); + reqVO.setStatus(AfterSaleStatusEnum.APPLY.getStatus()); + reqVO.setWay(AfterSaleWayEnum.RETURN_AND_REFUND.getWay()); + reqVO.setType(AfterSaleTypeEnum.IN_SALE.getType()); + reqVO.setOrderNo("20221119084745002050001"); + reqVO.setSpuName("芋"); + reqVO.setCreateTime(new LocalDateTime[]{buildTime(2022, 1, 1), buildTime(2022, 1, 16)}); + + // 调用 + PageResult pageResult = tradeAfterSaleService.getAfterSalePage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbAfterSale, pageResult.getList().get(0)); + } +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceTest.java b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceTest.java deleted file mode 100644 index 7c3c605..0000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceTest.java +++ /dev/null @@ -1,156 +0,0 @@ -package cn.iocoder.yudao.module.trade.service.aftersale; - -import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.pay.api.refund.PayRefundApi; -import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSalePageReqVO; -import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleCreateReqVO; -import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO; -import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleLogDO; -import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; -import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; -import cn.iocoder.yudao.module.trade.dal.mysql.aftersale.TradeAfterSaleLogMapper; -import cn.iocoder.yudao.module.trade.dal.mysql.aftersale.TradeAfterSaleMapper; -import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleStatusEnum; -import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleTypeEnum; -import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleWayEnum; -import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum; -import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; -import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; -import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService; -import cn.iocoder.yudao.module.trade.service.order.TradeOrderUpdateService; -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.context.annotation.Import; - -import javax.annotation.Resource; -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; -import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; -import static java.util.Arrays.asList; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.when; - -/** - * {@link TradeAfterSaleService} 的单元测试 - * - * @author 芋道源码 - */ -@Import(TradeAfterSaleServiceImpl.class) -public class TradeAfterSaleServiceTest extends BaseDbUnitTest { - - @Resource - private TradeAfterSaleServiceImpl tradeAfterSaleService; - - @Resource - private TradeAfterSaleMapper tradeAfterSaleMapper; - @Resource - private TradeAfterSaleLogMapper tradeAfterSaleLogMapper; - - @MockBean - private TradeOrderUpdateService tradeOrderUpdateService; - @Resource - private TradeOrderQueryService tradeOrderQueryService; - - @MockBean - private PayRefundApi payRefundApi; - - @MockBean - private TradeOrderProperties tradeOrderProperties; - - @Test - public void testCreateAfterSale() { - // 准备参数 - Long userId = 1024L; - AppTradeAfterSaleCreateReqVO createReqVO = new AppTradeAfterSaleCreateReqVO() - .setOrderItemId(1L).setRefundPrice(100).setWay(TradeAfterSaleWayEnum.RETURN_AND_REFUND.getWay()) - .setApplyReason("退钱").setApplyDescription("快退") - .setApplyPicUrls(asList("https://www.baidu.com/1.png", "https://www.baidu.com/2.png")); - // mock 方法(交易订单项) - TradeOrderItemDO orderItem = randomPojo(TradeOrderItemDO.class, o -> { - o.setOrderId(111L).setUserId(userId).setPayPrice(200); - o.setAfterSaleStatus(TradeOrderItemAfterSaleStatusEnum.NONE.getStatus()); - }); - when(tradeOrderQueryService.getOrderItem(eq(1024L), eq(1L))) - .thenReturn(orderItem); - // mock 方法(交易订单) - TradeOrderDO order = randomPojo(TradeOrderDO.class, o -> o.setStatus(TradeOrderStatusEnum.DELIVERED.getStatus()) - .setNo("202211301234")); - when(tradeOrderQueryService.getOrder(eq(1024L), eq(111L))).thenReturn(order); - - // 调用 - Long afterSaleId = tradeAfterSaleService.createAfterSale(userId, createReqVO); - // 断言(TradeAfterSaleDO) - TradeAfterSaleDO afterSale = tradeAfterSaleMapper.selectById(afterSaleId); - assertNotNull(afterSale.getNo()); - assertEquals(afterSale.getStatus(), TradeAfterSaleStatusEnum.APPLY.getStatus()); - assertEquals(afterSale.getType(), TradeAfterSaleTypeEnum.IN_SALE.getType()); - assertPojoEquals(afterSale, createReqVO); - assertEquals(afterSale.getUserId(), 1024L); - assertPojoEquals(afterSale, orderItem, "id", "creator", "createTime", "updater", "updateTime"); - assertEquals(afterSale.getOrderNo(), "202211301234"); - assertNull(afterSale.getPayRefundId()); - assertNull(afterSale.getRefundTime()); - assertNull(afterSale.getLogisticsId()); - assertNull(afterSale.getLogisticsNo()); - assertNull(afterSale.getDeliveryTime()); - assertNull(afterSale.getReceiveReason()); - // 断言(TradeAfterSaleLogDO) - TradeAfterSaleLogDO afterSaleLog = tradeAfterSaleLogMapper.selectList().get(0); - assertEquals(afterSaleLog.getUserId(), userId); - assertEquals(afterSaleLog.getUserType(), UserTypeEnum.MEMBER.getValue()); - assertEquals(afterSaleLog.getAfterSaleId(), afterSaleId); - assertPojoEquals(afterSale, orderItem, "id", "creator", "createTime", "updater", "updateTime"); - assertEquals(afterSaleLog.getContent(), TradeAfterSaleStatusEnum.APPLY.getContent()); - } - - @Test - public void testGetAfterSalePage() { - // mock 数据 - TradeAfterSaleDO dbAfterSale = randomPojo(TradeAfterSaleDO.class, o -> { // 等会查询到 - o.setNo("202211190847450020500077"); - o.setStatus(TradeAfterSaleStatusEnum.APPLY.getStatus()); - o.setWay(TradeAfterSaleWayEnum.RETURN_AND_REFUND.getWay()); - o.setType(TradeAfterSaleTypeEnum.IN_SALE.getType()); - o.setOrderNo("202211190847450020500011"); - o.setSpuName("芋艿"); - o.setCreateTime(buildTime(2022, 1, 15)); - }); - tradeAfterSaleMapper.insert(dbAfterSale); - // 测试 no 不匹配 - tradeAfterSaleMapper.insert(cloneIgnoreId(dbAfterSale, o -> o.setNo("202211190847450020500066"))); - // 测试 status 不匹配 - tradeAfterSaleMapper.insert(cloneIgnoreId(dbAfterSale, o -> o.setStatus(TradeAfterSaleStatusEnum.SELLER_REFUSE.getStatus()))); - // 测试 way 不匹配 - tradeAfterSaleMapper.insert(cloneIgnoreId(dbAfterSale, o -> o.setWay(TradeAfterSaleWayEnum.REFUND.getWay()))); - // 测试 type 不匹配 - tradeAfterSaleMapper.insert(cloneIgnoreId(dbAfterSale, o -> o.setType(TradeAfterSaleTypeEnum.AFTER_SALE.getType()))); - // 测试 orderNo 不匹配 - tradeAfterSaleMapper.insert(cloneIgnoreId(dbAfterSale, o -> o.setOrderNo("202211190847450020500022"))); - // 测试 spuName 不匹配 - tradeAfterSaleMapper.insert(cloneIgnoreId(dbAfterSale, o -> o.setSpuName("土豆"))); - // 测试 createTime 不匹配 - tradeAfterSaleMapper.insert(cloneIgnoreId(dbAfterSale, o -> o.setCreateTime(buildTime(2022, 1, 20)))); - // 准备参数 - TradeAfterSalePageReqVO reqVO = new TradeAfterSalePageReqVO(); - reqVO.setNo("20221119084745002050007"); - reqVO.setStatus(TradeAfterSaleStatusEnum.APPLY.getStatus()); - reqVO.setWay(TradeAfterSaleWayEnum.RETURN_AND_REFUND.getWay()); - reqVO.setType(TradeAfterSaleTypeEnum.IN_SALE.getType()); - reqVO.setOrderNo("20221119084745002050001"); - reqVO.setSpuName("芋"); - reqVO.setCreateTime(new LocalDateTime[]{buildTime(2022, 1, 1), buildTime(2022, 1, 16)}); - - // 调用 - PageResult pageResult = tradeAfterSaleService.getAfterSalePage(reqVO); - // 断言 - assertEquals(1, pageResult.getTotal()); - assertEquals(1, pageResult.getList().size()); - assertPojoEquals(dbAfterSale, pageResult.getList().get(0)); - } -} diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/redis/RedisKeyConstants.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/redis/RedisKeyConstants.java index fc4c949..30081c6 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/redis/RedisKeyConstants.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/redis/RedisKeyConstants.java @@ -22,6 +22,6 @@ public interface RedisKeyConstants { * KEY 格式:pay_no:{prefix} * VALUE 数据格式:编号自增 */ - String PAY_NO = "pay_no"; + String PAY_NO = "pay_no:"; } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/redis/no/PayNoRedisDAO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/redis/no/PayNoRedisDAO.java index 7ce6caa..f6be6f9 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/redis/no/PayNoRedisDAO.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/redis/no/PayNoRedisDAO.java @@ -1,9 +1,13 @@ package cn.iocoder.yudao.module.pay.dal.redis.no; -import cn.hutool.core.date.DatePattern;import cn.hutool.core.date.DateUtil;import org.springframework.data.redis.core.StringRedisTemplate; +import cn.hutool.core.date.DatePattern;import cn.hutool.core.date.DateUtil; +import cn.iocoder.yudao.module.pay.dal.redis.RedisKeyConstants; +import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Repository; -import javax.annotation.Resource;import java.time.LocalDateTime; +import javax.annotation.Resource; +import java.time.Duration; +import java.time.LocalDateTime; /** * 支付序号的 Redis DAO @@ -23,8 +27,12 @@ public class PayNoRedisDAO { * @return 序号 */ public String generate(String prefix) { + // 递增序号 String noPrefix = prefix + DateUtil.format(LocalDateTime.now(), DatePattern.PURE_DATETIME_PATTERN); - Long no = stringRedisTemplate.opsForValue().increment(noPrefix); + String key = RedisKeyConstants.PAY_NO + noPrefix; + Long no = stringRedisTemplate.opsForValue().increment(key); + // 设置过期时间 + stringRedisTemplate.expire(key, Duration.ofMinutes(1L)); return noPrefix + no; } -- libgit2 0.21.4