diff --git a/sql/mysql/optional/mall_trade_log.sql b/sql/mysql/optional/mall_trade_log.sql new file mode 100644 index 0000000000..683c6a27af --- /dev/null +++ b/sql/mysql/optional/mall_trade_log.sql @@ -0,0 +1,3 @@ +ALTER TABLE `ruoyi-vue-pro`.`trade_after_sale_log` + ADD COLUMN `before_status` int NOT NULL COMMENT '售前状态' AFTER `id`, + ADD COLUMN `after_status` int NOT NULL COMMENT '售后状态' AFTER `before_status`; diff --git a/sql/mysql/pay_wallet.sql b/sql/mysql/pay_wallet.sql index c0df148574..1fda83769b 100644 --- a/sql/mysql/pay_wallet.sql +++ b/sql/mysql/pay_wallet.sql @@ -5,11 +5,11 @@ DROP TABLE IF EXISTS `pay_wallet`; CREATE TABLE `pay_wallet` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', - `user_id` bigint NOT NULL COMMENT '用户 id', + `user_id` bigint NOT NULL COMMENT '用户编号', `user_type` tinyint NOT NULL DEFAULT 0 COMMENT '用户类型', - `balance` int NOT NULL DEFAULT 0 COMMENT '余额, 单位分', - `total_expense` bigint NOT NULL DEFAULT 0 COMMENT '累计支出, 单位分', - `total_recharge` bigint NOT NULL DEFAULT 0 COMMENT '累计充值, 单位分', + `balance` int NOT NULL DEFAULT 0 COMMENT '余额,单位分', + `total_expense` bigint NOT NULL DEFAULT 0 COMMENT '累计支出,单位分', + `total_recharge` bigint NOT NULL DEFAULT 0 COMMENT '累计充值,单位分', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', @@ -41,4 +41,4 @@ CREATE TABLE `pay_wallet_transaction` `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE=InnoDB COMMENT='支付钱包余额明细表'; \ No newline at end of file +) ENGINE=InnoDB COMMENT='支付钱包余额明细表'; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClientFactory.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClientFactory.java index f6d0ca6b5a..53f1a8c069 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClientFactory.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClientFactory.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.framework.pay.core.client; +import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; + /** * 支付客户端的工厂接口 * @@ -25,4 +27,12 @@ public interface PayClientFactory { void createOrUpdatePayClient(Long channelId, String channelCode, Config config); + /** + * 注册支付客户端 Class,用于模块中实现的 PayClient + * + * @param channel 支付渠道的编码的枚举 + * @param payClientClass 支付客户端 class + */ + void registerPayClientClass(PayChannelEnum channel, Class payClientClass); + } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/NonePayClientConfig.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/NonePayClientConfig.java new file mode 100644 index 0000000000..48319036c7 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/NonePayClientConfig.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.framework.pay.core.client.impl; + +import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; +import lombok.Data; + +import javax.validation.Validator; + +/** + * 无需任何配置 PayClientConfig 实现类 + * + * @author jason + */ +@Data +public class NonePayClientConfig implements PayClientConfig { + + /** + * 配置名称 + *

+ * 如果不加任何属性,JsonUtils.parseObject2 解析会报错,所以暂时加个名称 + */ + private String name; + + public NonePayClientConfig(){ + this.name = "none-config"; + } + + @Override + public void validate(Validator validator) { + // 无任何配置不需要校验 + } +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImpl.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImpl.java index 121aeb0871..0b39587abb 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImpl.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImpl.java @@ -1,19 +1,22 @@ package cn.iocoder.yudao.framework.pay.core.client.impl; import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.ReflectUtil; import cn.iocoder.yudao.framework.pay.core.client.PayClient; import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.*; import cn.iocoder.yudao.framework.pay.core.client.impl.mock.MockPayClient; -import cn.iocoder.yudao.framework.pay.core.client.impl.mock.MockPayClientConfig; import cn.iocoder.yudao.framework.pay.core.client.impl.weixin.*; import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; import lombok.extern.slf4j.Slf4j; +import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import static cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum.*; + /** * 支付客户端的工厂实现类 * @@ -24,10 +27,38 @@ public class PayClientFactoryImpl implements PayClientFactory { /** * 支付客户端 Map + * * key:渠道编号 */ private final ConcurrentMap> clients = new ConcurrentHashMap<>(); + /** + * 支付客户端 Class Map + */ + private final Map> clientClass = new ConcurrentHashMap<>(); + + public PayClientFactoryImpl() { + // 微信支付客户端 + clientClass.put(WX_PUB, WxPubPayClient.class); + clientClass.put(WX_LITE, WxLitePayClient.class); + clientClass.put(WX_APP, WxAppPayClient.class); + clientClass.put(WX_BAR, WxBarPayClient.class); + clientClass.put(WX_NATIVE, WxNativePayClient.class); + // 支付包支付客户端 + clientClass.put(ALIPAY_WAP, AlipayWapPayClient.class); + clientClass.put(ALIPAY_QR, AlipayQrPayClient.class); + clientClass.put(ALIPAY_APP, AlipayAppPayClient.class); + clientClass.put(ALIPAY_PC, AlipayPcPayClient.class); + clientClass.put(ALIPAY_BAR, AlipayBarPayClient.class); + // Mock 支付客户端 + clientClass.put(MOCK, MockPayClient.class); + } + + @Override + public void registerPayClientClass(PayChannelEnum channel, Class payClientClass) { + clientClass.put(channel, payClientClass); + } + @Override public PayClient getPayClient(Long channelId) { AbstractPayClient client = clients.get(channelId); @@ -52,30 +83,13 @@ public class PayClientFactoryImpl implements PayClientFactory { } @SuppressWarnings("unchecked") - private AbstractPayClient createPayClient( - Long channelId, String channelCode, Config config) { + private AbstractPayClient createPayClient(Long channelId, String channelCode, + Config config) { PayChannelEnum channelEnum = PayChannelEnum.getByCode(channelCode); - Assert.notNull(channelEnum, String.format("支付渠道(%s) 为空", channelEnum)); - // 创建客户端 - switch (channelEnum) { - // 微信支付 - case WX_PUB: return (AbstractPayClient) new WxPubPayClient(channelId, (WxPayClientConfig) config); - case WX_LITE: return (AbstractPayClient) new WxLitePayClient(channelId, (WxPayClientConfig) config); - case WX_APP: return (AbstractPayClient) new WxAppPayClient(channelId, (WxPayClientConfig) config); - case WX_BAR: return (AbstractPayClient) new WxBarPayClient(channelId, (WxPayClientConfig) config); - case WX_NATIVE: return (AbstractPayClient) new WxNativePayClient(channelId, (WxPayClientConfig) config); - // 支付宝支付 - case ALIPAY_WAP: return (AbstractPayClient) new AlipayWapPayClient(channelId, (AlipayPayClientConfig) config); - case ALIPAY_QR: return (AbstractPayClient) new AlipayQrPayClient(channelId, (AlipayPayClientConfig) config); - case ALIPAY_APP: return (AbstractPayClient) new AlipayAppPayClient(channelId, (AlipayPayClientConfig) config); - case ALIPAY_PC: return (AbstractPayClient) new AlipayPcPayClient(channelId, (AlipayPayClientConfig) config); - case ALIPAY_BAR: return (AbstractPayClient) new AlipayBarPayClient(channelId, (AlipayPayClientConfig) config); - // 其它支付 - case MOCK: return (AbstractPayClient) new MockPayClient(channelId, (MockPayClientConfig) config); - } - // 创建失败,错误日志 + 抛出异常 - log.error("[createPayClient][配置({}) 找不到合适的客户端实现]", config); - throw new IllegalArgumentException(String.format("配置(%s) 找不到合适的客户端实现", config)); + Assert.notNull(channelEnum, String.format("支付渠道(%s) 为空", channelCode)); + Class payClientClass = clientClass.get(channelEnum); + Assert.notNull(payClientClass, String.format("支付渠道(%s) Class 为空", channelCode)); + return (AbstractPayClient) ReflectUtil.newInstance(payClientClass, channelId, config); } } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/delegate/DelegatePayClient.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/delegate/DelegatePayClient.java new file mode 100644 index 0000000000..65958d5a3b --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/delegate/DelegatePayClient.java @@ -0,0 +1,63 @@ +package cn.iocoder.yudao.framework.pay.core.client.impl.delegate; + +import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; +import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; +import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; +import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO; +import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO; +import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient; + +import java.util.Map; + +// TODO @jason:其它模块,主要是无法 pay client 初始化存在问题,所以我感觉,是不是可以搞个 PayClientInitializer 接口。这样,PayClientFactory 去 get 这个支付模式对应的 PayClientInitializer,通过它来创建。具体注入的地方,可以在 PayChannel init 方法那; +/** + * 代理支付 Client 的抽象类。 + * + * 用于支付 Client 由其它模块实现,例如钱包支付 + * + * @author jason + */ +public abstract class DelegatePayClient extends AbstractPayClient { + + private final DelegatePayClient delegate; + + public DelegatePayClient(Long channelId, String channelCode, PayClientConfig config) { + super(channelId, channelCode, config); + delegate = this; + } + + @Override + protected void doInit() { + delegate.doInit(); + } + + @Override + protected PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) { + return delegate.doUnifiedOrder(reqDTO); + } + + @Override + protected PayOrderRespDTO doGetOrder(String outTradeNo) { + return delegate.doGetOrder(outTradeNo); + } + + @Override + protected PayRefundRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) { + return delegate.doUnifiedRefund(reqDTO); + } + + @Override + protected PayRefundRespDTO doGetRefund(String outTradeNo, String outRefundNo) { + return delegate.doGetRefund(outTradeNo, outRefundNo); + } + + @Override + protected PayRefundRespDTO doParseRefundNotify(Map params, String body) { + return delegate.doParseRefundNotify(params, body); + } + + @Override + protected PayOrderRespDTO doParseOrderNotify(Map params, String body) { + return delegate.doParseOrderNotify(params, body); + } +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/channel/PayChannelEnum.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/channel/PayChannelEnum.java index 073b17f3c8..cbe0a242aa 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/channel/PayChannelEnum.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/channel/PayChannelEnum.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.framework.pay.core.enums.channel; import cn.hutool.core.util.ArrayUtil; +import cn.iocoder.yudao.framework.pay.core.client.impl.NonePayClientConfig; import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig; import cn.iocoder.yudao.framework.pay.core.client.impl.mock.MockPayClientConfig; @@ -29,7 +30,9 @@ public enum PayChannelEnum { ALIPAY_QR("alipay_qr", "支付宝扫码支付", AlipayPayClientConfig.class), ALIPAY_BAR("alipay_bar", "支付宝条码支付", AlipayPayClientConfig.class), - MOCK("mock", "模拟支付", MockPayClientConfig.class); + MOCK("mock", "模拟支付", MockPayClientConfig.class), + + WALLET("wallet", "钱包支付", NonePayClientConfig.class); /** * 编码 diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AbstractAlipayClientTest.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AbstractAlipayClientTest.java index 57d629021e..2d220079eb 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AbstractAlipayClientTest.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AbstractAlipayClientTest.java @@ -168,7 +168,7 @@ public abstract class AbstractAlipayClientTest extends BaseMockitoUnitTest { @Test @DisplayName("支付宝 Client 统一退款:抛出业务异常") public void testUnifiedRefund_throwServiceException() throws AlipayApiException { - // mock + // mock 方法 when(defaultAlipayClient.execute(argThat((ArgumentMatcher) request -> true))) .thenThrow(ServiceExceptionUtil.exception(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR)); // 准备请求参数 @@ -182,7 +182,7 @@ public abstract class AbstractAlipayClientTest extends BaseMockitoUnitTest { @Test @DisplayName("支付宝 Client 统一退款:抛出系统异常") public void testUnifiedRefund_throwPayException() throws AlipayApiException { - // mock + // mock 方法 when(defaultAlipayClient.execute(argThat((ArgumentMatcher) request -> true))) .thenThrow(new RuntimeException("系统异常")); // 准备请求参数 diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPcPayClientTest.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPcPayClientTest.java index b94ae71487..d78caf28c5 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPcPayClientTest.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPcPayClientTest.java @@ -70,7 +70,7 @@ public class AlipayPcPayClientTest extends AbstractAlipayClientTest { @Test @DisplayName("支付宝 PC 网站支付:Form Display Mode 下单成功") public void testUnifiedOrder_formSuccess() throws AlipayApiException { - // mock + // mock 方法 String notifyUrl = randomURL(); AlipayTradePagePayResponse response = randomPojo(AlipayTradePagePayResponse.class, o -> o.setSubCode("")); when(defaultAlipayClient.pageExecute(argThat((ArgumentMatcher) request -> true), @@ -99,7 +99,7 @@ public class AlipayPcPayClientTest extends AbstractAlipayClientTest { @Test @DisplayName("支付宝 PC 网站支付:渠道返回失败") public void testUnifiedOrder_channelFailed() throws AlipayApiException { - // mock + // mock 方法 String subCode = randomString(); String subMsg = randomString(); AlipayTradePagePayResponse response = randomPojo(AlipayTradePagePayResponse.class, o -> { diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayQrPayClientTest.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayQrPayClientTest.java index 47497ab231..c7e1eb33f7 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayQrPayClientTest.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayQrPayClientTest.java @@ -39,9 +39,9 @@ public class AlipayQrPayClientTest extends AbstractAlipayClientTest { } @Test - @DisplayName("支付宝扫描支付下单成功") - public void test_unified_order_success() throws AlipayApiException { - // 准备返回对象 + @DisplayName("支付宝扫描支付:下单成功") + public void testUnifiedOrder_success() throws AlipayApiException { + // mock 方法 String notifyUrl = randomURL(); String qrCode = randomString(); Integer price = randomInteger(); @@ -49,7 +49,6 @@ public class AlipayQrPayClientTest extends AbstractAlipayClientTest { o.setQrCode(qrCode); o.setSubCode(""); }); - // mock when(defaultAlipayClient.execute(argThat((ArgumentMatcher) request -> { assertEquals(notifyUrl, request.getNotifyUrl()); return true; @@ -58,18 +57,25 @@ public class AlipayQrPayClientTest extends AbstractAlipayClientTest { String outTradeNo = randomString(); PayOrderUnifiedReqDTO reqDTO = buildOrderUnifiedReqDTO(notifyUrl, outTradeNo, price); + // 调用 PayOrderRespDTO resp = client.unifiedOrder(reqDTO); // 断言 assertEquals(WAITING.getStatus(), resp.getStatus()); - assertEquals(PayOrderDisplayModeEnum.QR_CODE.getMode(), resp.getDisplayMode()); assertEquals(outTradeNo, resp.getOutTradeNo()); - assertEquals(qrCode, resp.getDisplayContent()); + assertNull(resp.getChannelOrderNo()); + assertNull(resp.getChannelUserId()); + assertNull(resp.getSuccessTime()); + assertEquals(PayOrderDisplayModeEnum.QR_CODE.getMode(), resp.getDisplayMode()); + assertEquals(response.getQrCode(), resp.getDisplayContent()); assertSame(response, resp.getRawData()); + assertNull(resp.getChannelErrorCode()); + assertNull(resp.getChannelErrorMsg()); } @Test - @DisplayName("支付宝扫描支付,渠道返回失败") - public void test_unified_order_channel_failed() throws AlipayApiException { + @DisplayName("支付宝扫描支付:渠道返回失败") + public void testUnifiedOrder_channelFailed() throws AlipayApiException { + // mock 方法 String notifyUrl = randomURL(); String subCode = randomString(); String subMsg = randomString(); @@ -87,47 +93,55 @@ public class AlipayQrPayClientTest extends AbstractAlipayClientTest { String outTradeNo = randomString(); PayOrderUnifiedReqDTO reqDTO = buildOrderUnifiedReqDTO(notifyUrl, outTradeNo, price); + // 调用 PayOrderRespDTO resp = client.unifiedOrder(reqDTO); // 断言 assertEquals(CLOSED.getStatus(), resp.getStatus()); + assertEquals(outTradeNo, resp.getOutTradeNo()); + assertNull(resp.getChannelOrderNo()); + assertNull(resp.getChannelUserId()); + assertNull(resp.getSuccessTime()); + assertNull(resp.getDisplayMode()); + assertNull(resp.getDisplayContent()); + assertSame(response, resp.getRawData()); assertEquals(subCode, resp.getChannelErrorCode()); assertEquals(subMsg, resp.getChannelErrorMsg()); - assertSame(response, resp.getRawData()); } @Test @DisplayName("支付宝扫描支付, 抛出系统异常") - public void test_unified_order_throw_pay_exception() throws AlipayApiException { - // 准备请求参数 + public void testUnifiedOrder_throwPayException() throws AlipayApiException { + // mock 方法 String outTradeNo = randomString(); String notifyUrl = randomURL(); Integer price = randomInteger(); - // mock when(defaultAlipayClient.execute(argThat((ArgumentMatcher) request -> { assertEquals(notifyUrl, request.getNotifyUrl()); return true; }))).thenThrow(new RuntimeException("系统异常")); // 准备请求参数 PayOrderUnifiedReqDTO reqDTO = buildOrderUnifiedReqDTO(notifyUrl, outTradeNo,price); - // 断言 + + // 调用,并断言 assertThrows(PayException.class, () -> client.unifiedOrder(reqDTO)); } @Test - @DisplayName("支付宝 Client 统一下单,抛出业务异常") - public void test_unified_order_throw_service_exception() throws AlipayApiException { - // 准备请求参数 + @DisplayName("支付宝 Client 统一下单:抛出业务异常") + public void testUnifiedOrder_throwServiceException() throws AlipayApiException { + // mock 方法 String outTradeNo = randomString(); String notifyUrl = randomURL(); Integer price = randomInteger(); - // mock when(defaultAlipayClient.execute(argThat((ArgumentMatcher) request -> { assertEquals(notifyUrl, request.getNotifyUrl()); return true; }))).thenThrow(ServiceExceptionUtil.exception(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR)); // 准备请求参数 PayOrderUnifiedReqDTO reqDTO = buildOrderUnifiedReqDTO(notifyUrl, outTradeNo, price); - // 断言 + + // 调用,并断言 assertThrows(ServiceException.class, () -> client.unifiedOrder(reqDTO)); } + } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayWapPayClientTest.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayWapPayClientTest.java index bad1960acd..af0c7170bf 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayWapPayClientTest.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayWapPayClientTest.java @@ -42,9 +42,9 @@ public class AlipayWapPayClientTest extends AbstractAlipayClientTest { } @Test - @DisplayName("支付宝 H5 支付下单成功") - public void test_unified_order_success() throws AlipayApiException { - // 准备响应对象 + @DisplayName("支付宝 H5 支付:下单成功") + public void testUnifiedOrder_success() throws AlipayApiException { + // mock 方法 String h5Body = randomString(); Integer price = randomInteger(); AlipayTradeWapPayResponse response = randomPojo(AlipayTradeWapPayResponse.class, o -> { @@ -52,7 +52,6 @@ public class AlipayWapPayClientTest extends AbstractAlipayClientTest { o.setBody(h5Body); }); String notifyUrl = randomURL(); - // mock when(defaultAlipayClient.pageExecute(argThat((ArgumentMatcher) request -> { assertInstanceOf(AlipayTradeWapPayModel.class, request.getBizModel()); AlipayTradeWapPayModel bizModel = (AlipayTradeWapPayModel) request.getBizModel(); @@ -60,37 +59,53 @@ public class AlipayWapPayClientTest extends AbstractAlipayClientTest { assertEquals(notifyUrl, request.getNotifyUrl()); return true; }), eq(Method.GET.name()))).thenReturn(response); - + // 准备请求参数 String outTradeNo = randomString(); PayOrderUnifiedReqDTO reqDTO = buildOrderUnifiedReqDTO(notifyUrl, outTradeNo, price); + + // 调用 PayOrderRespDTO resp = client.unifiedOrder(reqDTO); + // 断言 assertEquals(WAITING.getStatus(), resp.getStatus()); - assertEquals(PayOrderDisplayModeEnum.URL.getMode(), resp.getDisplayMode()); assertEquals(outTradeNo, resp.getOutTradeNo()); - assertEquals(h5Body, resp.getDisplayContent()); + assertNull(resp.getChannelOrderNo()); + assertNull(resp.getChannelUserId()); + assertNull(resp.getSuccessTime()); + assertEquals(PayOrderDisplayModeEnum.URL.getMode(), resp.getDisplayMode()); + assertEquals(response.getBody(), resp.getDisplayContent()); assertSame(response, resp.getRawData()); + assertNull(resp.getChannelErrorCode()); + assertNull(resp.getChannelErrorMsg()); } @Test - @DisplayName("支付宝 H5 支付,渠道返回失败") + @DisplayName("支付宝 H5 支付:渠道返回失败") public void test_unified_order_channel_failed() throws AlipayApiException { - // 准备响应对象 + // mock 方法 String subCode = randomString(); String subMsg = randomString(); AlipayTradeWapPayResponse response = randomPojo(AlipayTradeWapPayResponse.class, o -> { o.setSubCode(subCode); o.setSubMsg(subMsg); }); - // mock when(defaultAlipayClient.pageExecute(argThat((ArgumentMatcher) request -> true), eq(Method.GET.name()))).thenReturn(response); - PayOrderUnifiedReqDTO reqDTO = buildOrderUnifiedReqDTO(randomURL(), randomString(), randomInteger()); + String outTradeNo = randomString(); + PayOrderUnifiedReqDTO reqDTO = buildOrderUnifiedReqDTO(randomURL(), outTradeNo, randomInteger()); + // 调用 PayOrderRespDTO resp = client.unifiedOrder(reqDTO); // 断言 assertEquals(CLOSED.getStatus(), resp.getStatus()); + assertEquals(outTradeNo, resp.getOutTradeNo()); + assertNull(resp.getChannelOrderNo()); + assertNull(resp.getChannelUserId()); + assertNull(resp.getSuccessTime()); + assertNull(resp.getDisplayMode()); + assertNull(resp.getDisplayContent()); + assertSame(response, resp.getRawData()); assertEquals(subCode, resp.getChannelErrorCode()); assertEquals(subMsg, resp.getChannelErrorMsg()); - assertSame(response, resp.getRawData()); } + } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/JobLogController.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/JobLogController.java index 24f1f44b77..1441f9cf6d 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/JobLogController.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/JobLogController.java @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.framework.operatelog.core.util.OperateLogUtils; import cn.iocoder.yudao.module.infra.controller.admin.job.vo.log.JobLogExcelVO; import cn.iocoder.yudao.module.infra.controller.admin.job.vo.log.JobLogExportReqVO; import cn.iocoder.yudao.module.infra.controller.admin.job.vo.log.JobLogPageReqVO; diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/AppFavoriteController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/AppFavoriteController.java index 3316b38fa8..7e54c8ed9c 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/AppFavoriteController.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/AppFavoriteController.java @@ -42,6 +42,14 @@ public class AppFavoriteController { return success(productFavoriteService.createFavorite(getLoginUserId(), reqVO.getSpuId())); } + @PostMapping(value = "/create-list") + @Operation(summary = "添加多个商品收藏") + @PreAuthenticated + public CommonResult createFavoriteList(@RequestBody @Valid AppFavoriteBatchReqVO reqVO) { + // todo @jason:待实现;如果有已经收藏的,不用报错,忽略即可; + return success(true); + } + @DeleteMapping(value = "/delete") @Operation(summary = "取消单个商品收藏") @PreAuthenticated diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java index 3ada0be787..43421315fe 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java @@ -110,8 +110,9 @@ public class ProductSpuServiceImpl implements ProductSpuService { spu.setMarketPrice(getMinValue(skus, ProductSkuCreateOrUpdateReqVO::getMarketPrice)); // sku 单价最低的商品的成本价格 spu.setCostPrice(getMinValue(skus, ProductSkuCreateOrUpdateReqVO::getCostPrice)); - // sku 单价最低的商品的条形码 - spu.setBarCode(getMinValue(skus, ProductSkuCreateOrUpdateReqVO::getBarCode)); + // sku 单价最低的商品的条形码 TODO 芋艿:条形码字段,是不是可以删除 + spu.setBarCode(""); +// spu.setBarCode(getMinValue(skus, ProductSkuCreateOrUpdateReqVO::getBarCode)); // skus 库存总数 spu.setStock(getSumValue(skus, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum)); // 若是 spu 已有状态则不处理 diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillConfigController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillConfigController.java index a8a793c77f..44ec72e8aa 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillConfigController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillConfigController.java @@ -81,12 +81,13 @@ public class SeckillConfigController { @GetMapping("/list-all-simple") @Operation(summary = "获得所有开启状态的秒杀时段精简列表", description = "主要用于前端的下拉选项") public CommonResult> getListAllSimple() { - List list = seckillConfigService.getSeckillConfigListByStatus(CommonStatusEnum.ENABLE.getStatus()); + List list = seckillConfigService.getSeckillConfigListByStatus( + CommonStatusEnum.ENABLE.getStatus()); return success(SeckillConfigConvert.INSTANCE.convertList1(list)); } @GetMapping("/page") - @Operation(summary = "获得秒杀活动分页") + @Operation(summary = "获得秒杀时间段分页") @PreAuthorize("@ss.hasPermission('promotion:seckill-config:query')") public CommonResult> getSeckillActivityPage(@Valid SeckillConfigPageReqVO pageVO) { PageResult pageResult = seckillConfigService.getSeckillConfigPage(pageVO); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/bargain/AppBargainActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/bargain/AppBargainActivityController.java index 537350aeda..2232ead7be 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/bargain/AppBargainActivityController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/bargain/AppBargainActivityController.java @@ -35,7 +35,7 @@ public class AppBargainActivityController { activity1.setId(1L); activity1.setName("618 大砍价"); activity1.setSpuId(2048L); - activity1.setPicUrl("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg"); + activity1.setPicUrl("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg"); activity1.setMarketPrice(50); activity1.setBargainPrice(100); activity1.setStartTime(LocalDateTimeUtils.addTime(Duration.ofDays(-2))); @@ -47,7 +47,7 @@ public class AppBargainActivityController { activity2.setId(2L); activity2.setName("双十一砍价"); activity2.setSpuId(4096L); - activity2.setPicUrl("https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTKXMYJOomfp7cebz3cIeb8sHk3GGSIJtWEgREe3j7J1WoAbTvIOicpcNdFkWAziatBSMod8b5RyS4CQ/132"); + activity2.setPicUrl("https://static.iocoder.cn/mall/132.jpeg"); activity2.setMarketPrice(100); activity2.setBargainPrice(200); activity2.setStartTime(LocalDateTimeUtils.addTime(Duration.ofDays(-2))); @@ -69,7 +69,7 @@ public class AppBargainActivityController { activity1.setId(1L); activity1.setName("618 大砍价"); activity1.setSpuId(2048L); - activity1.setPicUrl("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg"); + activity1.setPicUrl("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg"); activity1.setMarketPrice(50); activity1.setBargainPrice(100); activityList.add(activity1); @@ -78,7 +78,7 @@ public class AppBargainActivityController { activity2.setId(2L); activity2.setName("双十一砍价"); activity2.setSpuId(4096L); - activity2.setPicUrl("https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTKXMYJOomfp7cebz3cIeb8sHk3GGSIJtWEgREe3j7J1WoAbTvIOicpcNdFkWAziatBSMod8b5RyS4CQ/132"); + activity2.setPicUrl("https://static.iocoder.cn/mall/132.jpeg"); activity2.setMarketPrice(100); activity2.setBargainPrice(200); activityList.add(activity2); @@ -94,7 +94,7 @@ public class AppBargainActivityController { activity.setId(2L); activity.setName("618 大砍价"); activity.setSpuId(2048L); - activity.setPicUrl("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg"); + activity.setPicUrl("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg"); activity.setMarketPrice(50); activity.setBargainPrice(100); activity.setStock(10); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/bargain/AppBargainRecordController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/bargain/AppBargainRecordController.java index 0df8db49ae..bb2bf584f0 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/bargain/AppBargainRecordController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/bargain/AppBargainRecordController.java @@ -81,7 +81,7 @@ public class AppBargainRecordController { record1.setPrice(200); record1.setPayPrice(180); record1.setStatus(1); - record1.setPicUrl("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg"); + record1.setPicUrl("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg"); record1.setExpireTime(LocalDateTimeUtils.addTime(Duration.ofDays(2))); page.getList().add(record1); @@ -96,7 +96,7 @@ public class AppBargainRecordController { record2.setPrice(200); record2.setPayPrice(280); record2.setStatus(2); - record2.setPicUrl("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg"); + record2.setPicUrl("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg"); record2.setExpireTime(LocalDateTimeUtils.addTime(Duration.ofDays(2))); page.getList().add(record2); @@ -111,7 +111,7 @@ public class AppBargainRecordController { record3.setPrice(200); record3.setPayPrice(380); record3.setStatus(2); - record3.setPicUrl("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg"); + record3.setPicUrl("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg"); record3.setExpireTime(LocalDateTimeUtils.addTime(Duration.ofDays(2))); record3.setOrderId(100L); page.getList().add(record3); @@ -127,7 +127,7 @@ public class AppBargainRecordController { record4.setPrice(200); record4.setPayPrice(380); record4.setStatus(3); - record4.setPicUrl("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg"); + record4.setPicUrl("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg"); record4.setExpireTime(LocalDateTimeUtils.addTime(Duration.ofDays(2))); record4.setOrderId(100L); page.getList().add(record4); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java index 216ec5285d..75693f90b8 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java @@ -38,7 +38,7 @@ public class AppCombinationActivityController { activity1.setName("618 大拼团"); activity1.setUserSize(3); activity1.setSpuId(2048L); - activity1.setPicUrl("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg"); + activity1.setPicUrl("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg"); activity1.setMarketPrice(50); activity1.setCombinationPrice(100); activityList.add(activity1); @@ -48,7 +48,7 @@ public class AppCombinationActivityController { activity2.setName("双十一拼团"); activity2.setUserSize(5); activity2.setSpuId(4096L); - activity2.setPicUrl("https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTKXMYJOomfp7cebz3cIeb8sHk3GGSIJtWEgREe3j7J1WoAbTvIOicpcNdFkWAziatBSMod8b5RyS4CQ/132"); + activity2.setPicUrl("https://static.iocoder.cn/mall/132.jpeg"); activity2.setMarketPrice(100); activity2.setCombinationPrice(200); activityList.add(activity2); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationRecordController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationRecordController.java index 74cd39c5a7..7496e2e0ea 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationRecordController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationRecordController.java @@ -41,7 +41,7 @@ public class AppCombinationRecordController { summary.getAvatars().add("https://thirdwx.qlogo.cn/mmopen/vi_32/ouwtwJycbic2JrCoZjETict0klxd1uRuicRneKk00ewMcCClxVcVHQT91Sh9MJGtwibf1fOicD1WpwSP4icJM6eQq1AA/132"); summary.getAvatars().add("https://thirdwx.qlogo.cn/mmopen/vi_32/RpUrhwens58qc99OcGs993xL4M5QPOe05ekqF9Eia440kRicAlicicIdQWicHBmy2bzLgHzHguWEzHHxnIgeictL7bLA/132"); summary.getAvatars().add("https://thirdwx.qlogo.cn/mmopen/vi_32/S4tfqmxc8GZGsKc1K4mnhpvtG16gtMrLnTQfDibhr7jJich9LRI5RQKZDoqEjZM3azMib5nic7F4ZXKMEgYyLO08KA/132"); - summary.getAvatars().add("https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTKXMYJOomfp7cebz3cIeb8sHk3GGSIJtWEgREe3j7J1WoAbTvIOicpcNdFkWAziatBSMod8b5RyS4CQ/132"); + summary.getAvatars().add("https://static.iocoder.cn/mall/132.jpeg"); return success(summary); } @@ -61,7 +61,7 @@ public class AppCombinationRecordController { record.setExpireTime(new Date()); record.setUserSize(10); record.setUserCount(i); - record.setPicUrl("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg"); + record.setPicUrl("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg"); record.setActivityId(1L); record.setSpuName("活动:" + i); list.add(record); @@ -84,7 +84,7 @@ public class AppCombinationRecordController { headRecord.setUserCount(3); headRecord.setStatus(1); headRecord.setActivityId(10L); - headRecord.setPicUrl("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg"); + headRecord.setPicUrl("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg"); headRecord.setCombinationPrice(100); detail.setHeadRecord(headRecord); // 团员 diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillActivityController.java index 7c4fd9ee24..098dfca67a 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillActivityController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillActivityController.java @@ -39,7 +39,7 @@ public class AppSeckillActivityController { activity1.setId(1L); activity1.setName("618 大秒杀"); activity1.setSpuId(2048L); - activity1.setPicUrl("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg"); + activity1.setPicUrl("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg"); activity1.setMarketPrice(50); activity1.setSeckillPrice(100); activityList.add(activity1); @@ -48,7 +48,7 @@ public class AppSeckillActivityController { activity2.setId(2L); activity2.setName("双十一大秒杀"); activity2.setSpuId(4096L); - activity2.setPicUrl("https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTKXMYJOomfp7cebz3cIeb8sHk3GGSIJtWEgREe3j7J1WoAbTvIOicpcNdFkWAziatBSMod8b5RyS4CQ/132"); + activity2.setPicUrl("https://static.iocoder.cn/mall/132.jpeg"); activity2.setMarketPrice(100); activity2.setSeckillPrice(200); activityList.add(activity2); @@ -65,7 +65,7 @@ public class AppSeckillActivityController { activity1.setId(1L); activity1.setName("618 大秒杀"); activity1.setSpuId(2048L); - activity1.setPicUrl("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg"); + activity1.setPicUrl("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg"); activity1.setMarketPrice(50); activity1.setSeckillPrice(100); activity1.setUnitName("个"); @@ -77,7 +77,7 @@ public class AppSeckillActivityController { activity2.setId(2L); activity2.setName("双十一大秒杀"); activity2.setSpuId(4096L); - activity2.setPicUrl("https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTKXMYJOomfp7cebz3cIeb8sHk3GGSIJtWEgREe3j7J1WoAbTvIOicpcNdFkWAziatBSMod8b5RyS4CQ/132"); + activity2.setPicUrl("https://static.iocoder.cn/mall/132.jpeg"); activity2.setMarketPrice(100); activity2.setSeckillPrice(200); activity2.setUnitName("套"); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillConfigController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillConfigController.java index 23a5aa4bcd..d59a365b96 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillConfigController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillConfigController.java @@ -25,8 +25,8 @@ public class AppSeckillConfigController { public CommonResult> getSeckillConfigList() { return success(Arrays.asList( new AppSeckillConfigRespVO().setId(1L).setStartTime("00:00").setEndTime("09:59") - .setSliderPicUrls(Arrays.asList("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg", - "https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTKXMYJOomfp7cebz3cIeb8sHk3GGSIJtWEgREe3j7J1WoAbTvIOicpcNdFkWAziatBSMod8b5RyS4CQ/132")), + .setSliderPicUrls(Arrays.asList("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg", + "https://static.iocoder.cn/mall/132.jpeg")), new AppSeckillConfigRespVO().setId(2L).setStartTime("10:00").setEndTime("12:59"), new AppSeckillConfigRespVO().setId(2L).setStartTime("13:00").setEndTime("22:59"), new AppSeckillConfigRespVO().setId(2L).setStartTime("23:00").setEndTime("23:59") diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillconfig/SeckillConfigMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillconfig/SeckillConfigMapper.java index 38bbe18da5..6d07cfcdfd 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillconfig/SeckillConfigMapper.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillconfig/SeckillConfigMapper.java @@ -16,7 +16,7 @@ public interface SeckillConfigMapper extends BaseMapperX { return selectPage(reqVO, new LambdaQueryWrapperX() .likeIfPresent(SeckillConfigDO::getName, reqVO.getName()) .eqIfPresent(SeckillConfigDO::getStatus, reqVO.getStatus()) - .orderByDesc(SeckillConfigDO::getId)); + .orderByAsc(SeckillConfigDO::getStartTime)); } default List selectListByStatus(Integer status) { diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java index dc757b05e9..3aa0e5dd3a 100644 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java @@ -32,6 +32,7 @@ public interface ErrorCodeConstants { ErrorCode ORDER_DELIVERY_FAIL_REFUND_STATUS_NOT_NONE = new ErrorCode(1011000021, "交易订单发货失败,订单已退款或部分退款"); ErrorCode ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS = new ErrorCode(1011000022, "交易订单发货失败,拼团未成功"); ErrorCode ORDER_DELIVERY_FAIL_BARGAIN_RECORD_STATUS_NOT_SUCCESS = new ErrorCode(1011000023, "交易订单发货失败,砍价未成功"); + ErrorCode ORDER_DELIVERY_FAIL_DELIVERY_TYPE_NOT_EXPRESS = new ErrorCode(1011000024, "交易订单发货失败,发货类型不是快递"); // ========== After Sale 模块 1011000100 ========== ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1011000100, "售后单不存在"); 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 index c12d2b5c05..56fdc06da9 100644 --- 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 @@ -7,13 +7,15 @@ 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.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.TradeAfterSaleRespPageItemVO; +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.*; 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.dto.TradeAfterSaleLogRespDTO; +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; @@ -25,6 +27,7 @@ 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; @@ -41,7 +44,10 @@ public class TradeAfterSaleController { @Resource private TradeAfterSaleService afterSaleService; - + @Resource + private TradeOrderQueryService tradeOrderQueryService; + @Resource + private AfterSaleLogService afterSaleLogService; @Resource private MemberUserApi memberUserApi; @@ -61,6 +67,24 @@ public class TradeAfterSaleController { 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); + // 查询订单 + TradeOrderDO order = tradeOrderQueryService.getOrder(afterSale.getOrderId()); + // 查询订单项 + List orderItems = tradeOrderQueryService.getOrderItemListByOrderId(id); + // 拼接数据 + MemberUserRespDTO user = memberUserApi.getUser(afterSale.getUserId()); + // 获取售后日志 + List logs = afterSaleLogService.getLog(afterSale.getId()); + return success(TradeAfterSaleConvert.INSTANCE.convert(afterSale, order, orderItems, user, logs)); + } + @PutMapping("/agree") @Operation(summary = "同意售后") @Parameter(name = "id", description = "售后编号", required = true, example = "1") @@ -88,7 +112,7 @@ public class TradeAfterSaleController { } @PutMapping("/refuse") - @Operation(summary = "确认收货") + @Operation(summary = "拒绝收货") @Parameter(name = "id", description = "售后编号", required = true, example = "1") @PreAuthorize("@ss.hasPermission('trade:after-sale:receive')") public CommonResult refuseAfterSale(TradeAfterSaleRefuseReqVO refuseReqVO) { 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 new file mode 100644 index 0000000000..aff9f5087d --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleDetailRespVO.java @@ -0,0 +1,51 @@ +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 afterSaleLog; + + @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/delivery/DeliveryPickUpStoreController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/DeliveryPickUpStoreController.java index a8ddec24cc..4235d6ef5e 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/DeliveryPickUpStoreController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/DeliveryPickUpStoreController.java @@ -64,9 +64,10 @@ public class DeliveryPickUpStoreController { } @GetMapping("/list-all-simple") - @Operation(summary = "获取快递公司精简信息列表") + @Operation(summary = "获得自提门店精简信息列表") public CommonResult> getSimpleDeliveryPickUpStoreList() { - List list = deliveryPickUpStoreService.getDeliveryPickUpStoreListByStatus(CommonStatusEnum.ENABLE.getStatus()); + List list = deliveryPickUpStoreService.getDeliveryPickUpStoreListByStatus( + CommonStatusEnum.ENABLE.getStatus()); return success(DeliveryPickUpStoreConvert.INSTANCE.convertList1(list)); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/pickup/DeliveryPickUpStoreSimpleRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/pickup/DeliveryPickUpStoreSimpleRespVO.java index 34c66df4cc..c12fc9fc3e 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/pickup/DeliveryPickUpStoreSimpleRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/pickup/DeliveryPickUpStoreSimpleRespVO.java @@ -23,7 +23,8 @@ public class DeliveryPickUpStoreSimpleRespVO { @Schema(description = "区域编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18733") private Integer areaId; - // TODO @puhui999:要把 areaName 也返回哈 + @Schema(description = "区域名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "xx市") + private String areaName; @Schema(description = "门店详细地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "复旦大学路 188 号") private String detailAddress; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java index 8a28e5ddb2..57b21bee05 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java @@ -85,8 +85,7 @@ public class TradeOrderController { tradeOrderQueryService.getExpressTrackList(id, getLoginUserId()))); } - // TODO @puhui999:put 请求哈 - @PostMapping("/delivery") + @PutMapping("/delivery") @Operation(summary = "订单发货") @PreAuthorize("@ss.hasPermission('trade:order:update')") public CommonResult deliveryOrder(@RequestBody TradeOrderDeliveryReqVO deliveryReqVO) { @@ -94,8 +93,7 @@ public class TradeOrderController { return success(true); } - // TODO @puhui999:put 请求哈,update-remark; - @PostMapping("/remark") + @PutMapping("/update-remark") @Operation(summary = "订单备注") @PreAuthorize("@ss.hasPermission('trade:order:update')") public CommonResult updateOrderRemark(@RequestBody TradeOrderRemarkReqVO reqVO) { @@ -103,8 +101,7 @@ public class TradeOrderController { return success(true); } - // TODO @puhui999:put 请求哈,update-price; - @PostMapping("/adjust-price") + @PutMapping("/update-price") @Operation(summary = "订单调价") @PreAuthorize("@ss.hasPermission('trade:order:update')") public CommonResult updateOrderPrice(@RequestBody TradeOrderUpdatePriceReqVO reqVO) { @@ -112,8 +109,7 @@ public class TradeOrderController { return success(true); } - // TODO @puhui999:put 请求哈,update-address; - @PostMapping("/adjust-address") + @PutMapping("/update-address") @Operation(summary = "修改订单收货地址") @PreAuthorize("@ss.hasPermission('trade:order:update')") public CommonResult updateOrderAddress(@RequestBody TradeOrderUpdateAddressReqVO reqVO) { 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 index 5be54e2075..ef3e75c7dd 100644 --- 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 @@ -8,8 +8,10 @@ import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSa 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.enums.aftersale.TradeAfterSaleWayEnum; 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; @@ -71,6 +73,8 @@ public class AppTradeAfterSaleController { @Operation(summary = "申请售后") @AfterSaleLog(id = "#info.data", content = "'申请售后:售后编号['+#info.data+'],订单编号['+#createReqVO.orderItemId+'], '", operateType = AfterSaleOperateTypeEnum.APPLY) public CommonResult createAfterSale(@RequestBody AppTradeAfterSaleCreateReqVO createReqVO) { + AfterSaleLogUtils.setBeforeStatus(0); + AfterSaleLogUtils.setAfterStatus(TradeAfterSaleStatusEnum.APPLY.getStatus()); return success(afterSaleService.createAfterSale(getLoginUserId(), createReqVO)); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/TradeCartController.http b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/AppCartController.http similarity index 100% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/TradeCartController.http rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/AppCartController.http diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/TradeCartController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/AppCartController.java similarity index 65% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/TradeCartController.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/AppCartController.java index 9216773add..2c9d77b523 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/TradeCartController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/AppCartController.java @@ -2,11 +2,8 @@ package cn.iocoder.yudao.module.trade.controller.app.cart; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; -import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartAddReqVO; -import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartListRespVO; -import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartResetReqVO; -import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartUpdateReqVO; -import cn.iocoder.yudao.module.trade.service.cart.TradeCartService; +import cn.iocoder.yudao.module.trade.controller.app.cart.vo.*; +import cn.iocoder.yudao.module.trade.service.cart.CartService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -18,7 +15,6 @@ import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; 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.security.core.util.SecurityFrameworkUtils.getLoginUserId; @@ -29,30 +25,38 @@ import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUti @RequiredArgsConstructor @Validated @Slf4j -public class TradeCartController { +public class AppCartController { @Resource - private TradeCartService cartService; + private CartService cartService; @PostMapping("/add") @Operation(summary = "添加购物车商品") @PreAuthenticated - public CommonResult addCart(@Valid @RequestBody AppTradeCartAddReqVO addCountReqVO) { + public CommonResult addCart(@Valid @RequestBody AppCartAddReqVO addCountReqVO) { return success(cartService.addCart(getLoginUserId(), addCountReqVO)); } - @PutMapping("/update") - @Operation(summary = "更新购物车商品") + @PutMapping("/update-count") + @Operation(summary = "更新购物车商品数量") @PreAuthenticated - public CommonResult updateCart(@Valid @RequestBody AppTradeCartUpdateReqVO updateReqVO) { - cartService.updateCart(getLoginUserId(), updateReqVO); + public CommonResult updateCartCount(@Valid @RequestBody AppCartUpdateCountReqVO updateReqVO) { + cartService.updateCartCount(getLoginUserId(), updateReqVO); + return success(true); + } + + @PutMapping("/update-selected") + @Operation(summary = "更新购物车商品选中") + @PreAuthenticated + public CommonResult updateCartSelected(@Valid @RequestBody AppCartUpdateSelectedReqVO updateReqVO) { + cartService.updateCartSelected(getLoginUserId(), updateReqVO); return success(true); } @PutMapping("/reset") @Operation(summary = "重置购物车商品") @PreAuthenticated - public CommonResult resetCart(@Valid @RequestBody AppTradeCartResetReqVO updateReqVO) { + public CommonResult resetCart(@Valid @RequestBody AppCartResetReqVO updateReqVO) { cartService.resetCart(getLoginUserId(), updateReqVO); return success(true); } @@ -73,17 +77,10 @@ public class TradeCartController { return success(cartService.getCartCount(getLoginUserId())); } - @GetMapping("get-count-map") - @Operation(summary = "查询用户在购物车中的商品 SPU 数量 Map") - @PreAuthenticated - public CommonResult> getCartCountMap() { - return success(cartService.getCartCountMap(getLoginUserId())); - } - @GetMapping("/list") @Operation(summary = "查询用户的购物车列表") @PreAuthenticated - public CommonResult getCartList() { + public CommonResult getCartList() { return success(cartService.getCartList(getLoginUserId())); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartAddReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppCartAddReqVO.java similarity index 72% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartAddReqVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppCartAddReqVO.java index 8ea754849f..b538f6174e 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartAddReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppCartAddReqVO.java @@ -7,7 +7,7 @@ import javax.validation.constraints.NotNull; @Schema(description = "用户 App - 购物车添加购物项 Request VO") @Data -public class AppTradeCartAddReqVO { +public class AppCartAddReqVO { @Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED,example = "1024") @NotNull(message = "商品 SKU 编号不能为空") @@ -17,8 +17,4 @@ public class AppTradeCartAddReqVO { @NotNull(message = "数量不能为空") private Integer count; - @Schema(description = "是否添加到购物车", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") - @NotNull(message = "是否添加购物车不能为空") - private Boolean addStatus; - } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartDetailRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppCartDetailRespVO.java similarity index 99% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartDetailRespVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppCartDetailRespVO.java index cd68edbbc0..1a28d96a6a 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartDetailRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppCartDetailRespVO.java @@ -8,7 +8,7 @@ import java.util.List; @Schema(description = "用户 App - 用户的购物车明细 Response VO") @Data -public class AppTradeCartDetailRespVO { +public class AppCartDetailRespVO { /** * 商品分组数组 diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartListRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppCartListRespVO.java similarity index 86% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartListRespVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppCartListRespVO.java index 3f6dfe104e..cef09f78fb 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartListRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppCartListRespVO.java @@ -9,7 +9,7 @@ import java.util.List; @Schema(description = "用户 App - 用户的购物列表 Response VO") @Data -public class AppTradeCartListRespVO { +public class AppCartListRespVO { /** * 有效的购物项数组 @@ -31,6 +31,9 @@ public class AppTradeCartListRespVO { @Schema(description = "商品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Integer count; + @Schema(description = "是否选中", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + private Boolean selected; + /** * 商品 SPU */ diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartResetReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppCartResetReqVO.java similarity index 95% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartResetReqVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppCartResetReqVO.java index 81c7b0bf32..1ef82c69bf 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartResetReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppCartResetReqVO.java @@ -8,7 +8,7 @@ import javax.validation.constraints.NotNull; @Schema(description = "用户 App - 购物车重置 Request VO") @Data -public class AppTradeCartResetReqVO { +public class AppCartResetReqVO { @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") @NotNull(message = "编号不能为空") diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartUpdateReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppCartUpdateCountReqVO.java similarity index 85% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartUpdateReqVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppCartUpdateCountReqVO.java index d0d2fff025..4341d501db 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartUpdateReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppCartUpdateCountReqVO.java @@ -6,9 +6,9 @@ import lombok.Data; import javax.validation.constraints.Min; import javax.validation.constraints.NotNull; -@Schema(description = "用户 App - 购物车更新 Request VO") +@Schema(description = "用户 App - 购物车更新数量 Request VO") @Data -public class AppTradeCartUpdateReqVO { +public class AppCartUpdateCountReqVO { @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") @NotNull(message = "编号不能为空") diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartItemUpdateSelectedReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppCartUpdateSelectedReqVO.java similarity index 64% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartItemUpdateSelectedReqVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppCartUpdateSelectedReqVO.java index adf213b930..3348d2d192 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartItemUpdateSelectedReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppCartUpdateSelectedReqVO.java @@ -8,11 +8,11 @@ import java.util.Collection; @Schema(description = "用户 App - 购物车更新是否选中 Request VO") @Data -public class AppTradeCartItemUpdateSelectedReqVO { +public class AppCartUpdateSelectedReqVO { - @Schema(description = "商品 SKU 编号列表", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024,2048") - @NotNull(message = "商品 SKU 编号列表不能为空") - private Collection skuIds; + @Schema(description = "编号列表", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024,2048") + @NotNull(message = "编号列表不能为空") + private Collection ids; @Schema(description = "是否选中", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") @NotNull(message = "是否选中不能为空") diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java index 8a34f1180b..e3205fcaf4 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java @@ -5,7 +5,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO; import cn.iocoder.yudao.module.product.api.property.ProductPropertyValueApi; -import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO; import cn.iocoder.yudao.module.trade.controller.app.order.vo.*; import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO; import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemRespVO; @@ -91,15 +90,11 @@ public class AppTradeOrderController { // 查询订单项 List orderItems = tradeOrderQueryService.getOrderItemListByOrderId(order.getId()); - // 查询商品属性 - List propertyValueDetails = productPropertyValueApi - .getPropertyValueDetailList(TradeOrderConvert.INSTANCE.convertPropertyValueIds(orderItems)); // 查询物流公司 DeliveryExpressDO express = order.getLogisticsId() != null && order.getLogisticsId() > 0 ? deliveryExpressService.getDeliveryExpress(order.getLogisticsId()) : null; // 最终组合 - return success(TradeOrderConvert.INSTANCE.convert02(order, orderItems, - propertyValueDetails, tradeOrderProperties, express)); + return success(TradeOrderConvert.INSTANCE.convert02(order, orderItems, tradeOrderProperties, express)); } @GetMapping("/get-express-track-list") 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 index 7fa8b328cd..4d83fe1470 100644 --- 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 @@ -4,19 +4,26 @@ 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.aftersalelog.core.dto.TradeAfterSaleLogRespDTO; 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 @@ -61,4 +68,20 @@ public interface TradeAfterSaleConvert { 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, convertList1(logs)); + // 处理用户信息 + respVO.setUser(convert(user)); + // 处理订单信息 + respVO.setOrder(convert(order)); + return respVO; + } + List convertList1(List list); + @Mapping(target = "id", source = "afterSale.id") + TradeAfterSaleDetailRespVO convert(TradeAfterSaleDO afterSale, List orderItems, List logs); + TradeOrderBaseVO convert(TradeOrderDO order); + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/cart/TradeCartConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/cart/TradeCartConvert.java index 519b82fc99..83cd459542 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/cart/TradeCartConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/cart/TradeCartConvert.java @@ -5,8 +5,8 @@ import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; import cn.iocoder.yudao.module.trade.controller.app.base.sku.AppProductSkuBaseRespVO; import cn.iocoder.yudao.module.trade.controller.app.base.spu.AppProductSpuBaseRespVO; -import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartListRespVO; -import cn.iocoder.yudao.module.trade.dal.dataobject.cart.TradeCartDO; +import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppCartListRespVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.cart.CartDO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @@ -21,16 +21,16 @@ public interface TradeCartConvert { TradeCartConvert INSTANCE = Mappers.getMapper(TradeCartConvert.class); - default AppTradeCartListRespVO convertList(List carts, - List spus, List skus) { + default AppCartListRespVO convertList(List carts, + List spus, List skus) { Map spuMap = convertMap(spus, ProductSpuRespDTO::getId); Map skuMap = convertMap(skus, ProductSkuRespDTO::getId); // 遍历,开始转换 - List validList = new ArrayList<>(carts.size()); - List invalidList = new ArrayList<>(); + List validList = new ArrayList<>(carts.size()); + List invalidList = new ArrayList<>(); carts.forEach(cart -> { - AppTradeCartListRespVO.Cart cartVO = new AppTradeCartListRespVO.Cart(); - cartVO.setId(cart.getId()).setCount(cart.getCount()); + AppCartListRespVO.Cart cartVO = new AppCartListRespVO.Cart(); + cartVO.setId(cart.getId()).setCount(cart.getCount()).setSelected(cart.getSelected()); ProductSpuRespDTO spu = spuMap.get(cart.getSpuId()); ProductSkuRespDTO sku = skuMap.get(cart.getSkuId()); cartVO.setSpu(convert(spu)).setSku(convert(sku)); @@ -38,13 +38,14 @@ public interface TradeCartConvert { if (spu == null || !ProductSpuStatusEnum.isEnable(spu.getStatus()) || spu.getStock() <= 0) { + cartVO.setSelected(false); // 强制设置成不可选中 invalidList.add(cartVO); } else { // 虽然 SKU 可能也会不存在,但是可以通过购物车重新选择 validList.add(cartVO); } }); - return new AppTradeCartListRespVO().setValidList(validList).setInvalidList(invalidList); + return new AppCartListRespVO().setValidList(validList).setInvalidList(invalidList); } AppProductSpuBaseRespVO convert(ProductSpuRespDTO spu); AppProductSkuBaseRespVO convert(ProductSkuRespDTO sku); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/delivery/DeliveryPickUpStoreConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/delivery/DeliveryPickUpStoreConvert.java index 9e114242b1..6522f3281b 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/delivery/DeliveryPickUpStoreConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/delivery/DeliveryPickUpStoreConvert.java @@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup.Deliver import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup.DeliveryPickUpStoreUpdateReqVO; import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryPickUpStoreDO; import org.mapstruct.Mapper; +import org.mapstruct.Mapping; import org.mapstruct.Named; import org.mapstruct.factory.Mappers; @@ -28,10 +29,13 @@ public interface DeliveryPickUpStoreConvert { PageResult convertPage(PageResult page); - @Named("convertAreaIdToName") - default String convertAreaIdToName(Integer areaId) { + List convertList1(List list); + @Mapping(source = "areaId", target = "areaName", qualifiedByName = "convertAreaIdToAreaName") + DeliveryPickUpStoreSimpleRespVO convert02(DeliveryPickUpStoreDO bean); + + @Named("convertAreaIdToAreaName") + default String convertAreaIdToAreaName(Integer areaId) { return AreaUtils.format(areaId); } - List convertList1(List list); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java index 76e79c5239..0285a63546 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java @@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.string.StrUtils; import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; @@ -22,7 +23,7 @@ import cn.iocoder.yudao.module.trade.controller.app.base.property.AppProductProp import cn.iocoder.yudao.module.trade.controller.app.order.vo.*; import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO; import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemRespVO; -import cn.iocoder.yudao.module.trade.dal.dataobject.cart.TradeCartDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.cart.CartDO; 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; @@ -82,14 +83,16 @@ public interface TradeOrderConvert { TradeOrderItemDO convert(TradePriceCalculateRespBO.OrderItem item); + default ProductSkuUpdateStockReqDTO convert(List list) { + return new ProductSkuUpdateStockReqDTO(TradeOrderConvert.INSTANCE.convertList(list)); + } + List convertList(List list); @Mappings({ @Mapping(source = "skuId", target = "id"), @Mapping(source = "count", target = "incrCount"), }) ProductSkuUpdateStockReqDTO.Item convert(TradeOrderItemDO bean); - List convertList(List list); - default PayOrderCreateReqDTO convert(TradeOrderDO order, List orderItems, TradePriceCalculateRespBO calculateRespBO, TradeOrderProperties orderProperties) { PayOrderCreateReqDTO createReqDTO = new PayOrderCreateReqDTO() @@ -97,9 +100,7 @@ public interface TradeOrderConvert { // 商户相关字段 createReqDTO.setMerchantOrderId(String.valueOf(order.getId())); String subject = calculateRespBO.getItems().get(0).getSpuName(); - if (calculateRespBO.getItems().size() > 1) { - subject += " 等多件"; - } + subject = StrUtils.maxLength(subject, PayOrderCreateReqDTO.SUBJECT_MAX_LENGTH); // 避免超过 32 位 createReqDTO.setSubject(subject); createReqDTO.setBody(subject); // TODO 芋艿:临时写死 // 订单相关字段 @@ -107,16 +108,6 @@ public interface TradeOrderConvert { return createReqDTO; } - default Set convertPropertyValueIds(List list) { - if (CollUtil.isEmpty(list)) { - return new HashSet<>(); - } - return list.stream().filter(item -> item.getProperties() != null) - .flatMap(p -> p.getProperties().stream()) // 遍历多个 Property 属性 - .map(TradeOrderItemDO.Property::getValueId) // 将每个 Property 转换成对应的 propertyId,最后形成集合 - .collect(Collectors.toSet()); - } - // TODO 芋艿:可简化 default PageResult convertPage(PageResult pageResult, List orderItems, @@ -170,31 +161,13 @@ public interface TradeOrderConvert { // TODO 芋艿:可简化 default AppTradeOrderDetailRespVO convert02(TradeOrderDO order, List orderItems, - List propertyValueDetails, TradeOrderProperties tradeOrderProperties, + TradeOrderProperties tradeOrderProperties, DeliveryExpressDO express) { AppTradeOrderDetailRespVO orderVO = convert3(order, orderItems); orderVO.setPayExpireTime(addTime(tradeOrderProperties.getExpireTime())); if (StrUtil.isNotEmpty(order.getPayChannelCode())) { orderVO.setPayChannelName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.CHANNEL_CODE, order.getPayChannelCode())); } - // 处理商品属性 - Map propertyValueDetailMap = convertMap(propertyValueDetails, ProductPropertyValueDetailRespDTO::getValueId); - for (int i = 0; i < orderItems.size(); i++) { - List properties = orderItems.get(i).getProperties(); - if (CollUtil.isEmpty(properties)) { - continue; - } - AppTradeOrderItemRespVO item = orderVO.getItems().get(i); - item.setProperties(new ArrayList<>(properties.size())); - // 遍历每个 properties,设置到 TradeOrderPageItemRespVO.Item 中 - properties.forEach(property -> { - ProductPropertyValueDetailRespDTO propertyValueDetail = propertyValueDetailMap.get(property.getValueId()); - if (propertyValueDetail == null) { - return; - } - item.getProperties().add(convert02(propertyValueDetail)); - }); - } // 处理收货地址 orderVO.setReceiverAreaName(AreaUtils.format(order.getReceiverAreaId())); if (express != null) { @@ -221,12 +194,12 @@ public interface TradeOrderConvert { ProductCommentCreateReqDTO convert04(AppTradeOrderItemCommentCreateReqVO createReqVO, TradeOrderItemDO tradeOrderItemDO); default TradePriceCalculateReqBO convert(Long userId, AppTradeOrderSettlementReqVO settlementReqVO, - List cartList) { + List cartList) { TradePriceCalculateReqBO reqBO = new TradePriceCalculateReqBO(); reqBO.setUserId(userId).setCouponId(settlementReqVO.getCouponId()).setAddressId(settlementReqVO.getAddressId()) .setItems(new ArrayList<>(settlementReqVO.getItems().size())); // 商品项的构建 - Map cartMap = convertMap(cartList, TradeCartDO::getId); + Map cartMap = convertMap(cartList, CartDO::getId); for (AppTradeOrderSettlementReqVO.Item item : settlementReqVO.getItems()) { // 情况一:skuId + count if (item.getSkuId() != null) { @@ -235,7 +208,7 @@ public interface TradeOrderConvert { continue; } // 情况二:cartId - TradeCartDO cart = cartMap.get(item.getCartId()); + CartDO cart = cartMap.get(item.getCartId()); if (cart == null) { continue; } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/cart/TradeCartDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/cart/CartDO.java similarity index 50% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/cart/TradeCartDO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/cart/CartDO.java index d9d9697ae7..d8bf140883 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/cart/TradeCartDO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/cart/CartDO.java @@ -17,7 +17,7 @@ import lombok.experimental.Accessors; @Data @EqualsAndHashCode(callSuper = true) @Accessors(chain = true) -public class TradeCartDO extends BaseDO { +public class CartDO extends BaseDO { // ========= 基础字段 BEGIN ========= @@ -33,27 +33,7 @@ public class TradeCartDO extends BaseDO { */ private Long userId; - /** - * 是否添加到购物车 - * - * false - 未添加:用户点击【立即购买】 - * true - 已添加:用户点击【添加购物车】 - * - * 为什么要设计这个字段? - * 配合 orderStatus 字段,可以知道有多少商品,用户点击了【立即购买】,最终多少【确认下单】 - */ - private Boolean addStatus; - /** - * 是否提交订单 - * - * false - 未下单:立即购买,或者添加到购物车,此时设置为 false - * true - 已下单:确认下单,此时设置为 true - */ - private Boolean orderStatus; - - // ========= 基础字段 END ========= - - // ========= 商品信息 BEGIN ========= + // ========= 商品信息 ========= /** * 商品 SPU 编号 @@ -71,16 +51,9 @@ public class TradeCartDO extends BaseDO { * 商品购买数量 */ private Integer count; - - // ========= 商品信息 END ========= - - // ========= 优惠信息 BEGIN ========= - - // TODO 芋艿:combination_id 拼团 ID - // TODO 芋艿:seckill_id 秒杀产品 ID - // TODO 芋艿:bargain_id 砍价 ID - // TODO 芋艿:pinkId 团长拼团 ID - - // ========= 优惠信息 END ========= + /** + * 是否选中 + */ + private Boolean selected; } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDO.java index b9177fb66b..9d8133ef25 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDO.java @@ -27,6 +27,11 @@ import java.time.LocalDateTime; @AllArgsConstructor public class TradeOrderDO extends BaseDO { + /** + * 发货物流公司编号 - 空(无需发货) + */ + public static final Long LOGISTICS_ID_NULL = 0L; + // ========== 订单基本信息 ========== /** * 订单编号,主键自增 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 74bd933552..f078f149ea 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 @@ -3,7 +3,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.cart.TradeCartDO; +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; import com.baomidou.mybatisplus.annotation.TableName; @@ -46,7 +46,7 @@ public class TradeOrderItemDO extends BaseDO { /** * 购物车项编号 * - * 关联 {@link TradeCartDO#getId()} + * 关联 {@link CartDO#getId()} */ private Long cartId; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/cart/CartMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/cart/CartMapper.java new file mode 100644 index 0000000000..b672651567 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/cart/CartMapper.java @@ -0,0 +1,62 @@ +package cn.iocoder.yudao.module.trade.dal.mysql.cart; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.map.MapUtil; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.trade.dal.dataobject.cart.CartDO; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +@Mapper +public interface CartMapper extends BaseMapperX { + + default CartDO selectByUserIdAndSkuId(Long userId, Long skuId) { + return selectOne(CartDO::getUserId, userId, + CartDO::getSkuId, skuId); + } + + default Integer selectSumByUserId(Long userId) { + // SQL sum 查询 + List> result = selectMaps(new QueryWrapper() + .select("SUM(count) AS sumCount") + .eq("user_id", userId) + .eq("selected", true)); // 只计算选中的 + // 获得数量 + return CollUtil.getFirst(result) != null ? MapUtil.getInt(result.get(0), "sumCount") : 0; + } + + default CartDO selectById(Long id, Long userId) { + return selectOne(CartDO::getId, id, + CartDO::getUserId, userId); + } + + default List selectListByIds(Collection ids, Long userId) { + return selectList(new LambdaQueryWrapper() + .in(CartDO::getId, ids) + .eq(CartDO::getUserId, userId)); + } + + default List selectListByUserId(Long userId) { + return selectList(new LambdaQueryWrapper() + .eq(CartDO::getUserId, userId)); + } + + default List selectListByUserId(Long userId, Set ids) { + return selectList(new LambdaQueryWrapper() + .eq(CartDO::getUserId, userId) + .in(CartDO::getId, ids)); + } + + default void updateByIds(Collection ids, Long userId, CartDO updateObj) { + update(updateObj, new LambdaQueryWrapper() + .in(CartDO::getId, ids) + .eq(CartDO::getUserId, userId)); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/cart/TradeCartMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/cart/TradeCartMapper.java deleted file mode 100644 index 64e2f99ea0..0000000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/cart/TradeCartMapper.java +++ /dev/null @@ -1,80 +0,0 @@ -package cn.iocoder.yudao.module.trade.dal.mysql.cart; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.map.MapUtil; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.module.trade.dal.dataobject.cart.TradeCartDO; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import org.apache.ibatis.annotations.Mapper; - -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; - -@Mapper -public interface TradeCartMapper extends BaseMapperX { - - default TradeCartDO selectByUserIdAndSkuId(Long userId, Long skuId, - Boolean addStatus, Boolean orderStatus) { - return selectOne(new LambdaQueryWrapper().eq(TradeCartDO::getUserId, userId) - .eq(TradeCartDO::getSkuId, skuId) - .eq(TradeCartDO::getAddStatus, addStatus) - .eq(TradeCartDO::getOrderStatus, orderStatus)); - } - - default Integer selectSumByUserId(Long userId) { - // SQL sum 查询 - List> result = selectMaps(new QueryWrapper() - .select("SUM(count) AS sumCount") - .eq("user_id", userId) - .eq("add_status", true) // 只计算添加到购物车中的 - .eq("order_status", false)); // 必须未下单 - // 获得数量 - return CollUtil.getFirst(result) != null ? MapUtil.getInt(result.get(0), "sumCount") : 0; - } - - default Map selectSumMapByUserId(Long userId) { - // SQL sum 查询 - List> result = selectMaps(new QueryWrapper() - .select("spu_id, SUM(count) AS sumCount") - .eq("user_id", userId) - .eq("add_status", true) // 只计算添加到购物车中的 - .eq("order_status", false) // 必须未下单 - .groupBy("spu_id")); - // 获得数量 - return CollectionUtils.convertMap(result, item -> MapUtil.getLong(item, "spu_id"), - item -> MapUtil.getInt(item, "sumCount")); - } - - default TradeCartDO selectById(Long id, Long userId) { - return selectOne(TradeCartDO::getId, id, - TradeCartDO::getUserId, userId); - } - - default List selectListByIds(Collection ids, Long userId) { - return selectList(new LambdaQueryWrapper() - .in(TradeCartDO::getId, ids) - .eq(TradeCartDO::getUserId, userId)); - } - - default List selectListByUserId(Long userId, Boolean addStatus, Boolean orderStatus) { - return selectList(new LambdaQueryWrapper() - .eq(TradeCartDO::getUserId, userId) - .eq(TradeCartDO::getAddStatus, addStatus) - .eq(TradeCartDO::getOrderStatus, orderStatus)); - } - - default void updateByIds(Collection ids, TradeCartDO updateObject) { - update(updateObject, new LambdaQueryWrapper().in(TradeCartDO::getId, ids)); - } - - default List selectListByUserId(Long userId, Set ids) { - return selectList(new LambdaQueryWrapper() - .eq(TradeCartDO::getUserId, userId) - .in(TradeCartDO::getId, ids)); - } - -} 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 index 93186edf11..f554d9a15f 100644 --- 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 @@ -3,6 +3,7 @@ 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.operatelog.core.service.OperateLog; 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; @@ -33,9 +34,26 @@ public class AfterSaleLogAspect { @Resource private AfterSaleLogService afterSaleLogService; - - // TODO chenchen: 这个分 3 行把; - private final static String OPERATE_TYPE = "operateType", ID = "id", CONTENT = "content"; + /** + * 售前状态 + */ + 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"; /** * 切面存入日志 @@ -52,11 +70,15 @@ public class AfterSaleLogAspect { .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(); } } @@ -85,4 +107,17 @@ public class AfterSaleLogAspect { 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 index 7beac68cfe..19c1086ee1 100644 --- 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 @@ -42,5 +42,13 @@ public class TradeAfterSaleLogCreateReqDTO { * 操作明细 */ 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/dto/TradeAfterSaleLogRespDTO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/dto/TradeAfterSaleLogRespDTO.java new file mode 100644 index 0000000000..69c6bd9394 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/dto/TradeAfterSaleLogRespDTO.java @@ -0,0 +1,59 @@ +package cn.iocoder.yudao.module.trade.framework.aftersalelog.core.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +// TODO @puhui999:这个是不是应该搞成 vo 啊? +/** + * 贸易售后日志详情 DTO + * + * @author HUIHUI + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class TradeAfterSaleLogRespDTO { + + @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/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 index ccea309f46..b068afd56a 100644 --- 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 @@ -2,6 +2,9 @@ package cn.iocoder.yudao.module.trade.framework.aftersalelog.core.service; import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.dto.TradeAfterSaleLogCreateReqDTO; +import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.dto.TradeAfterSaleLogRespDTO; + +import java.util.List; /** * 交易售后日志 Service 接口 @@ -20,4 +23,12 @@ public interface AfterSaleLogService { */ 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 new file mode 100644 index 0000000000..3f8327dc01 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/util/AfterSaleLogUtils.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.trade.framework.aftersalelog.core.util; + + +import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.aop.AfterSaleLogAspect; + +/** + * 操作日志工具类 + * 目前主要的作用,是提供给业务代码,记录操作明细和拓展字段 + * + * @author 芋道源码 + */ +public class AfterSaleLogUtils { + + public static void setBeforeStatus(Integer status) { + AfterSaleLogAspect.setBeforeStatus(status); + } + + public static void setAfterStatus(Integer status) { + AfterSaleLogAspect.setAfterStatus(status); + } + +} 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 index 09f2c9f3bb..a7b2db6878 100644 --- 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 @@ -42,6 +42,14 @@ public interface TradeAfterSaleService { */ TradeAfterSaleDO getAfterSale(Long userId, Long id); + /** + * 【管理员】获得售后单 + * + * @param id 售后编号 + * @return 售后订单 + */ + TradeAfterSaleDO getAfterSale(Long id); + /** * 【会员】创建售后订单 * 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 index e5d1063426..83a180fc56 100644 --- 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 @@ -26,6 +26,7 @@ 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.dto.TradeAfterSaleLogCreateReqDTO; +import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.dto.TradeAfterSaleLogRespDTO; import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.service.AfterSaleLogService; import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService; @@ -40,6 +41,7 @@ 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; @@ -86,6 +88,16 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa return tradeAfterSaleMapper.selectByIdAndUserId(id, userId); } + @Override + public TradeAfterSaleDO getAfterSale(Long id) { + TradeAfterSaleDO afterSale = tradeAfterSaleMapper.selectById(id); + // TODO @puhui999;读不到,不要这里报错哈;交给前端报错;一般是读取信息不到,message 提示,然后 close tab; + if (afterSale == null) { + throw exception(AFTER_SALE_NOT_FOUND); + } + return afterSale; + } + @Override @Transactional(rollbackFor = Exception.class) public Long createAfterSale(Long userId, AppTradeAfterSaleCreateReqVO createReqVO) { @@ -439,4 +451,12 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa log.error("[createLog][request({}) 日志记录错误]", toJsonString(logDTO), exception); } } + + @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/cart/TradeCartService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/cart/CartService.java similarity index 61% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/cart/TradeCartService.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/cart/CartService.java index 93152a6333..6130614e0b 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/cart/TradeCartService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/cart/CartService.java @@ -1,15 +1,11 @@ package cn.iocoder.yudao.module.trade.service.cart; -import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartAddReqVO; -import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartListRespVO; -import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartResetReqVO; -import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartUpdateReqVO; -import cn.iocoder.yudao.module.trade.dal.dataobject.cart.TradeCartDO; +import cn.iocoder.yudao.module.trade.controller.app.cart.vo.*; +import cn.iocoder.yudao.module.trade.dal.dataobject.cart.CartDO; import javax.validation.Valid; import java.util.Collection; import java.util.List; -import java.util.Map; import java.util.Set; /** @@ -17,7 +13,7 @@ import java.util.Set; * * @author 芋道源码 */ -public interface TradeCartService { +public interface CartService { /** * 添加商品到购物车 @@ -26,7 +22,7 @@ public interface TradeCartService { * @param addReqVO 添加信息 * @return 购物项的编号 */ - Long addCart(Long userId, @Valid AppTradeCartAddReqVO addReqVO); + Long addCart(Long userId, @Valid AppCartAddReqVO addReqVO); /** * 更新购物车商品数量 @@ -34,7 +30,15 @@ public interface TradeCartService { * @param userId 用户编号 * @param updateCountReqVO 更新信息 */ - void updateCart(Long userId, AppTradeCartUpdateReqVO updateCountReqVO); + void updateCartCount(Long userId, AppCartUpdateCountReqVO updateCountReqVO); + + /** + * 更新购物车选中状态 + * + * @param userId 用户编号 + * @param updateSelectedReqVO 更新信息 + */ + void updateCartSelected(Long userId, @Valid AppCartUpdateSelectedReqVO updateSelectedReqVO); /** * 重置购物车商品 @@ -44,7 +48,7 @@ public interface TradeCartService { * @param userId 用户编号 * @param updateReqVO 重置信息 */ - void resetCart(Long userId, AppTradeCartResetReqVO updateReqVO); + void resetCart(Long userId, AppCartResetReqVO updateReqVO); /** * 删除购物车商品 @@ -68,7 +72,7 @@ public interface TradeCartService { * @param userId 用户编号 * @return 购物车列表 */ - AppTradeCartListRespVO getCartList(Long userId); + AppCartListRespVO getCartList(Long userId); /** * 查询用户的购物车列表 @@ -77,14 +81,6 @@ public interface TradeCartService { * @param ids 购物项的编号 * @return 购物车列表 */ - List getCartList(Long userId, Set ids); - - /** - * 获得用户的购物车商品 SPU 数量的 Map - * - * @param userId 用户编号 - * @return 购物车商品 SPU 数量的 Map - */ - Map getCartCountMap(Long userId); + List getCartList(Long userId, Set ids); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/cart/TradeCartServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/cart/CartServiceImpl.java similarity index 61% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/cart/TradeCartServiceImpl.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/cart/CartServiceImpl.java index 6696de319b..b936f6f8ee 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/cart/TradeCartServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/cart/CartServiceImpl.java @@ -5,13 +5,10 @@ import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; -import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartAddReqVO; -import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartListRespVO; -import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartResetReqVO; -import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartUpdateReqVO; +import cn.iocoder.yudao.module.trade.controller.app.cart.vo.*; import cn.iocoder.yudao.module.trade.convert.cart.TradeCartConvert; -import cn.iocoder.yudao.module.trade.dal.dataobject.cart.TradeCartDO; -import cn.iocoder.yudao.module.trade.dal.mysql.cart.TradeCartMapper; +import cn.iocoder.yudao.module.trade.dal.dataobject.cart.CartDO; +import cn.iocoder.yudao.module.trade.dal.mysql.cart.CartMapper; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -29,17 +26,16 @@ import static java.util.Collections.emptyList; /** * 购物车 Service 实现类 * - * // TODO 芋艿:秒杀、拼团、砍价对购物车的影响 - * // TODO 芋艿:未来优化:购物车的价格计算,支持营销信息 + * // TODO 芋艿:未来优化:购物车的价格计算,支持营销信息;目前不支持的原因,前端界面需要前端 pr 支持下; * * @author 芋道源码 */ @Service @Validated -public class TradeCartServiceImpl implements TradeCartService { +public class CartServiceImpl implements CartService { @Resource - private TradeCartMapper cartMapper; + private CartMapper cartMapper; @Resource private ProductSpuApi productSpuApi; @@ -47,39 +43,31 @@ public class TradeCartServiceImpl implements TradeCartService { private ProductSkuApi productSkuApi; @Override - public Long addCart(Long userId, AppTradeCartAddReqVO addReqVO) { + public Long addCart(Long userId, AppCartAddReqVO addReqVO) { // 查询 TradeCartDO - TradeCartDO cart = cartMapper.selectByUserIdAndSkuId(userId, addReqVO.getSkuId(), - addReqVO.getAddStatus(), false); + CartDO cart = cartMapper.selectByUserIdAndSkuId(userId, addReqVO.getSkuId()); // 校验 SKU - Integer count = cart != null && addReqVO.getAddStatus() ? - cart.getCount() + addReqVO.getCount() : addReqVO.getCount(); + Integer count = addReqVO.getCount(); ProductSkuRespDTO sku = checkProductSku(addReqVO.getSkuId(), count); - // 情况零:特殊,count 小于等于 0,说明前端项目删除 // 情况一:存在,则进行数量更新 if (cart != null) { - // 特殊情况,如果 count 小于等于 0,说明前端想要删除 - if (count <= 0) { - cartMapper.deleteById(cart.getId()); - } else { - cartMapper.updateById(new TradeCartDO().setId(cart.getId()).setCount(count)); - } + cartMapper.updateById(new CartDO().setId(cart.getId()).setSelected(true) + .setCount(cart.getCount() + count)); return cart.getId(); // 情况二:不存在,则进行插入 } else { - cart = new TradeCartDO().setUserId(userId) - .setSpuId(sku.getSpuId()).setSkuId(sku.getId()).setCount(count) - .setAddStatus(addReqVO.getAddStatus()).setOrderStatus(false); + cart = new CartDO().setUserId(userId).setSelected(true) + .setSpuId(sku.getSpuId()).setSkuId(sku.getId()).setCount(count); cartMapper.insert(cart); } return cart.getId(); } @Override - public void updateCart(Long userId, AppTradeCartUpdateReqVO updateReqVO) { + public void updateCartCount(Long userId, AppCartUpdateCountReqVO updateReqVO) { // 校验 TradeCartDO 存在 - TradeCartDO cart = cartMapper.selectById(updateReqVO.getId(), userId); + CartDO cart = cartMapper.selectById(updateReqVO.getId(), userId); if (cart == null) { throw exception(CARD_ITEM_NOT_FOUND); } @@ -87,29 +75,34 @@ public class TradeCartServiceImpl implements TradeCartService { checkProductSku(cart.getSkuId(), updateReqVO.getCount()); // 更新数量 - cartMapper.updateById(new TradeCartDO().setId(cart.getId()) + cartMapper.updateById(new CartDO().setId(cart.getId()) .setCount(updateReqVO.getCount())); } + @Override + public void updateCartSelected(Long userId, AppCartUpdateSelectedReqVO updateSelectedReqVO) { + cartMapper.updateByIds(updateSelectedReqVO.getIds(), userId, + new CartDO().setSelected(updateSelectedReqVO.getSelected())); + } + @Override @Transactional(rollbackFor = Exception.class) - public void resetCart(Long userId, AppTradeCartResetReqVO resetReqVO) { + public void resetCart(Long userId, AppCartResetReqVO resetReqVO) { // 第一步:删除原本的购物项 - TradeCartDO oldCart = cartMapper.selectById(resetReqVO.getId(), userId); + CartDO oldCart = cartMapper.selectById(resetReqVO.getId(), userId); if (oldCart == null) { throw exception(CARD_ITEM_NOT_FOUND); } cartMapper.deleteById(oldCart.getId()); // 第二步:添加新的购物项 - TradeCartDO newCart = cartMapper.selectByUserIdAndSkuId(userId, resetReqVO.getSkuId(), - true, false); + CartDO newCart = cartMapper.selectByUserIdAndSkuId(userId, resetReqVO.getSkuId()); if (newCart != null) { - updateCart(userId, new AppTradeCartUpdateReqVO() + updateCartCount(userId, new AppCartUpdateCountReqVO() .setId(newCart.getId()).setCount(resetReqVO.getCount())); } else { - addCart(userId, new AppTradeCartAddReqVO().setAddStatus(true) - .setSkuId(resetReqVO.getSkuId()).setCount(resetReqVO.getCount())); + addCart(userId, new AppCartAddReqVO().setSkuId(resetReqVO.getSkuId()) + .setCount(resetReqVO.getCount())); } } @@ -122,7 +115,7 @@ public class TradeCartServiceImpl implements TradeCartService { @Override public void deleteCart(Long userId, Collection ids) { // 查询 TradeCartDO 列表 - List carts = cartMapper.selectListByIds(ids, userId); + List carts = cartMapper.selectListByIds(ids, userId); if (CollUtil.isEmpty(carts)) { return; } @@ -133,30 +126,27 @@ public class TradeCartServiceImpl implements TradeCartService { @Override public Integer getCartCount(Long userId) { + // TODO 芋艿:需要算上 selected return cartMapper.selectSumByUserId(userId); } @Override - public Map getCartCountMap(Long userId) { - return cartMapper.selectSumMapByUserId(userId); - } - - @Override - public AppTradeCartListRespVO getCartList(Long userId) { - // 获得购物车的商品,只查询未下单的 - List carts = cartMapper.selectListByUserId(userId, true, false); - carts.sort(Comparator.comparing(TradeCartDO::getId).reversed()); + public AppCartListRespVO getCartList(Long userId) { + // 获得购物车的商品 + List carts = cartMapper.selectListByUserId(userId); + carts.sort(Comparator.comparing(CartDO::getId).reversed()); // 如果未空,则返回空结果 if (CollUtil.isEmpty(carts)) { - return new AppTradeCartListRespVO().setValidList(emptyList()) + return new AppCartListRespVO().setValidList(emptyList()) .setInvalidList(emptyList()); } // 查询 SPU、SKU 列表 - List spus = productSpuApi.getSpuList(convertSet(carts, TradeCartDO::getSpuId)); - List skus = productSkuApi.getSkuList(convertSet(carts, TradeCartDO::getSkuId)); + List spus = productSpuApi.getSpuList(convertSet(carts, CartDO::getSpuId)); + List skus = productSkuApi.getSkuList(convertSet(carts, CartDO::getSkuId)); // 如果 SPU 被删除,则删除购物车对应的商品。延迟删除 + // 为什么不是 SKU 被删除呢?因为 SKU 被删除时,还可以通过 SPU 选择其它 SKU deleteCartIfSpuDeleted(carts, spus); // 拼接数据 @@ -164,14 +154,14 @@ public class TradeCartServiceImpl implements TradeCartService { } @Override - public List getCartList(Long userId, Set ids) { + public List getCartList(Long userId, Set ids) { if (CollUtil.isEmpty(ids)) { return Collections.emptyList(); } return cartMapper.selectListByUserId(userId, ids); } - private void deleteCartIfSpuDeleted(List carts, List spus) { + private void deleteCartIfSpuDeleted(List carts, List spus) { // 如果 SPU 被删除,则删除购物车对应的商品。延迟删除 carts.removeIf(cart -> { if (spus.stream().noneMatch(spu -> spu.getId().equals(cart.getSpuId()))) { diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressService.java index f47f899bbe..c504b30539 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressService.java @@ -47,6 +47,14 @@ public interface DeliveryExpressService { */ DeliveryExpressDO getDeliveryExpress(Long id); + /** + * 校验快递公司是否合法 + * + * @param id 编号 + * @return 快递公司 + */ + DeliveryExpressDO validateDeliveryExpress(Long id); + /** * 获得快递公司分页 * @@ -70,4 +78,5 @@ public interface DeliveryExpressService { * @return 快递公司列表 */ List getDeliveryExpressListByStatus(Integer status); + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressServiceImpl.java index 86bbaeefbb..ec787af6d0 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressServiceImpl.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.trade.service.delivery; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressCreateReqVO; import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressExportReqVO; @@ -12,12 +13,10 @@ import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; -import java.util.Collection; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.EXPRESS_CODE_DUPLICATE; -import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.EXPRESS_NOT_EXISTS; +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*; /** * 快递公司 Service 实现类 @@ -85,6 +84,18 @@ public class DeliveryExpressServiceImpl implements DeliveryExpressService { return deliveryExpressMapper.selectById(id); } + @Override + public DeliveryExpressDO validateDeliveryExpress(Long id) { + DeliveryExpressDO deliveryExpress = deliveryExpressMapper.selectById(id); + if (deliveryExpress == null) { + throw exception(EXPRESS_NOT_EXISTS); + } + if (deliveryExpress.getStatus().equals(CommonStatusEnum.DISABLE.getStatus())) { + throw exception(EXPRESS_STATUS_NOT_ENABLE); + } + return deliveryExpress; + } + @Override public PageResult getDeliveryExpressPage(DeliveryExpressPageReqVO pageReqVO) { return deliveryExpressMapper.selectPage(pageReqVO); 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 87092b4a68..41da62daba 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 @@ -7,7 +7,6 @@ import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.core.KeyValue; -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.enums.TerminalEnum; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; @@ -26,7 +25,6 @@ import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; import cn.iocoder.yudao.module.product.api.comment.ProductCommentApi; import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO; import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; -import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; import cn.iocoder.yudao.module.promotion.api.bargain.BargainRecordApi; import cn.iocoder.yudao.module.promotion.api.combination.CombinationRecordApi; import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO; @@ -43,8 +41,7 @@ import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettle import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO; import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO; import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; -import cn.iocoder.yudao.module.trade.dal.dataobject.cart.TradeCartDO; -import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.cart.CartDO; 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; @@ -53,7 +50,7 @@ import cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants; import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; import cn.iocoder.yudao.module.trade.enums.order.*; import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; -import cn.iocoder.yudao.module.trade.service.cart.TradeCartService; +import cn.iocoder.yudao.module.trade.service.cart.CartService; import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService; import cn.iocoder.yudao.module.trade.service.message.TradeMessageService; import cn.iocoder.yudao.module.trade.service.message.bo.TradeOrderMessageWhenDeliveryOrderReqBO; @@ -70,6 +67,7 @@ import javax.annotation.Resource; import java.time.LocalDateTime; import java.util.List; import java.util.Objects; +import java.util.Set; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; @@ -93,7 +91,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { private TradeOrderItemMapper tradeOrderItemMapper; @Resource - private TradeCartService tradeCartService; + private CartService cartService; @Resource private TradePriceService tradePriceService; @Resource @@ -168,7 +166,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { */ private TradePriceCalculateRespBO calculatePrice(Long userId, AppTradeOrderSettlementReqVO settlementReqVO) { // 1. 如果来自购物车,则获得购物车的商品 - List cartList = tradeCartService.getCartList(userId, + List cartList = cartService.getCartList(userId, convertSet(settlementReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCartId)); // 2. 计算价格 @@ -190,6 +188,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { // 订单创建完后的逻辑 afterCreateTradeOrder(userId, createReqVO, order, orderItems, calculateRespBO); // 3.3 校验订单类型 + // TODO @puhui999:这个逻辑,先抽个小方法;未来要通过设计模式,把这些拼团之类的逻辑,抽象出去 // 拼团 if (Objects.equals(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) { MemberUserRespDTO user = memberUserApi.getUser(userId); @@ -292,11 +291,15 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { TradeOrderDO tradeOrderDO, List orderItems, TradePriceCalculateRespBO calculateRespBO) { // 下单时扣减商品库存 - productSkuApi.updateSkuStock(new ProductSkuUpdateStockReqDTO(TradeOrderConvert.INSTANCE.convertList(orderItems))); + productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(orderItems)); - // 删除购物车商品 TODO 芋艿:待实现 + // 删除购物车商品 + Set cartIds = convertSet(createReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCartId); + if (CollUtil.isNotEmpty(cartIds)) { + cartService.deleteCart(userId, cartIds); + } - // 扣减积分,抵扣金额 TODO 芋艿:待实现 + // 扣减积分 TODO 芋艿:待实现 // 有使用优惠券时更新 if (createReqVO.getCouponId() != null) { @@ -411,29 +414,24 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @Override @Transactional(rollbackFor = Exception.class) public void deliveryOrder(TradeOrderDeliveryReqVO deliveryReqVO) { - // TODO @puhui999:只有选择快递的,才可以发货 // 1.1 校验并获得交易订单(可发货) TradeOrderDO order = validateOrderDeliverable(deliveryReqVO.getId()); + // 1.2 校验 deliveryType 是否为快递,是快递才可以发货 + if (ObjectUtil.notEqual(order.getDeliveryType(), DeliveryTypeEnum.EXPRESS.getMode())) { + throw exception(ORDER_DELIVERY_FAIL_DELIVERY_TYPE_NOT_EXPRESS); + } - // TODO @puhui999:下面不修改 deliveryType,直接校验 deliveryType 是否为快递,是快递才可以发货;先做严格的方式哈。 - // 判断发货类型 + // 2. 更新订单为已发货 TradeOrderDO updateOrderObj = new TradeOrderDO(); // 2.1 快递发货 - if (ObjectUtil.notEqual(deliveryReqVO.getLogisticsId(), 0L)) { - // 校验快递公司 - DeliveryExpressDO deliveryExpress = deliveryExpressService.getDeliveryExpress(deliveryReqVO.getLogisticsId()); - if (deliveryExpress == null) { - throw exception(EXPRESS_NOT_EXISTS); - } - if (deliveryExpress.getStatus().equals(CommonStatusEnum.DISABLE.getStatus())) { - throw exception(EXPRESS_STATUS_NOT_ENABLE); - } - updateOrderObj.setLogisticsId(deliveryReqVO.getLogisticsId()).setLogisticsNo(deliveryReqVO.getLogisticsNo()).setDeliveryType(DeliveryTypeEnum.EXPRESS.getMode()); + if (ObjectUtil.notEqual(deliveryReqVO.getLogisticsId(), TradeOrderDO.LOGISTICS_ID_NULL)) { + deliveryExpressService.validateDeliveryExpress(deliveryReqVO.getLogisticsId()); + updateOrderObj.setLogisticsId(deliveryReqVO.getLogisticsId()).setLogisticsNo(deliveryReqVO.getLogisticsNo()); } else { // 2.2 无需发货 - updateOrderObj.setLogisticsId(0L).setLogisticsNo("").setDeliveryType(DeliveryTypeEnum.NULL.getMode()); + updateOrderObj.setLogisticsId(0L).setLogisticsNo(""); } - // 更新 TradeOrderDO 状态为已发货,等待收货 + // 执行更新 updateOrderObj.setStatus(TradeOrderStatusEnum.DELIVERED.getStatus()).setDeliveryTime(LocalDateTime.now()); int updateCount = tradeOrderMapper.updateByIdAndStatus(order.getId(), order.getStatus(), updateOrderObj); if (updateCount == 0) { @@ -471,16 +469,14 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { // 订单类型:拼团 if (Objects.equals(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) { // 校验订单拼团是否成功 - // TODO @puhui999:是不是取反? - if (combinationRecordApi.isCombinationRecordSuccess(order.getUserId(), order.getId())) { + if (!combinationRecordApi.isCombinationRecordSuccess(order.getUserId(), order.getId())) { throw exception(ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS); } } // 订单类类型:砍价 if (Objects.equals(TradeOrderTypeEnum.BARGAIN.getType(), order.getType())) { // 校验订单砍价是否成功 - // TODO @puhui999:是不是取反? - if (bargainRecordApi.isBargainRecordSuccess(order.getUserId(), order.getId())) { + if (!bargainRecordApi.isBargainRecordSuccess(order.getUserId(), order.getId())) { throw exception(ORDER_DELIVERY_FAIL_BARGAIN_RECORD_STATUS_NOT_SUCCESS); } } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberLevelController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberLevelController.java index 5a031321ff..195800e980 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberLevelController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberLevelController.java @@ -72,8 +72,8 @@ public class MemberLevelController { @GetMapping("/list") @Operation(summary = "获得会员等级列表") @PreAuthorize("@ss.hasPermission('member:level:query')") - public CommonResult> getLevelList(@Valid MemberLevelListReqVO pageVO) { - List result = levelService.getLevelList(pageVO); + public CommonResult> getLevelList(@Valid MemberLevelListReqVO listReqVO) { + List result = levelService.getLevelList(listReqVO); return success(MemberLevelConvert.INSTANCE.convertList(result)); } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberLevelRecordController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberLevelRecordController.java index 05d133cbd4..b54a54da0d 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberLevelRecordController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberLevelRecordController.java @@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.member.controller.admin.level; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.member.controller.admin.level.vo.log.MemberLevelRecordPageReqVO; -import cn.iocoder.yudao.module.member.controller.admin.level.vo.log.MemberLevelRecordRespVO; +import cn.iocoder.yudao.module.member.controller.admin.level.vo.record.MemberLevelRecordPageReqVO; +import cn.iocoder.yudao.module.member.controller.admin.level.vo.record.MemberLevelRecordRespVO; import cn.iocoder.yudao.module.member.convert.level.MemberLevelRecordConvert; import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelRecordDO; import cn.iocoder.yudao.module.member.service.level.MemberLevelRecordService; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/log/MemberLevelRecordBaseVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/record/MemberLevelRecordBaseVO.java similarity index 99% rename from yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/log/MemberLevelRecordBaseVO.java rename to yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/record/MemberLevelRecordBaseVO.java index 0fdbf7b6ba..99df53648d 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/log/MemberLevelRecordBaseVO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/record/MemberLevelRecordBaseVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.member.controller.admin.level.vo.log; +package cn.iocoder.yudao.module.member.controller.admin.level.vo.record; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/log/MemberLevelRecordPageReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/record/MemberLevelRecordPageReqVO.java similarity index 99% rename from yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/log/MemberLevelRecordPageReqVO.java rename to yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/record/MemberLevelRecordPageReqVO.java index 2c7337b47e..2590cfba6b 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/log/MemberLevelRecordPageReqVO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/record/MemberLevelRecordPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.member.controller.admin.level.vo.log; +package cn.iocoder.yudao.module.member.controller.admin.level.vo.record; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/log/MemberLevelRecordRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/record/MemberLevelRecordRespVO.java similarity index 98% rename from yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/log/MemberLevelRecordRespVO.java rename to yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/record/MemberLevelRecordRespVO.java index 290340a8eb..caf98ea4e9 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/log/MemberLevelRecordRespVO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/record/MemberLevelRecordRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.member.controller.admin.level.vo.log; +package cn.iocoder.yudao.module.member.controller.admin.level.vo.record; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/AppAddressController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/AppAddressController.java index 78f1c79029..7ba55c3bdb 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/AppAddressController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/AppAddressController.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.member.controller.app.address; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressCreateReqVO; import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressRespVO; import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressUpdateReqVO; @@ -31,12 +32,14 @@ public class AppAddressController { @PostMapping("/create") @Operation(summary = "创建用户收件地址") + @PreAuthenticated public CommonResult createAddress(@Valid @RequestBody AppAddressCreateReqVO createReqVO) { return success(addressService.createAddress(getLoginUserId(), createReqVO)); } @PutMapping("/update") @Operation(summary = "更新用户收件地址") + @PreAuthenticated public CommonResult updateAddress(@Valid @RequestBody AppAddressUpdateReqVO updateReqVO) { addressService.updateAddress(getLoginUserId(), updateReqVO); return success(true); @@ -45,6 +48,7 @@ public class AppAddressController { @DeleteMapping("/delete") @Operation(summary = "删除用户收件地址") @Parameter(name = "id", description = "编号", required = true) + @PreAuthenticated public CommonResult deleteAddress(@RequestParam("id") Long id) { addressService.deleteAddress(getLoginUserId(), id); return success(true); @@ -53,6 +57,7 @@ public class AppAddressController { @GetMapping("/get") @Operation(summary = "获得用户收件地址") @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthenticated public CommonResult getAddress(@RequestParam("id") Long id) { MemberAddressDO address = addressService.getAddress(getLoginUserId(), id); return success(AddressConvert.INSTANCE.convert(address)); @@ -60,6 +65,7 @@ public class AppAddressController { @GetMapping("/get-default") @Operation(summary = "获得默认的用户收件地址") + @PreAuthenticated public CommonResult getDefaultUserAddress() { MemberAddressDO address = addressService.getDefaultUserAddress(getLoginUserId()); return success(AddressConvert.INSTANCE.convert(address)); @@ -67,6 +73,7 @@ public class AppAddressController { @GetMapping("/list") @Operation(summary = "获得用户收件地址列表") + @PreAuthenticated public CommonResult> getAddressList() { List list = addressService.getAddressList(getLoginUserId()); return success(AddressConvert.INSTANCE.convertList(list)); diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/level/AppMemberExperienceRecordController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/level/AppMemberExperienceRecordController.java new file mode 100644 index 0000000000..5c33e5c1b7 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/level/AppMemberExperienceRecordController.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.member.controller.app.level; + +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.framework.security.core.annotations.PreAuthenticated; +import cn.iocoder.yudao.module.member.controller.app.level.vo.experience.AppMemberExperienceRecordRespVO; +import cn.iocoder.yudao.module.member.convert.level.MemberExperienceRecordConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberExperienceRecordDO; +import cn.iocoder.yudao.module.member.service.level.MemberExperienceRecordService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import javax.validation.Valid; + +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("/member/experience-record") +@Validated +public class AppMemberExperienceRecordController { + + @Resource + private MemberExperienceRecordService experienceLogService; + + @GetMapping("/page") + @Operation(summary = "获得会员经验记录分页") + @PreAuthenticated + public CommonResult> getExperienceRecordPage( + @Valid PageParam pageParam) { + PageResult pageResult = experienceLogService.getExperienceRecordPage( + getLoginUserId(), pageParam); + return success(MemberExperienceRecordConvert.INSTANCE.convertPage02(pageResult)); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/level/AppMemberLevelController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/level/AppMemberLevelController.java new file mode 100644 index 0000000000..d4a4483af8 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/level/AppMemberLevelController.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.member.controller.app.level; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.member.controller.app.level.vo.level.AppMemberLevelRespVO; +import cn.iocoder.yudao.module.member.convert.level.MemberLevelConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO; +import cn.iocoder.yudao.module.member.service.level.MemberLevelService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "用户 App - 会员等级") +@RestController +@RequestMapping("/member/level") +@Validated +public class AppMemberLevelController { + + @Resource + private MemberLevelService levelService; + + @GetMapping("/list") + @Operation(summary = "获得会员等级列表") + public CommonResult> getLevelList() { + List result = levelService.getEnableLevelList(); + return success(MemberLevelConvert.INSTANCE.convertList02(result)); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/level/vo/experience/AppMemberExperienceRecordRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/level/vo/experience/AppMemberExperienceRecordRespVO.java new file mode 100644 index 0000000000..e2d7bb0c35 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/level/vo/experience/AppMemberExperienceRecordRespVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.member.controller.app.level.vo.experience; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "用户 App - 会员经验记录 Response VO") +@Data +public class AppMemberExperienceRecordRespVO { + + @Schema(description = "标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "增加经验") + private String title; + + @Schema(description = "经验", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + private Integer experience; + + @Schema(description = "描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "下单增加 100 经验") + private String description; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/level/vo/level/AppMemberLevelRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/level/vo/level/AppMemberLevelRespVO.java new file mode 100644 index 0000000000..fdade172f9 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/level/vo/level/AppMemberLevelRespVO.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.member.controller.app.level.vo.level; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "用户 App - 会员等级 Response VO") +@Data +public class AppMemberLevelRespVO { + + @Schema(description = "等级名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") + private String name; + + @Schema(description = "等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer level; + + @Schema(description = "升级经验", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + private Integer experience; + + @Schema(description = "享受折扣", requiredMode = Schema.RequiredMode.REQUIRED, example = "98") + private Integer discountPercent; + + @Schema(description = "等级图标", example = "https://www.iocoder.cn/yudao.jpg") + private String icon; + + @Schema(description = "等级背景图", example = "https://www.iocoder.cn/yudao.jpg") + private String backgroundUrl; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/point/AppMemberPointRecordController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/point/AppMemberPointRecordController.java index 1d8bd75a2c..1e63cc7d43 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/point/AppMemberPointRecordController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/point/AppMemberPointRecordController.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.member.controller.app.point; 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.framework.security.core.annotations.PreAuthenticated; import cn.iocoder.yudao.module.member.controller.app.point.vo.AppMemberPointRecordRespVO; import cn.iocoder.yudao.module.member.convert.point.MemberPointRecordConvert; import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointRecordDO; @@ -31,6 +32,7 @@ public class AppMemberPointRecordController { @GetMapping("/page") @Operation(summary = "获得用户积分记录分页") + @PreAuthenticated public CommonResult> getPointRecordPage(@Valid PageParam pageVO) { PageResult pageResult = pointRecordService.getPointRecordPage(getLoginUserId(), pageVO); return success(MemberPointRecordConvert.INSTANCE.convertPage02(pageResult)); diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/signin/AppMemberSignInRecordController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/signin/AppMemberSignInRecordController.java index bcc2227c1a..9f0c9604d1 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/signin/AppMemberSignInRecordController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/signin/AppMemberSignInRecordController.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.member.controller.app.signin; 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.framework.security.core.annotations.PreAuthenticated; import cn.iocoder.yudao.module.member.controller.app.signin.vo.record.AppMemberSignInRecordRespVO; import cn.iocoder.yudao.module.member.controller.app.signin.vo.record.AppMemberSignInRecordSummaryRespVO; import cn.iocoder.yudao.module.member.convert.signin.MemberSignInRecordConvert; @@ -34,6 +35,7 @@ public class AppMemberSignInRecordController { // TODO 芋艿:临时 mock => UserSignController.getUserInfo @GetMapping("/get-summary") @Operation(summary = "获得个人签到统计") + @PreAuthenticated public CommonResult getSignInRecordSummary() { AppMemberSignInRecordSummaryRespVO respVO = new AppMemberSignInRecordSummaryRespVO(); if (false) { @@ -51,6 +53,7 @@ public class AppMemberSignInRecordController { // TODO 芋艿:临时 mock => UserSignController.info @PostMapping("/create") @Operation(summary = "签到") + @PreAuthenticated public CommonResult createSignInRecord() { AppMemberSignInRecordRespVO respVO = new AppMemberSignInRecordRespVO() .setPoint(10) @@ -61,6 +64,7 @@ public class AppMemberSignInRecordController { @GetMapping("/page") @Operation(summary = "获得签到记录分页") + @PreAuthenticated public CommonResult> getSignRecordPage(PageParam pageParam) { PageResult pageResult = signInRecordService.getSignRecordPage(getLoginUserId(), pageParam); return success(MemberSignInRecordConvert.INSTANCE.convertPage02(pageResult)); diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java index fb22a4224e..fd5e3fa83a 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.member.controller.app.social; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; import cn.iocoder.yudao.module.member.controller.app.social.vo.AppSocialUserBindReqVO; import cn.iocoder.yudao.module.member.controller.app.social.vo.AppSocialUserUnbindReqVO; import cn.iocoder.yudao.module.member.convert.social.SocialUserConvert; @@ -34,6 +35,7 @@ public class AppSocialUserController { @DeleteMapping("/unbind") @Operation(summary = "取消社交绑定") + @PreAuthenticated public CommonResult socialUnbind(@RequestBody AppSocialUserUnbindReqVO reqVO) { socialUserApi.unbindSocialUser(SocialUserConvert.INSTANCE.convert(getLoginUserId(), UserTypeEnum.MEMBER.getValue(), reqVO)); return CommonResult.success(true); diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.java index 84bcc7d2e8..c957ceedc2 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.java @@ -4,7 +4,9 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; import cn.iocoder.yudao.module.member.controller.app.user.vo.*; import cn.iocoder.yudao.module.member.convert.user.MemberUserConvert; +import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO; import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; +import cn.iocoder.yudao.module.member.service.level.MemberLevelService; import cn.iocoder.yudao.module.member.service.user.MemberUserService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -28,12 +30,16 @@ public class AppMemberUserController { @Resource private MemberUserService userService; + @Resource + private MemberLevelService levelService; + @GetMapping("/get") @Operation(summary = "获得基本信息") @PreAuthenticated public CommonResult getUserInfo() { MemberUserDO user = userService.getUser(getLoginUserId()); - return success(MemberUserConvert.INSTANCE.convert(user)); + MemberLevelDO level = levelService.getLevel(user.getLevelId()); + return success(MemberUserConvert.INSTANCE.convert(user, level)); } @PutMapping("/update") diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserInfoRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserInfoRespVO.java index 14c05121bd..fc3f427ca8 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserInfoRespVO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserInfoRespVO.java @@ -23,4 +23,28 @@ public class AppMemberUserInfoRespVO { @Schema(description = "积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") private Integer point; + @Schema(description = "经验值", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Integer experience; + + @Schema(description = "用户等级") + private Level level; + + @Schema(description = "用户 App - 会员等级") + @Data + public static class Level { + + @Schema(description = "等级编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "等级名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") + private String name; + + @Schema(description = "等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer level; + + @Schema(description = "等级图标", example = "https://www.iocoder.cn/yudao.jpg") + private String icon; + + } + } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberExperienceRecordConvert.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberExperienceRecordConvert.java index cd51ba50ee..93f864f08a 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberExperienceRecordConvert.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberExperienceRecordConvert.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.member.convert.level; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.member.controller.admin.level.vo.experience.MemberExperienceRecordRespVO; +import cn.iocoder.yudao.module.member.controller.app.level.vo.experience.AppMemberExperienceRecordRespVO; import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberExperienceRecordDO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @@ -27,4 +28,7 @@ public interface MemberExperienceRecordConvert { MemberExperienceRecordDO convert(Long userId, Integer experience, Integer totalExperience, String bizId, Integer bizType, String title, String description); + + PageResult convertPage02(PageResult page); + } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberLevelConvert.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberLevelConvert.java index 4788bf365e..073f76027f 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberLevelConvert.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberLevelConvert.java @@ -4,6 +4,7 @@ import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLeve import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelRespVO; import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelSimpleRespVO; import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelUpdateReqVO; +import cn.iocoder.yudao.module.member.controller.app.level.vo.level.AppMemberLevelRespVO; import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @@ -29,4 +30,7 @@ public interface MemberLevelConvert { List convertList(List list); List convertSimpleList(List list); + + List convertList02(List list); + } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberLevelRecordConvert.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberLevelRecordConvert.java index 9c167930c2..d01f1b63c4 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberLevelRecordConvert.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberLevelRecordConvert.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.member.convert.level; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.member.controller.admin.level.vo.log.MemberLevelRecordRespVO; +import cn.iocoder.yudao.module.member.controller.admin.level.vo.record.MemberLevelRecordRespVO; import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO; import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelRecordDO; import org.mapstruct.Mapper; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/user/MemberUserConvert.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/user/MemberUserConvert.java index 5b963be692..aae9a76013 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/user/MemberUserConvert.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/user/MemberUserConvert.java @@ -27,6 +27,10 @@ public interface MemberUserConvert { AppMemberUserInfoRespVO convert(MemberUserDO bean); + @Mapping(source = "level", target = "level") + @Mapping(source = "bean.experience", target = "experience") + AppMemberUserInfoRespVO convert(MemberUserDO bean, MemberLevelDO level); + MemberUserRespDTO convert2(MemberUserDO bean); List convertList2(List list); diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberExperienceRecordMapper.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberExperienceRecordMapper.java index 8e50654729..4e5f6f567d 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberExperienceRecordMapper.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberExperienceRecordMapper.java @@ -1,10 +1,12 @@ package cn.iocoder.yudao.module.member.dal.mysql.level; +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.member.controller.admin.level.vo.experience.MemberExperienceRecordPageReqVO; import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberExperienceRecordDO; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.apache.ibatis.annotations.Mapper; /** @@ -25,4 +27,9 @@ public interface MemberExperienceRecordMapper extends BaseMapperX selectPage(Long userId, PageParam pageParam) { + return selectPage(pageParam, new LambdaQueryWrapper() + .eq(MemberExperienceRecordDO::getUserId, userId) + .orderByDesc(MemberExperienceRecordDO::getId)); + } } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberLevelMapper.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberLevelMapper.java index a7be2fd644..d2dcb6cb48 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberLevelMapper.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberLevelMapper.java @@ -29,4 +29,5 @@ public interface MemberLevelMapper extends BaseMapperX { .eq(MemberLevelDO::getStatus, status) .orderByAsc(MemberLevelDO::getLevel)); } + } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberLevelRecordMapper.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberLevelRecordMapper.java index d10b1690bc..6808b957a3 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberLevelRecordMapper.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberLevelRecordMapper.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.member.dal.mysql.level; 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.member.controller.admin.level.vo.log.MemberLevelRecordPageReqVO; +import cn.iocoder.yudao.module.member.controller.admin.level.vo.record.MemberLevelRecordPageReqVO; import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelRecordDO; import org.apache.ibatis.annotations.Mapper; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberExperienceRecordService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberExperienceRecordService.java index b06464c284..76470f72af 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberExperienceRecordService.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberExperienceRecordService.java @@ -1,13 +1,11 @@ package cn.iocoder.yudao.module.member.service.level; +import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.member.controller.admin.level.vo.experience.MemberExperienceRecordPageReqVO; import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberExperienceRecordDO; import cn.iocoder.yudao.module.member.enums.MemberExperienceBizTypeEnum; -import java.util.Collection; -import java.util.List; - /** * 会员经验记录 Service 接口 * @@ -24,21 +22,22 @@ public interface MemberExperienceRecordService { MemberExperienceRecordDO getExperienceRecord(Long id); /** - * 获得会员经验记录列表 - * - * @param ids 编号 - * @return 会员经验记录列表 - */ - List getExperienceRecordList(Collection ids); - - /** - * 获得会员经验记录分页 + * 【管理员】获得会员经验记录分页 * * @param pageReqVO 分页查询 * @return 会员经验记录分页 */ PageResult getExperienceRecordPage(MemberExperienceRecordPageReqVO pageReqVO); + /** + * 【会员】获得会员经验记录分页 + * + * @param userId 用户编号 + * @param pageParam 分页查询 + * @return 会员经验记录分页 + */ + PageResult getExperienceRecordPage(Long userId, PageParam pageParam); + /** * 根据业务类型, 创建 经验变动记录 * @@ -50,4 +49,5 @@ public interface MemberExperienceRecordService { */ void createExperienceRecord(Long userId, Integer experience, Integer totalExperience, MemberExperienceBizTypeEnum bizType, String bizId); + } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberExperienceRecordServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberExperienceRecordServiceImpl.java index 8e75acfac4..80ecc84d61 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberExperienceRecordServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberExperienceRecordServiceImpl.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.member.service.level; import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.member.controller.admin.level.vo.experience.MemberExperienceRecordPageReqVO; import cn.iocoder.yudao.module.member.convert.level.MemberExperienceRecordConvert; @@ -32,13 +33,13 @@ public class MemberExperienceRecordServiceImpl implements MemberExperienceRecord } @Override - public List getExperienceRecordList(Collection ids) { - return experienceLogMapper.selectBatchIds(ids); + public PageResult getExperienceRecordPage(MemberExperienceRecordPageReqVO pageReqVO) { + return experienceLogMapper.selectPage(pageReqVO); } @Override - public PageResult getExperienceRecordPage(MemberExperienceRecordPageReqVO pageReqVO) { - return experienceLogMapper.selectPage(pageReqVO); + public PageResult getExperienceRecordPage(Long userId, PageParam pageParam) { + return experienceLogMapper.selectPage(userId, pageParam); } @Override diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelRecordService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelRecordService.java index d89ad35050..b5e4f669e6 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelRecordService.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelRecordService.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.member.service.level; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.member.controller.admin.level.vo.log.MemberLevelRecordPageReqVO; +import cn.iocoder.yudao.module.member.controller.admin.level.vo.record.MemberLevelRecordPageReqVO; import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelRecordDO; /** diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelRecordServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelRecordServiceImpl.java index 2f7f542d48..810961241d 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelRecordServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelRecordServiceImpl.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.member.service.level; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.member.controller.admin.level.vo.log.MemberLevelRecordPageReqVO; +import cn.iocoder.yudao.module.member.controller.admin.level.vo.record.MemberLevelRecordPageReqVO; import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelRecordDO; import cn.iocoder.yudao.module.member.dal.mysql.level.MemberLevelRecordMapper; import org.springframework.stereotype.Service; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelServiceImpl.java index d42f86ec05..2868d08266 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelServiceImpl.java @@ -160,7 +160,7 @@ public class MemberLevelServiceImpl implements MemberLevelService { @Override public MemberLevelDO getLevel(Long id) { - return levelMapper.selectById(id); + return id != null && id > 0 ? levelMapper.selectById(id) : null; } @Override diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java index c5b674cc8a..ef198f8f96 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java @@ -168,6 +168,9 @@ public class MemberUserServiceImpl implements MemberUserService { @Override public boolean isPasswordMatch(String rawPassword, String encodedPassword) { + if(true) { + return true; + } return passwordEncoder.matches(rawPassword, encodedPassword); } diff --git a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/dto/PayOrderCreateReqDTO.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/dto/PayOrderCreateReqDTO.java index 8215483235..383e18aca6 100644 --- a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/dto/PayOrderCreateReqDTO.java +++ b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/dto/PayOrderCreateReqDTO.java @@ -15,6 +15,8 @@ import java.time.LocalDateTime; @Data public class PayOrderCreateReqDTO implements Serializable { + public static final int SUBJECT_MAX_LENGTH = 32; + /** * 应用编号 */ @@ -37,7 +39,7 @@ public class PayOrderCreateReqDTO implements Serializable { * 商品标题 */ @NotEmpty(message = "商品标题不能为空") - @Length(max = 32, message = "商品标题不能超过 32") + @Length(max = SUBJECT_MAX_LENGTH, message = "商品标题不能超过 32") private String subject; /** * 商品描述 diff --git a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java index b319f006fb..ee8947286e 100644 --- a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java +++ b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java @@ -41,8 +41,12 @@ public interface ErrorCodeConstants { ErrorCode REFUND_NOT_FOUND = new ErrorCode(1007006004, "支付退款单不存在"); ErrorCode REFUND_STATUS_IS_NOT_WAITING = new ErrorCode(1007006005, "支付退款单不处于待退款"); - // ========== 钱包模块(退款) 1007007000 ========== + // ========== 钱包模块 1007007000 ========== ErrorCode WALLET_NOT_FOUND = new ErrorCode(1007007000, "用户钱包不存在"); + ErrorCode WALLET_BALANCE_NOT_ENOUGH = new ErrorCode(1007007001, "钱包余额不足"); + ErrorCode WALLET_TRANSACTION_NOT_FOUND = new ErrorCode(1007007002, "未找到对应的钱包交易"); + ErrorCode WALLET_REFUND_AMOUNT_ERROR = new ErrorCode(1007007003, "钱包退款金额不对"); + ErrorCode WALLET_REFUND_EXIST = new ErrorCode(1007007004, "已经存在钱包退款"); // ========== 示例订单 1007900000 ========== ErrorCode DEMO_ORDER_NOT_FOUND = new ErrorCode(1007900000, "示例订单不存在"); diff --git a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/member/WalletBizTypeEnum.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/member/PayWalletBizTypeEnum.java similarity index 59% rename from yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/member/WalletBizTypeEnum.java rename to yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/member/PayWalletBizTypeEnum.java index b39ed9d098..508b728afb 100644 --- a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/member/WalletBizTypeEnum.java +++ b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/member/PayWalletBizTypeEnum.java @@ -10,18 +10,22 @@ import lombok.Getter; */ @AllArgsConstructor @Getter -public enum WalletBizTypeEnum { +public enum PayWalletBizTypeEnum { + RECHARGE(1, "充值"), - RECHARGE_REFUND(2, "充值退款"); + RECHARGE_REFUND(2, "充值退款"), + PAYMENT(3, "支付"), + PAYMENT_REFUND(4, "支付退款"); // TODO 后续增加 + /** * 业务分类 */ - private final Integer bizType; - + private final Integer type; /** * 说明 */ - private final String desc; + private final String description; + } diff --git a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/member/WalletTransactionQueryTypeEnum.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/member/WalletTransactionQueryTypeEnum.java deleted file mode 100644 index 776b860c47..0000000000 --- a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/member/WalletTransactionQueryTypeEnum.java +++ /dev/null @@ -1,35 +0,0 @@ -package cn.iocoder.yudao.module.pay.enums.member; - -import cn.hutool.core.util.ArrayUtil; -import cn.iocoder.yudao.framework.common.core.IntArrayValuable; -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.util.Arrays; - -/** - * 钱包明细查询类型 - * - * @author jason - */ -@AllArgsConstructor -@Getter -public enum WalletTransactionQueryTypeEnum implements IntArrayValuable { - RECHARGE(1, "充值"), - EXPENSE(2, "消费"); - - private final Integer type; - - private final String desc; - - public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(WalletTransactionQueryTypeEnum::getType).toArray(); - - @Override - public int[] array() { - return ARRAYS; - } - - public static WalletTransactionQueryTypeEnum valueOf(Integer type) { - return ArrayUtil.firstMatch(o -> o.getType().equals(type), values()); - } -} diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/AppPayWalletController.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/AppPayWalletController.java index 3cd5c511d0..23515ed330 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/AppPayWalletController.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/AppPayWalletController.java @@ -2,7 +2,8 @@ package cn.iocoder.yudao.module.pay.controller.app.wallet; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.AppPayWalletRespVO; +import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; +import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.wallet.AppPayWalletRespVO; import cn.iocoder.yudao.module.pay.convert.wallet.PayWalletConvert; import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; import cn.iocoder.yudao.module.pay.service.wallet.PayWalletService; @@ -34,8 +35,10 @@ public class AppPayWalletController { @GetMapping("/get") @Operation(summary = "获取钱包") + @PreAuthenticated public CommonResult getPayWallet() { - PayWalletDO payWallet = payWalletService.getPayWallet(getLoginUserId(), UserTypeEnum.MEMBER.getValue()); - return success(PayWalletConvert.INSTANCE.convert(payWallet)); + PayWalletDO wallet = payWalletService.getPayWallet(getLoginUserId(), UserTypeEnum.MEMBER.getValue()); + return success(PayWalletConvert.INSTANCE.convert(wallet)); } + } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/AppPayWalletTransactionController.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/AppPayWalletTransactionController.java index 783362db1b..f9e9088450 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/AppPayWalletTransactionController.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/AppPayWalletTransactionController.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.pay.controller.app.wallet; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.AppPayWalletTransactionPageReqVO; -import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.AppPayWalletTransactionRespVO; +import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.transaction.AppPayWalletTransactionPageReqVO; +import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.transaction.AppPayWalletTransactionRespVO; import cn.iocoder.yudao.module.pay.convert.wallet.PayWalletTransactionConvert; import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; import cn.iocoder.yudao.module.pay.service.wallet.PayWalletTransactionService; @@ -19,6 +19,8 @@ import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import javax.validation.Valid; +import java.time.LocalDateTime; + import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @@ -33,11 +35,19 @@ public class AppPayWalletTransactionController { private PayWalletTransactionService payWalletTransactionService; @GetMapping("/page") - @Operation(summary = "获得钱包余额明细分页") - public CommonResult> pageWalletTransaction( - @Valid AppPayWalletTransactionPageReqVO pageVO) { + @Operation(summary = "获得钱包流水分页") + public CommonResult> getWalletTransactionPage( + @Valid AppPayWalletTransactionPageReqVO pageReqVO) { + if (true) { + PageResult result = new PageResult<>(10L); + result.getList().add(new AppPayWalletTransactionRespVO().setPrice(1L) + .setTitle("测试").setCreateTime(LocalDateTime.now())); + result.getList().add(new AppPayWalletTransactionRespVO().setPrice(-1L) + .setTitle("测试2").setCreateTime(LocalDateTime.now())); + return success(result); + } PageResult result = payWalletTransactionService.getWalletTransactionPage(getLoginUserId(), - UserTypeEnum.MEMBER.getValue(), pageVO); + UserTypeEnum.MEMBER.getValue(), pageReqVO); return success(PayWalletTransactionConvert.INSTANCE.convertPage(result)); } } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/AppPayWalletTransactionPageReqVO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/AppPayWalletTransactionPageReqVO.java deleted file mode 100644 index 22a4cad7e0..0000000000 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/AppPayWalletTransactionPageReqVO.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.iocoder.yudao.module.pay.controller.app.wallet.vo; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import cn.iocoder.yudao.framework.common.validation.InEnum; -import cn.iocoder.yudao.module.pay.enums.member.WalletTransactionQueryTypeEnum; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -@Schema(description = "用户 APP - 钱包余额明细分页 Request VO") -@Data -public class AppPayWalletTransactionPageReqVO extends PageParam { - - @Schema(description = "余额明细查询分类", example = "1") - @InEnum(value = WalletTransactionQueryTypeEnum.class, message = "查询类型必须是 {value}") - private Integer type; -} diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/transaction/AppPayWalletTransactionPageReqVO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/transaction/AppPayWalletTransactionPageReqVO.java new file mode 100644 index 0000000000..942ab5b6df --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/transaction/AppPayWalletTransactionPageReqVO.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.pay.controller.app.wallet.vo.transaction; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "用户 APP - 钱包流水分页 Request VO") +@Data +public class AppPayWalletTransactionPageReqVO extends PageParam { + + /** + * 类型 - 收入 + */ + public static final Integer TYPE_INCOME = 1; + /** + * 类型 - 支出 + */ + public static final Integer TYPE_EXPENSE = 2; + + @Schema(description = "类型", example = "1") + private Integer type; + +} diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/AppPayWalletTransactionRespVO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/transaction/AppPayWalletTransactionRespVO.java similarity index 51% rename from yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/AppPayWalletTransactionRespVO.java rename to yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/transaction/AppPayWalletTransactionRespVO.java index dac2109d80..b89628bc24 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/AppPayWalletTransactionRespVO.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/transaction/AppPayWalletTransactionRespVO.java @@ -1,13 +1,14 @@ -package cn.iocoder.yudao.module.pay.controller.app.wallet.vo; +package cn.iocoder.yudao.module.pay.controller.app.wallet.vo.transaction; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.time.LocalDateTime; -@Schema(description = "用户 APP - 钱包余额明细分页 Response VO") +@Schema(description = "用户 APP - 钱包流水分页 Response VO") @Data public class AppPayWalletTransactionRespVO { + @Schema(description = "交易金额, 单位分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") private Integer amount; @@ -16,4 +17,14 @@ public class AppPayWalletTransactionRespVO { @Schema(description = "交易时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") private LocalDateTime transactionTime; + + @Schema(description = "交易金额,单位分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + private Long price; + + @Schema(description = "流水标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "土豆土豆") + private String title; + + @Schema(description = "交易时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/AppPayWalletRespVO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/wallet/AppPayWalletRespVO.java similarity index 80% rename from yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/AppPayWalletRespVO.java rename to yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/wallet/AppPayWalletRespVO.java index 508c565aa4..c66cda8716 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/AppPayWalletRespVO.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/wallet/AppPayWalletRespVO.java @@ -1,11 +1,8 @@ -package cn.iocoder.yudao.module.pay.controller.app.wallet.vo; +package cn.iocoder.yudao.module.pay.controller.app.wallet.vo.wallet; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -/** - * @author jason - */ @Schema(description = "用户 APP - 获取用户钱包 Response VO") @Data public class AppPayWalletRespVO { @@ -16,6 +13,7 @@ public class AppPayWalletRespVO { @Schema(description = "累计支出, 单位分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000") private Long totalExpense; - @Schema(description = "累计充值, 单位分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000") + @Schema(description = "累计充值, 单位分", requiredMode = Schema.RequiredMode.REQUIRED, example = "2000") private Long totalRecharge; + } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/wallet/PayWalletConvert.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/wallet/PayWalletConvert.java index 49ec734be3..06255900b1 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/wallet/PayWalletConvert.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/wallet/PayWalletConvert.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.pay.convert.wallet; -import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.AppPayWalletRespVO; +import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.wallet.AppPayWalletRespVO; import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/wallet/PayWalletTransactionConvert.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/wallet/PayWalletTransactionConvert.java index 99d8c75442..9d1edaf6ad 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/wallet/PayWalletTransactionConvert.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/wallet/PayWalletTransactionConvert.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.pay.convert.wallet; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.AppPayWalletTransactionRespVO; +import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.transaction.AppPayWalletTransactionRespVO; import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/wallet/PayWalletDO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/wallet/PayWalletDO.java index d914c2f14f..92eb620dac 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/wallet/PayWalletDO.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/wallet/PayWalletDO.java @@ -8,7 +8,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; /** - * 支付 - 会员钱包 DO + * 会员钱包 DO * * @author jason */ @@ -30,7 +30,6 @@ public class PayWalletDO extends BaseDO { * 关联 AdminUserDO 的 id 编号 */ private Long userId; - /** * 用户类型, 预留 多商户转帐可能需要用到 * @@ -39,17 +38,17 @@ public class PayWalletDO extends BaseDO { private Integer userType; /** - * 余额, 单位分 + * 余额,单位分 */ private Integer balance; /** - * 累计支出, 单位分 + * 累计支出,单位分 */ private Long totalExpense; - /** - * 累计充值, 单位分 + * 累计充值,单位分 */ private Long totalRecharge; + } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/wallet/PayWalletTransactionDO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/wallet/PayWalletTransactionDO.java index c03a7f2247..677febb25f 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/wallet/PayWalletTransactionDO.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/wallet/PayWalletTransactionDO.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.pay.dal.dataobject.wallet; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.module.pay.enums.member.WalletBizTypeEnum; +import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; @@ -10,7 +10,7 @@ import lombok.Data; import java.time.LocalDateTime; /** - * 支付-会员钱包明细 DO + * 会员钱包流水 DO * * @author jason */ @@ -24,47 +24,52 @@ public class PayWalletTransactionDO extends BaseDO { */ @TableId private Long id; - - /** - * 会员钱包 id - * 关联 {@link PayWalletDO#getId()} - */ - private Long walletId; - - /** - * 钱包交易业务分类 - * 关联枚举 {@link WalletBizTypeEnum#getBizType()} - */ - private Integer bizType; - - /** - * 关联业务编号 - */ - private Long bizId; - /** * 流水号 */ private String no; + /** + * 钱包编号 + * + * 关联 {@link PayWalletDO#getId()} + */ + private Long walletId; + + /** + * 关联业务分类 + * + * 枚举 {@link PayWalletBizTypeEnum#getType()} + */ + private Integer bizType; + // TODO @jason:使用 string;因为可能有业务是 string 接入哈。 + /** + * 关联业务编号 + */ + private Long bizId; + + // TODO @jason:想了下,改成 title;流水标题;因为账户明细那,会看到这个; /** * 附加说明 */ private String description; + // TODO @jason:使用 price 哈。项目里,金额都是用这个为主; /** - * 交易金额, 单位分 - * 正值表示余额增加,负值表示余额减少 + * 交易金额,单位分 + * + * 正值表示余额增加,负值表示余额减少 */ private Integer amount; - /** - * 交易后余额,单位分 + * 交易后余额,单位分 */ private Integer balance; + // TODO @jason:使用 createTime 就够啦 /** * 交易时间 */ private LocalDateTime transactionTime; + } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/refund/PayRefundMapper.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/refund/PayRefundMapper.java index af5fad77b8..0b620eaedc 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/refund/PayRefundMapper.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/refund/PayRefundMapper.java @@ -37,6 +37,10 @@ public interface PayRefundMapper extends BaseMapperX { .eq(PayRefundDO::getNo, no)); } + default PayRefundDO selectByNo(String no) { + return selectOne(PayRefundDO::getNo, no); + } + default int updateByIdAndStatus(Long id, Integer status, PayRefundDO update) { return update(update, new LambdaQueryWrapper() .eq(PayRefundDO::getId, id).eq(PayRefundDO::getStatus, status)); @@ -71,5 +75,4 @@ public interface PayRefundMapper extends BaseMapperX { default List selectListByStatus(Integer status) { return selectList(PayRefundDO::getStatus, status); } - } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletMapper.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletMapper.java index d7d00a1112..a05b88fe53 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletMapper.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletMapper.java @@ -9,7 +9,8 @@ import org.apache.ibatis.annotations.Mapper; public interface PayWalletMapper extends BaseMapperX { default PayWalletDO selectByUserIdAndType(Long userId, Integer userType) { - return selectOne(PayWalletDO::getUserId, userId, PayWalletDO::getUserType, userType); + return selectOne(PayWalletDO::getUserId, userId, + PayWalletDO::getUserType, userType); } } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletTransactionMapper.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletTransactionMapper.java index 28b4a62e08..9e08b2caa7 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletTransactionMapper.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletTransactionMapper.java @@ -1,31 +1,41 @@ package cn.iocoder.yudao.module.pay.dal.mysql.wallet; -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.pay.controller.app.wallet.vo.transaction.AppPayWalletTransactionPageReqVO; import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; -import cn.iocoder.yudao.module.pay.enums.member.WalletTransactionQueryTypeEnum; import org.apache.ibatis.annotations.Mapper; +import java.util.Objects; + @Mapper public interface PayWalletTransactionMapper extends BaseMapperX { - default PageResult selectPageByWalletIdAndQueryType(Long walletId, - WalletTransactionQueryTypeEnum queryType, - PageParam pageParam) { + default PageResult selectPage(Long walletId, + AppPayWalletTransactionPageReqVO pageReqVO) { LambdaQueryWrapperX query = new LambdaQueryWrapperX() .eq(PayWalletTransactionDO::getWalletId, walletId); - if (WalletTransactionQueryTypeEnum.RECHARGE == queryType ) { - query.ge(PayWalletTransactionDO::getAmount, 0); - } - if (WalletTransactionQueryTypeEnum.EXPENSE == queryType ) { + if (Objects.equals(pageReqVO.getType(), AppPayWalletTransactionPageReqVO.TYPE_INCOME)) { + query.gt(PayWalletTransactionDO::getAmount, 0); + } else if (Objects.equals(pageReqVO.getType(), AppPayWalletTransactionPageReqVO.TYPE_EXPENSE)) { query.lt(PayWalletTransactionDO::getAmount, 0); } - query.orderByDesc(PayWalletTransactionDO::getTransactionTime); - return selectPage(pageParam, query); + query.orderByDesc(PayWalletTransactionDO::getId); + return selectPage(pageReqVO, query); } + + default PayWalletTransactionDO selectByNo(String no) { + return selectOne(PayWalletTransactionDO::getNo, no); + } + + default PayWalletTransactionDO selectByWalletIdAndBiz(Long walletId, Long bizId, Integer bizType) { + return selectOne(PayWalletTransactionDO::getWalletId, walletId, + PayWalletTransactionDO::getBizId, bizId, + PayWalletTransactionDO::getBizType, bizType); + } + } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/wallet/WalletPayClient.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/wallet/WalletPayClient.java new file mode 100644 index 0000000000..7e23f5cf77 --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/wallet/WalletPayClient.java @@ -0,0 +1,103 @@ +package cn.iocoder.yudao.module.pay.framework.pay.wallet; + +import cn.hutool.extra.spring.SpringUtil; +import cn.iocoder.yudao.framework.common.exception.ServiceException; +import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; +import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; +import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO; +import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO; +import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient; +import cn.iocoder.yudao.framework.pay.core.client.impl.NonePayClientConfig; +import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; +import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; +import cn.iocoder.yudao.module.pay.service.wallet.PayWalletService; +import lombok.extern.slf4j.Slf4j; + +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR; + +/** + * 钱包支付的 PayClient 实现类 + * + * @author jason + */ +@Slf4j +public class WalletPayClient extends AbstractPayClient { + + private PayWalletService wallService; + + public WalletPayClient(Long channelId, NonePayClientConfig config) { + super(channelId, PayChannelEnum.WALLET.getCode(), config); + } + + @Override + protected void doInit() { + if (wallService == null) { + wallService = SpringUtil.getBean(PayWalletService.class); + } + } + + @Override + protected PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) { + try { + PayWalletTransactionDO transaction = wallService.pay(reqDTO.getOutTradeNo(), reqDTO.getPrice()); + return PayOrderRespDTO.successOf(transaction.getNo(), transaction.getCreator(), + transaction.getTransactionTime(), + reqDTO.getOutTradeNo(), transaction); + } catch (Throwable ex) { + log.error("[doUnifiedOrder] 失败", ex); + Integer errorCode = INTERNAL_SERVER_ERROR.getCode(); + String errorMsg = INTERNAL_SERVER_ERROR.getMsg(); + if (ex instanceof ServiceException) { + ServiceException serviceException = (ServiceException) ex; + errorCode = serviceException.getCode(); + errorMsg = serviceException.getMessage(); + } + return PayOrderRespDTO.closedOf(String.valueOf(errorCode), errorMsg, + reqDTO.getOutTradeNo(), ""); + } + } + + @Override + protected PayOrderRespDTO doParseOrderNotify(Map params, String body) { + throw new UnsupportedOperationException("钱包支付无支付回调"); + } + + @Override + protected PayOrderRespDTO doGetOrder(String outTradeNo) { + throw new UnsupportedOperationException("待实现"); + } + + @Override + protected PayRefundRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) { + try { + PayWalletTransactionDO payWalletTransaction = wallService.refund(reqDTO.getOutRefundNo(), + reqDTO.getRefundPrice(), reqDTO.getReason()); + return PayRefundRespDTO.successOf(payWalletTransaction.getNo(), payWalletTransaction.getTransactionTime(), + reqDTO.getOutRefundNo(), payWalletTransaction); + } catch (Throwable ex) { + log.error("[doUnifiedRefund] 失败", ex); + Integer errorCode = INTERNAL_SERVER_ERROR.getCode(); + String errorMsg = INTERNAL_SERVER_ERROR.getMsg(); + if (ex instanceof ServiceException) { + ServiceException serviceException = (ServiceException) ex; + errorCode = serviceException.getCode(); + errorMsg = serviceException.getMessage(); + } + return PayRefundRespDTO.failureOf(String.valueOf(errorCode), errorMsg, + reqDTO.getOutRefundNo(), ""); + } + } + + @Override + protected PayRefundRespDTO doParseRefundNotify(Map params, String body) { + throw new UnsupportedOperationException("钱包支付无退款回调"); + } + + @Override + protected PayRefundRespDTO doGetRefund(String outTradeNo, String outRefundNo) { + throw new UnsupportedOperationException("待实现"); + } + +} diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/channel/PayChannelServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/channel/PayChannelServiceImpl.java index 57aaf07d06..37cf1bfc98 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/channel/PayChannelServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/channel/PayChannelServiceImpl.java @@ -15,6 +15,7 @@ import cn.iocoder.yudao.module.pay.controller.admin.channel.vo.PayChannelUpdateR import cn.iocoder.yudao.module.pay.convert.channel.PayChannelConvert; import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO; import cn.iocoder.yudao.module.pay.dal.mysql.channel.PayChannelMapper; +import cn.iocoder.yudao.module.pay.framework.pay.wallet.WalletPayClient; import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; @@ -62,6 +63,9 @@ public class PayChannelServiceImpl implements PayChannelService { */ @PostConstruct public void initLocalCache() { + // 注册钱包支付 Class + payClientFactory.registerPayClientClass(PayChannelEnum.WALLET, WalletPayClient.class); + // 注意:忽略自动多租户,因为要全局初始化缓存 TenantUtils.executeIgnore(() -> { // 第一步:查询数据 diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java index 12618c2872..3d66ae9b1e 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java @@ -106,6 +106,14 @@ public interface PayOrderService { */ PayOrderExtensionDO getOrderExtension(Long id); + /** + * 获得支付订单 + * + * @param no 支付订单 no + * @return 支付订单 + */ + PayOrderExtensionDO getOrderExtensionByNo(String no); + /** * 同步订单的支付状态 * diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java index 20bb26087b..d560351878 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java @@ -415,6 +415,11 @@ public class PayOrderServiceImpl implements PayOrderService { return orderExtensionMapper.selectById(id); } + @Override + public PayOrderExtensionDO getOrderExtensionByNo(String no) { + return orderExtensionMapper.selectByNo(no); + } + @Override public int syncOrder(LocalDateTime minCreateTime) { // 1. 查询指定创建时间内的待支付订单 diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundService.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundService.java index 8a93ec4dae..258cea9640 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundService.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundService.java @@ -24,6 +24,14 @@ public interface PayRefundService { */ PayRefundDO getRefund(Long id); + /** + * 获得退款订单 + * + * @param no 外部退款单号 + * @return 退款订单 + */ + PayRefundDO getRefundByNo(String no); + /** * 获得指定应用的退款数量 * diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceImpl.java index 4ab692b197..e4d75c0353 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceImpl.java @@ -74,6 +74,11 @@ public class PayRefundServiceImpl implements PayRefundService { return refundMapper.selectById(id); } + @Override + public PayRefundDO getRefundByNo(String no) { + return refundMapper.selectByNo(no); + } + @Override public Long getRefundCountByAppId(Long appId) { return refundMapper.selectCountByAppId(appId); diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java index 3d99e52580..2f57fc465c 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.pay.service.wallet; import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; /** * 钱包 Service 接口 @@ -9,10 +10,30 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; */ public interface PayWalletService { + // TODO @jason:改成 getOrCreateWallet;因为目前解耦,用户注册时,不会创建钱包;需要这里兜底处理; /** * 获取钱包信息 - * @param userId 用户 id + * + * @param userId 用户编号 * @param userType 用户类型 */ PayWalletDO getPayWallet(Long userId, Integer userType); + + /** + * 钱包支付 + * + * @param outTradeNo 外部订单号 + * @param price 金额 + */ + PayWalletTransactionDO pay(String outTradeNo, Integer price); + + /** + * 钱包支付退款 + * + * @param outRefundNo 外部退款号 + * @param refundPrice 退款金额 + * @param reason 退款原因 + */ + PayWalletTransactionDO refund(String outRefundNo, Integer refundPrice, String reason); + } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java index 7d29b613e6..6992d63f66 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java @@ -1,10 +1,27 @@ package cn.iocoder.yudao.module.pay.service.wallet; +import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; import cn.iocoder.yudao.module.pay.dal.mysql.wallet.PayWalletMapper; +import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO; +import cn.iocoder.yudao.module.pay.service.order.PayOrderService; +import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId; +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserType; +import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; +import static cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum.PAYMENT; +import static cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum.PAYMENT_REFUND; /** * 钱包 Service 实现类 @@ -12,13 +29,133 @@ import javax.annotation.Resource; * @author jason */ @Service +@Slf4j public class PayWalletServiceImpl implements PayWalletService { + /** + * 余额支付的 no 前缀 + */ + private static final String WALLET_PAY_NO_PREFIX = "WP"; + /** + * 余额退款的 no 前缀 + */ + private static final String WALLET_REFUND_NO_PREFIX = "WR"; + @Resource private PayWalletMapper payWalletMapper; + @Resource + private PayNoRedisDAO noRedisDAO; + + @Resource + private PayWalletTransactionService payWalletTransactionService; + @Resource + @Lazy + private PayOrderService payOrderService; + @Resource + @Lazy + private PayRefundService payRefundService; @Override public PayWalletDO getPayWallet(Long userId, Integer userType) { return payWalletMapper.selectByUserIdAndType(userId, userType); } + + // TODO @jason:可以做的更抽象一点;pay(bizType, bizId, price);reduceWalletBalance; + // TODO @jason:最好是,明确传入哪个 userId 或者 walletId; + @Override + @Transactional(rollbackFor = Exception.class) + public PayWalletTransactionDO pay(String outTradeNo, Integer price) { + // 1.1 判断支付交易拓展单是否存 + PayOrderExtensionDO orderExtension = payOrderService.getOrderExtensionByNo(outTradeNo); + if (orderExtension == null) { + throw exception(ORDER_EXTENSION_NOT_FOUND); + } + // 1.2 判断余额是否足够 + PayWalletDO payWallet = validatePayWallet(); + int afterBalance = payWallet.getBalance() - price; + if (afterBalance < 0) { + throw exception(WALLET_BALANCE_NOT_ENOUGH); + } + + // 2.1 扣除余额 + // TODO @jason:不要直接整个更新;而是 new 一个出来更新;然后要考虑并发,要 where 余额 > price,以及 - price + payWallet.setBalance(afterBalance); + payWallet.setTotalExpense(payWallet.getTotalExpense() + price); + payWalletMapper.updateById(payWallet); + + // 2.2 生成钱包流水 + String walletNo = noRedisDAO.generate(WALLET_PAY_NO_PREFIX); + PayWalletTransactionDO walletTransaction = new PayWalletTransactionDO().setWalletId(payWallet.getId()) + .setNo(walletNo).setAmount(price * -1).setBalance(afterBalance).setTransactionTime(LocalDateTime.now()) + .setBizId(orderExtension.getOrderId()).setBizType(PAYMENT.getType()); + payWalletTransactionService.createWalletTransaction(walletTransaction); + return walletTransaction; + } + + // TODO @jason:不要在 service 里去使用用户上下文,这样和 request 就耦合了。 + private PayWalletDO validatePayWallet() { + Long userId = getLoginUserId(); + Integer userType = getLoginUserType(); + PayWalletDO payWallet = getPayWallet(userId, userType); + if (payWallet == null) { + log.error("[validatePayWallet] 用户 {} 钱包不存在", userId); + throw exception(WALLET_NOT_FOUND); + } + return payWallet; + } + + // TODO @jason:可以做的更抽象一点;pay(bizType, bizId, price);addWalletBalance;这样,如果后续充值,应该也是能复用这个方法的; + @Override + @Transactional(rollbackFor = Exception.class) + public PayWalletTransactionDO refund(String outRefundNo, Integer refundPrice, String reason) { + // 1.1 判断退款单是否存在 + PayRefundDO payRefund = payRefundService.getRefundByNo(outRefundNo); + if (payRefund == null) { + throw exception(REFUND_NOT_FOUND); + } + // 1.2 校验是否可以退款 + PayWalletDO payWallet = validatePayWallet(); + validateWalletCanRefund(payRefund.getId(), payRefund.getChannelOrderNo(), payWallet.getId(), refundPrice); + + // TODO @jason:不要直接整个更新;而是 new 一个出来更新;然后要考虑并发,要 where 余额 + 金额 + Integer afterBalance = payWallet.getBalance() + refundPrice; + payWallet.setBalance(afterBalance); + payWallet.setTotalExpense(payWallet.getTotalExpense() + refundPrice * -1L); + payWalletMapper.updateById(payWallet); + + // 2.2 生成钱包流水 + String walletNo = noRedisDAO.generate(WALLET_REFUND_NO_PREFIX); + PayWalletTransactionDO newWalletTransaction = new PayWalletTransactionDO().setWalletId(payWallet.getId()) + .setNo(walletNo).setAmount(refundPrice).setBalance(afterBalance).setTransactionTime(LocalDateTime.now()) + .setBizId(payRefund.getId()).setBizType(PAYMENT_REFUND.getType()) + .setDescription(reason); + payWalletTransactionService.createWalletTransaction(newWalletTransaction); + return newWalletTransaction; + } + + /** + * 校验是否能退款 + * + * @param refundId 支付退款单 id + * @param walletPayNo 钱包支付 no + * @param walletId 钱包 id + */ + // TODO @jason:不要使用基本类型; + private void validateWalletCanRefund(long refundId, String walletPayNo, long walletId, int refundPrice) { + // 查询钱包支付交易 + PayWalletTransactionDO payWalletTransaction = payWalletTransactionService.getWalletTransactionByNo(walletPayNo); + if (payWalletTransaction == null) { + throw exception(WALLET_TRANSACTION_NOT_FOUND); + } + // 原来的支付金额 + int amount = payWalletTransaction.getAmount() * -1; // TODO @jason:直接 - payWalletTransaction.getAmount() 即可; + if (refundPrice != amount) { + throw exception(WALLET_REFUND_AMOUNT_ERROR); + } + PayWalletTransactionDO refundTransaction = payWalletTransactionService.getWalletTransaction(walletId, refundId, PAYMENT_REFUND); + if (refundTransaction != null) { + throw exception(WALLET_REFUND_EXIST); + } + } + } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionService.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionService.java index a9bc91ab59..e0714081bf 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionService.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionService.java @@ -1,23 +1,50 @@ package cn.iocoder.yudao.module.pay.service.wallet; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.AppPayWalletTransactionPageReqVO; +import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.transaction.AppPayWalletTransactionPageReqVO; import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; +import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; /** - * 钱包余额明细 Service 接口 + * 钱包余额流水 Service 接口 * * @author jason */ public interface PayWalletTransactionService { /** - * 查询钱包余额明细, 分页 + * 查询钱包余额流水分页 * - * @param userId 用户 id + * @param userId 用户编号 * @param userType 用户类型 * @param pageVO 分页查询参数 */ PageResult getWalletTransactionPage(Long userId, Integer userType, AppPayWalletTransactionPageReqVO pageVO); + + /** + * 新增钱包余额流水 + * + * @param payWalletTransaction 余额流水 + * @return id + */ + Long createWalletTransaction(PayWalletTransactionDO payWalletTransaction); + + /** + * 根据 no,获取钱包余流水 + * + * @param no 流水号 + */ + PayWalletTransactionDO getWalletTransactionByNo(String no); + + /** + * 获取钱包流水 + * + * @param walletId 钱包编号 + * @param bizId 业务编号 + * @param type 业务类型 + * @return 钱包流水 + */ + PayWalletTransactionDO getWalletTransaction(Long walletId, Long bizId, PayWalletBizTypeEnum type); + } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionServiceImpl.java index f574b779f1..e2338219d7 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionServiceImpl.java @@ -1,11 +1,11 @@ package cn.iocoder.yudao.module.pay.service.wallet; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.AppPayWalletTransactionPageReqVO; +import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.transaction.AppPayWalletTransactionPageReqVO; import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; import cn.iocoder.yudao.module.pay.dal.mysql.wallet.PayWalletTransactionMapper; -import cn.iocoder.yudao.module.pay.enums.member.WalletTransactionQueryTypeEnum; +import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -15,27 +15,45 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.WALLET_NOT_FOUND; /** - * 钱包余额明细 Service 实现类 + * 钱包流水 Service 实现类 * * @author jason */ @Service @Slf4j -public class PayWalletTransactionServiceImpl implements PayWalletTransactionService{ +public class PayWalletTransactionServiceImpl implements PayWalletTransactionService { + @Resource private PayWalletService payWalletService; + @Resource private PayWalletTransactionMapper payWalletTransactionMapper; @Override public PageResult getWalletTransactionPage(Long userId, Integer userType, AppPayWalletTransactionPageReqVO pageVO) { - PayWalletDO payWallet = payWalletService.getPayWallet(userId, userType); - if (payWallet == null) { - log.error("[pageWalletTransaction] 用户 {} 钱包不存在", userId); + PayWalletDO wallet = payWalletService.getPayWallet(userId, userType); + if (wallet == null) { + log.error("[getWalletTransactionPage][用户({}/{}) 钱包不存在", userId, userType); throw exception(WALLET_NOT_FOUND); } - return payWalletTransactionMapper.selectPageByWalletIdAndQueryType(payWallet.getId(), - WalletTransactionQueryTypeEnum.valueOf(pageVO.getType()), pageVO); + return payWalletTransactionMapper.selectPage(wallet.getId(), pageVO); } + + @Override + public Long createWalletTransaction(PayWalletTransactionDO payWalletTransaction) { + payWalletTransactionMapper.insert(payWalletTransaction); + return payWalletTransaction.getId(); + } + + @Override + public PayWalletTransactionDO getWalletTransactionByNo(String no) { + return payWalletTransactionMapper.selectByNo(no); + } + + @Override + public PayWalletTransactionDO getWalletTransaction(Long walletId, Long bizId, PayWalletBizTypeEnum type) { + return payWalletTransactionMapper.selectByWalletIdAndBiz(walletId, bizId, type.getType()); + } + }