From 4cb3b6926bbc1454d4c330c55d1314188563695c Mon Sep 17 00:00:00 2001 From: ranyu1998 <2772602769@qq.com> Date: Wed, 28 Feb 2024 13:24:44 +0800 Subject: [PATCH 1/4] feat(init): --- .gitignore | 26 +++ demo-web-adapter/pom.xml | 31 ++++ .../demo/mobile/CustomerMobileAdaptor.java | 11 ++ .../alibaba/demo/wap/CustomerWapAdaptor.java | 12 ++ .../alibaba/demo/web/CustomerController.java | 34 ++++ demo-web-app/pom.xml | 45 +++++ .../demo/customer/CustomerServiceImpl.java | 38 +++++ .../customer/executor/CustomerAddCmdExe.java | 23 +++ .../query/CustomerListByNameQryExe.java | 20 +++ .../alibaba/demo/order/OrderServiceImpl.java | 8 + .../demo/app/CustomerConvertorTest.java | 6 + .../demo/app/CustomerValidatorTest.java | 11 ++ demo-web-client/pom.xml | 25 +++ .../alibaba/demo/api/CustomerServiceI.java | 14 ++ .../com/alibaba/demo/dto/CustomerAddCmd.java | 11 ++ .../demo/dto/CustomerListByNameQry.java | 9 + .../alibaba/demo/dto/data/CustomerDTO.java | 17 ++ .../com/alibaba/demo/dto/data/ErrorCode.java | 21 +++ .../demo/dto/event/CustomerCreatedEvent.java | 23 +++ .../demo/dto/event/DomainEventConstant.java | 11 ++ demo-web-domain/pom.xml | 32 ++++ .../demo/domain/customer/CompanyType.java | 14 ++ .../alibaba/demo/domain/customer/Credit.java | 10 ++ .../demo/domain/customer/Customer.java | 38 +++++ .../demo/domain/customer/CustomerType.java | 14 ++ .../demo/domain/customer/SourceType.java | 12 ++ .../customer/domainservice/CreditChecker.java | 6 + .../customer/gateway/CreditGateway.java | 8 + .../customer/gateway/CustomerGateway.java | 7 + .../com/alibaba/demo/domain/order/Order.java | 5 + .../com/alibaba/demo/domain/package-info.java | 6 + .../demo/domain/CustomerEntityTest.java | 9 + demo-web-infrastructure/pom.xml | 39 +++++ .../alibaba/demo/config/DiamondConfig.java | 5 + .../demo/customer/CreditGatewayImpl.java | 10 ++ .../com/alibaba/demo/customer/CustomerDO.java | 12 ++ .../demo/customer/CustomerGatewayImpl.java | 19 +++ .../alibaba/demo/customer/CustomerMapper.java | 9 + .../alibaba/demo/order/OrderGatewayImpl.java | 5 + .../src/main/resources/logback-spring.xml | 35 ++++ .../resources/mybatis/customer-mapper.xml | 14 ++ .../main/resources/mybatis/mybatis-config.xml | 10 ++ .../demo/repository/CustomerMapperTest.java | 9 + .../src/test/resources/sample.properties | 0 pom.xml | 157 ++++++++++++++++++ start/pom.xml | 39 +++++ .../java/com/alibaba/demo/Application.java | 18 ++ .../src/main/resources/application.properties | 7 + start/src/main/resources/logback-spring.xml | 49 ++++++ .../com/alibaba/demo/TestApplication.java | 11 ++ .../demo/test/CustomerServiceTest.java | 63 +++++++ start/src/test/resources/logback-test.xml | 49 ++++++ start/src/test/resources/test.properties | 23 +++ 53 files changed, 1140 insertions(+) create mode 100644 .gitignore create mode 100644 demo-web-adapter/pom.xml create mode 100644 demo-web-adapter/src/main/java/com/alibaba/demo/mobile/CustomerMobileAdaptor.java create mode 100644 demo-web-adapter/src/main/java/com/alibaba/demo/wap/CustomerWapAdaptor.java create mode 100644 demo-web-adapter/src/main/java/com/alibaba/demo/web/CustomerController.java create mode 100644 demo-web-app/pom.xml create mode 100644 demo-web-app/src/main/java/com/alibaba/demo/customer/CustomerServiceImpl.java create mode 100644 demo-web-app/src/main/java/com/alibaba/demo/customer/executor/CustomerAddCmdExe.java create mode 100644 demo-web-app/src/main/java/com/alibaba/demo/customer/executor/query/CustomerListByNameQryExe.java create mode 100644 demo-web-app/src/main/java/com/alibaba/demo/order/OrderServiceImpl.java create mode 100644 demo-web-app/src/test/java/com/alibaba/demo/app/CustomerConvertorTest.java create mode 100644 demo-web-app/src/test/java/com/alibaba/demo/app/CustomerValidatorTest.java create mode 100644 demo-web-client/pom.xml create mode 100644 demo-web-client/src/main/java/com/alibaba/demo/api/CustomerServiceI.java create mode 100644 demo-web-client/src/main/java/com/alibaba/demo/dto/CustomerAddCmd.java create mode 100644 demo-web-client/src/main/java/com/alibaba/demo/dto/CustomerListByNameQry.java create mode 100644 demo-web-client/src/main/java/com/alibaba/demo/dto/data/CustomerDTO.java create mode 100644 demo-web-client/src/main/java/com/alibaba/demo/dto/data/ErrorCode.java create mode 100644 demo-web-client/src/main/java/com/alibaba/demo/dto/event/CustomerCreatedEvent.java create mode 100644 demo-web-client/src/main/java/com/alibaba/demo/dto/event/DomainEventConstant.java create mode 100644 demo-web-domain/pom.xml create mode 100644 demo-web-domain/src/main/java/com/alibaba/demo/domain/customer/CompanyType.java create mode 100644 demo-web-domain/src/main/java/com/alibaba/demo/domain/customer/Credit.java create mode 100644 demo-web-domain/src/main/java/com/alibaba/demo/domain/customer/Customer.java create mode 100644 demo-web-domain/src/main/java/com/alibaba/demo/domain/customer/CustomerType.java create mode 100644 demo-web-domain/src/main/java/com/alibaba/demo/domain/customer/SourceType.java create mode 100644 demo-web-domain/src/main/java/com/alibaba/demo/domain/customer/domainservice/CreditChecker.java create mode 100644 demo-web-domain/src/main/java/com/alibaba/demo/domain/customer/gateway/CreditGateway.java create mode 100644 demo-web-domain/src/main/java/com/alibaba/demo/domain/customer/gateway/CustomerGateway.java create mode 100644 demo-web-domain/src/main/java/com/alibaba/demo/domain/order/Order.java create mode 100644 demo-web-domain/src/main/java/com/alibaba/demo/domain/package-info.java create mode 100644 demo-web-domain/src/test/java/com/alibaba/demo/domain/CustomerEntityTest.java create mode 100644 demo-web-infrastructure/pom.xml create mode 100644 demo-web-infrastructure/src/main/java/com/alibaba/demo/config/DiamondConfig.java create mode 100644 demo-web-infrastructure/src/main/java/com/alibaba/demo/customer/CreditGatewayImpl.java create mode 100644 demo-web-infrastructure/src/main/java/com/alibaba/demo/customer/CustomerDO.java create mode 100644 demo-web-infrastructure/src/main/java/com/alibaba/demo/customer/CustomerGatewayImpl.java create mode 100644 demo-web-infrastructure/src/main/java/com/alibaba/demo/customer/CustomerMapper.java create mode 100644 demo-web-infrastructure/src/main/java/com/alibaba/demo/order/OrderGatewayImpl.java create mode 100644 demo-web-infrastructure/src/main/resources/logback-spring.xml create mode 100644 demo-web-infrastructure/src/main/resources/mybatis/customer-mapper.xml create mode 100644 demo-web-infrastructure/src/main/resources/mybatis/mybatis-config.xml create mode 100644 demo-web-infrastructure/src/test/java/com/alibaba/demo/repository/CustomerMapperTest.java create mode 100644 demo-web-infrastructure/src/test/resources/sample.properties create mode 100644 pom.xml create mode 100644 start/pom.xml create mode 100644 start/src/main/java/com/alibaba/demo/Application.java create mode 100644 start/src/main/resources/application.properties create mode 100644 start/src/main/resources/logback-spring.xml create mode 100644 start/src/test/java/com/alibaba/demo/TestApplication.java create mode 100644 start/src/test/java/com/alibaba/demo/test/CustomerServiceTest.java create mode 100644 start/src/test/resources/logback-test.xml create mode 100644 start/src/test/resources/test.properties diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..be72375 --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +target/ + +### eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr +out/ + +### NetBeans ### +nbproject/private/ +build/ +nbbuild/ +dist/ +nbdist/ +bin/ +doc/ +.DS_Store diff --git a/demo-web-adapter/pom.xml b/demo-web-adapter/pom.xml new file mode 100644 index 0000000..5969745 --- /dev/null +++ b/demo-web-adapter/pom.xml @@ -0,0 +1,31 @@ + + + 4.0.0 + + com.alibaba.cola.demo.web + demo-web-parent + 1.0.0-SNAPSHOT + ../pom.xml + + + demo-web-adapter + jar + demo-web-adapter + + + + com.alibaba.cola.demo.web + demo-web-app + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + diff --git a/demo-web-adapter/src/main/java/com/alibaba/demo/mobile/CustomerMobileAdaptor.java b/demo-web-adapter/src/main/java/com/alibaba/demo/mobile/CustomerMobileAdaptor.java new file mode 100644 index 0000000..50ab17a --- /dev/null +++ b/demo-web-adapter/src/main/java/com/alibaba/demo/mobile/CustomerMobileAdaptor.java @@ -0,0 +1,11 @@ +package com.alibaba.demo.mobile; + +/** + * Customer Mobile Adaptor + * + * + * @author Frank Zhang + * @date 2020-10-27 8:04 PM + */ +public class CustomerMobileAdaptor { +} diff --git a/demo-web-adapter/src/main/java/com/alibaba/demo/wap/CustomerWapAdaptor.java b/demo-web-adapter/src/main/java/com/alibaba/demo/wap/CustomerWapAdaptor.java new file mode 100644 index 0000000..5ede913 --- /dev/null +++ b/demo-web-adapter/src/main/java/com/alibaba/demo/wap/CustomerWapAdaptor.java @@ -0,0 +1,12 @@ +package com.alibaba.demo.wap; + +/** + * Customer Wap Adaptor + * + * WAP : Wireless Application Protocol) + * + * @author Frank Zhang + * @date 2020-10-27 8:03 PM + */ +public class CustomerWapAdaptor { +} diff --git a/demo-web-adapter/src/main/java/com/alibaba/demo/web/CustomerController.java b/demo-web-adapter/src/main/java/com/alibaba/demo/web/CustomerController.java new file mode 100644 index 0000000..01bd9ef --- /dev/null +++ b/demo-web-adapter/src/main/java/com/alibaba/demo/web/CustomerController.java @@ -0,0 +1,34 @@ +package com.alibaba.demo.web; + +import com.alibaba.cola.dto.MultiResponse; +import com.alibaba.cola.dto.Response; +import com.alibaba.demo.api.CustomerServiceI; +import com.alibaba.demo.dto.CustomerAddCmd; +import com.alibaba.demo.dto.CustomerListByNameQry; +import com.alibaba.demo.dto.data.CustomerDTO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@RestController +public class CustomerController { + + @Autowired + private CustomerServiceI customerService; + + @GetMapping(value = "/helloworld") + public String helloWorld(){ + return "Hello, welcome to COLA world!"; + } + + @GetMapping(value = "/customer") + public MultiResponse listCustomerByName(@RequestParam(required = false) String name){ + CustomerListByNameQry customerListByNameQry = new CustomerListByNameQry(); + customerListByNameQry.setName(name); + return customerService.listByName(customerListByNameQry); + } + + @PostMapping(value = "/customer") + public Response addCustomer(@RequestBody CustomerAddCmd customerAddCmd){ + return customerService.addCustomer(customerAddCmd); + } +} diff --git a/demo-web-app/pom.xml b/demo-web-app/pom.xml new file mode 100644 index 0000000..a1f9354 --- /dev/null +++ b/demo-web-app/pom.xml @@ -0,0 +1,45 @@ + + + 4.0.0 + + com.alibaba.cola.demo.web + demo-web-parent + 1.0.0-SNAPSHOT + ../pom.xml + + + demo-web-app + jar + demo-web-app + + + + com.alibaba.cola.demo.web + demo-web-client + + + com.alibaba.cola.demo.web + demo-web-infrastructure + + + + com.alibaba.cola + cola-component-catchlog-starter + + + + + org.hibernate.validator + hibernate-validator + + + javax.el + javax.el-api + + + org.glassfish + jakarta.el + + + + diff --git a/demo-web-app/src/main/java/com/alibaba/demo/customer/CustomerServiceImpl.java b/demo-web-app/src/main/java/com/alibaba/demo/customer/CustomerServiceImpl.java new file mode 100644 index 0000000..b64cab0 --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/customer/CustomerServiceImpl.java @@ -0,0 +1,38 @@ +package com.alibaba.demo.customer; + +import com.alibaba.cola.dto.MultiResponse; +import com.alibaba.cola.dto.Response; +import com.alibaba.cola.catchlog.CatchAndLog; +import com.alibaba.demo.api.CustomerServiceI; +import com.alibaba.demo.dto.CustomerAddCmd; +import com.alibaba.demo.dto.CustomerListByNameQry; +import com.alibaba.demo.dto.data.CustomerDTO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.alibaba.demo.customer.executor.CustomerAddCmdExe; +import com.alibaba.demo.customer.executor.query.CustomerListByNameQryExe; + +import javax.annotation.Resource; + + +@Service +@CatchAndLog +public class CustomerServiceImpl implements CustomerServiceI { + + @Resource + private CustomerAddCmdExe customerAddCmdExe; + + @Resource + private CustomerListByNameQryExe customerListByNameQryExe; + + public Response addCustomer(CustomerAddCmd customerAddCmd) { + return customerAddCmdExe.execute(customerAddCmd); + } + + @Override + public MultiResponse listByName(CustomerListByNameQry customerListByNameQry) { + return customerListByNameQryExe.execute(customerListByNameQry); + } + +} \ No newline at end of file diff --git a/demo-web-app/src/main/java/com/alibaba/demo/customer/executor/CustomerAddCmdExe.java b/demo-web-app/src/main/java/com/alibaba/demo/customer/executor/CustomerAddCmdExe.java new file mode 100644 index 0000000..14e52cc --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/customer/executor/CustomerAddCmdExe.java @@ -0,0 +1,23 @@ + +package com.alibaba.demo.customer.executor; + +import com.alibaba.cola.dto.Response; +import com.alibaba.cola.exception.BizException; +import com.alibaba.demo.dto.CustomerAddCmd; +import com.alibaba.demo.dto.data.ErrorCode; +import org.springframework.stereotype.Component; + + +@Component +public class CustomerAddCmdExe{ + + public Response execute(CustomerAddCmd cmd) { + //The flow of usecase is defined here. + //The core ablility should be implemented in Domain. or sink to Domian gradually + if(cmd.getCustomerDTO().getCompanyName().equals("ConflictCompanyName")){ + throw new BizException(ErrorCode.B_CUSTOMER_companyNameConflict.getErrCode(), "公司名冲突"); + } + return Response.buildSuccess(); + } + +} diff --git a/demo-web-app/src/main/java/com/alibaba/demo/customer/executor/query/CustomerListByNameQryExe.java b/demo-web-app/src/main/java/com/alibaba/demo/customer/executor/query/CustomerListByNameQryExe.java new file mode 100644 index 0000000..4fc00ff --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/customer/executor/query/CustomerListByNameQryExe.java @@ -0,0 +1,20 @@ +package com.alibaba.demo.customer.executor.query; + +import com.alibaba.cola.dto.MultiResponse; +import com.alibaba.demo.dto.CustomerListByNameQry; +import com.alibaba.demo.dto.data.CustomerDTO; +import java.util.ArrayList; +import java.util.List; +import org.springframework.stereotype.Component; + + +@Component +public class CustomerListByNameQryExe{ + public MultiResponse execute(CustomerListByNameQry cmd) { + List customerDTOList = new ArrayList<>(); + CustomerDTO customerDTO = new CustomerDTO(); + customerDTO.setCustomerName("Frank"); + customerDTOList.add(customerDTO); + return MultiResponse.of(customerDTOList); + } +} diff --git a/demo-web-app/src/main/java/com/alibaba/demo/order/OrderServiceImpl.java b/demo-web-app/src/main/java/com/alibaba/demo/order/OrderServiceImpl.java new file mode 100644 index 0000000..c25fa3a --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/order/OrderServiceImpl.java @@ -0,0 +1,8 @@ +package com.alibaba.demo.order; + +//package by domain, not by duty + + +public class OrderServiceImpl{ + +} \ No newline at end of file diff --git a/demo-web-app/src/test/java/com/alibaba/demo/app/CustomerConvertorTest.java b/demo-web-app/src/test/java/com/alibaba/demo/app/CustomerConvertorTest.java new file mode 100644 index 0000000..612f3a3 --- /dev/null +++ b/demo-web-app/src/test/java/com/alibaba/demo/app/CustomerConvertorTest.java @@ -0,0 +1,6 @@ +package com.alibaba.demo.app; + + +public class CustomerConvertorTest { + +} diff --git a/demo-web-app/src/test/java/com/alibaba/demo/app/CustomerValidatorTest.java b/demo-web-app/src/test/java/com/alibaba/demo/app/CustomerValidatorTest.java new file mode 100644 index 0000000..a2fec49 --- /dev/null +++ b/demo-web-app/src/test/java/com/alibaba/demo/app/CustomerValidatorTest.java @@ -0,0 +1,11 @@ +package com.alibaba.demo.app; + +import org.junit.Test; + +public class CustomerValidatorTest { + + @Test + public void testValidation(){ + + } +} diff --git a/demo-web-client/pom.xml b/demo-web-client/pom.xml new file mode 100644 index 0000000..43f8c90 --- /dev/null +++ b/demo-web-client/pom.xml @@ -0,0 +1,25 @@ + + + 4.0.0 + + com.alibaba.cola.demo.web + demo-web-parent + 1.0.0-SNAPSHOT + ../pom.xml + + + demo-web-client + jar + demo-web-client + + + + com.alibaba.cola + cola-component-dto + + + javax.validation + validation-api + + + diff --git a/demo-web-client/src/main/java/com/alibaba/demo/api/CustomerServiceI.java b/demo-web-client/src/main/java/com/alibaba/demo/api/CustomerServiceI.java new file mode 100644 index 0000000..72c18be --- /dev/null +++ b/demo-web-client/src/main/java/com/alibaba/demo/api/CustomerServiceI.java @@ -0,0 +1,14 @@ +package com.alibaba.demo.api; + +import com.alibaba.cola.dto.MultiResponse; +import com.alibaba.cola.dto.Response; +import com.alibaba.demo.dto.CustomerAddCmd; +import com.alibaba.demo.dto.CustomerListByNameQry; +import com.alibaba.demo.dto.data.CustomerDTO; + +public interface CustomerServiceI { + + Response addCustomer(CustomerAddCmd customerAddCmd); + + MultiResponse listByName(CustomerListByNameQry customerListByNameQry); +} diff --git a/demo-web-client/src/main/java/com/alibaba/demo/dto/CustomerAddCmd.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/CustomerAddCmd.java new file mode 100644 index 0000000..b048429 --- /dev/null +++ b/demo-web-client/src/main/java/com/alibaba/demo/dto/CustomerAddCmd.java @@ -0,0 +1,11 @@ +package com.alibaba.demo.dto; + +import com.alibaba.demo.dto.data.CustomerDTO; +import lombok.Data; + +@Data +public class CustomerAddCmd{ + + private CustomerDTO customerDTO; + +} diff --git a/demo-web-client/src/main/java/com/alibaba/demo/dto/CustomerListByNameQry.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/CustomerListByNameQry.java new file mode 100644 index 0000000..0e0b2cb --- /dev/null +++ b/demo-web-client/src/main/java/com/alibaba/demo/dto/CustomerListByNameQry.java @@ -0,0 +1,9 @@ +package com.alibaba.demo.dto; + +import com.alibaba.cola.dto.Query; +import lombok.Data; + +@Data +public class CustomerListByNameQry extends Query{ + private String name; +} diff --git a/demo-web-client/src/main/java/com/alibaba/demo/dto/data/CustomerDTO.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/data/CustomerDTO.java new file mode 100644 index 0000000..53c4175 --- /dev/null +++ b/demo-web-client/src/main/java/com/alibaba/demo/dto/data/CustomerDTO.java @@ -0,0 +1,17 @@ +package com.alibaba.demo.dto.data; + +import lombok.Data; + +import javax.validation.constraints.NotEmpty; + +@Data +public class CustomerDTO{ + private String customerId; + private String memberId; + private String customerName; + private String customerType; + @NotEmpty + private String companyName; + @NotEmpty + private String source; +} diff --git a/demo-web-client/src/main/java/com/alibaba/demo/dto/data/ErrorCode.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/data/ErrorCode.java new file mode 100644 index 0000000..caa46e0 --- /dev/null +++ b/demo-web-client/src/main/java/com/alibaba/demo/dto/data/ErrorCode.java @@ -0,0 +1,21 @@ +package com.alibaba.demo.dto.data; + +public enum ErrorCode{ + B_CUSTOMER_companyNameConflict("B_CUSTOMER_companyNameConflict", "客户公司名冲突"); + + private final String errCode; + private final String errDesc; + + private ErrorCode(String errCode, String errDesc) { + this.errCode = errCode; + this.errDesc = errDesc; + } + + public String getErrCode() { + return errCode; + } + + public String getErrDesc() { + return errDesc; + } +} diff --git a/demo-web-client/src/main/java/com/alibaba/demo/dto/event/CustomerCreatedEvent.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/event/CustomerCreatedEvent.java new file mode 100644 index 0000000..acd359a --- /dev/null +++ b/demo-web-client/src/main/java/com/alibaba/demo/dto/event/CustomerCreatedEvent.java @@ -0,0 +1,23 @@ +package com.alibaba.demo.dto.event; + +import static com.alibaba.demo.dto.event.DomainEventConstant.CUSTOMER_CREATED_TOPIC; + +/** + * CustomerCreatedEvent + * + * @author Frank Zhang + * @date 2019-01-04 10:32 AM + */ +public class CustomerCreatedEvent{ + + private String customerId; + + public String getCustomerId() { + return customerId; + } + + public void setCustomerId(String customerId) { + this.customerId = customerId; + } + +} diff --git a/demo-web-client/src/main/java/com/alibaba/demo/dto/event/DomainEventConstant.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/event/DomainEventConstant.java new file mode 100644 index 0000000..569ec5b --- /dev/null +++ b/demo-web-client/src/main/java/com/alibaba/demo/dto/event/DomainEventConstant.java @@ -0,0 +1,11 @@ +package com.alibaba.demo.dto.event; + +/** + * @author niexiaolong + * @date 2019/4/16 + */ +public class DomainEventConstant { + + public static final String CUSTOMER_CREATED_TOPIC = "CRM_CUSTOMER_CREATED_DOMAIN_EVENT_TOPIC"; + +} diff --git a/demo-web-domain/pom.xml b/demo-web-domain/pom.xml new file mode 100644 index 0000000..a1740c9 --- /dev/null +++ b/demo-web-domain/pom.xml @@ -0,0 +1,32 @@ + + + 4.0.0 + + com.alibaba.cola.demo.web + demo-web-parent + 1.0.0-SNAPSHOT + ../pom.xml + + + demo-web-domain + jar + demo-web-domain + + + + com.alibaba.cola.demo.web + demo-web-client + + + + + com.alibaba.cola + cola-component-domain-starter + + + com.alibaba.cola + cola-component-exception + + + + diff --git a/demo-web-domain/src/main/java/com/alibaba/demo/domain/customer/CompanyType.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/customer/CompanyType.java new file mode 100644 index 0000000..239fe2c --- /dev/null +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/customer/CompanyType.java @@ -0,0 +1,14 @@ +package com.alibaba.demo.domain.customer; + +/** + * CompanyType + * + * @author Frank Zhang + * @date 2018-01-08 11:02 AM + */ +public enum CompanyType { + POTENTIAL, + INTENTIONAL, + IMPORTANT, + VIP; +} diff --git a/demo-web-domain/src/main/java/com/alibaba/demo/domain/customer/Credit.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/customer/Credit.java new file mode 100644 index 0000000..a32190a --- /dev/null +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/customer/Credit.java @@ -0,0 +1,10 @@ +package com.alibaba.demo.domain.customer; + +import com.alibaba.cola.domain.Entity; +import lombok.Data; + +@Data +@Entity +public class Credit{ + +} diff --git a/demo-web-domain/src/main/java/com/alibaba/demo/domain/customer/Customer.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/customer/Customer.java new file mode 100644 index 0000000..b52c145 --- /dev/null +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/customer/Customer.java @@ -0,0 +1,38 @@ +package com.alibaba.demo.domain.customer; + +import com.alibaba.cola.domain.Entity; +import com.alibaba.cola.exception.BizException; +import lombok.Data; + +//Domain Entity can choose to extend the domain model which is used for DTO +@Data +@Entity +public class Customer{ + + private String customerId; + private String memberId; + private String globalId; + private long registeredCapital; + private String companyName; + private SourceType sourceType; + private CompanyType companyType; + + public Customer() { + } + + public boolean isBigCompany() { + return registeredCapital > 10000000; //注册资金大于1000万的是大企业 + } + + public boolean isSME() { + return registeredCapital > 10000 && registeredCapital < 1000000; //注册资金大于10万小于100万的为中小企业 + } + + public void checkConflict(){ + //Per different biz, the check policy could be different, if so, use ExtensionPoint + if("ConflictCompanyName".equals(this.companyName)){ + throw new BizException(this.companyName+" has already existed, you can not add it"); + } + + } +} diff --git a/demo-web-domain/src/main/java/com/alibaba/demo/domain/customer/CustomerType.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/customer/CustomerType.java new file mode 100644 index 0000000..0739dbd --- /dev/null +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/customer/CustomerType.java @@ -0,0 +1,14 @@ +package com.alibaba.demo.domain.customer; + +/** + * CustomerType + * + * @author Frank Zhang + * @date 2018-01-08 8:51 AM + */ +public enum CustomerType { + POTENTIAL, + INTENTIONAL, + IMPORTANT, + VIP; +} diff --git a/demo-web-domain/src/main/java/com/alibaba/demo/domain/customer/SourceType.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/customer/SourceType.java new file mode 100644 index 0000000..825e5f4 --- /dev/null +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/customer/SourceType.java @@ -0,0 +1,12 @@ +package com.alibaba.demo.domain.customer; + +/** + * SourceType + * + * @author Frank Zhang + * @date 2018-01-08 11:09 AM + */ +public enum SourceType { + BIZ_ONE, //From biz one + BIZ_TWO; //From biz two +} diff --git a/demo-web-domain/src/main/java/com/alibaba/demo/domain/customer/domainservice/CreditChecker.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/customer/domainservice/CreditChecker.java new file mode 100644 index 0000000..8c64697 --- /dev/null +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/customer/domainservice/CreditChecker.java @@ -0,0 +1,6 @@ +package com.alibaba.demo.domain.customer.domainservice; + +//The domain's ability can also be placed here +public class CreditChecker{ + +} diff --git a/demo-web-domain/src/main/java/com/alibaba/demo/domain/customer/gateway/CreditGateway.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/customer/gateway/CreditGateway.java new file mode 100644 index 0000000..c9cfc79 --- /dev/null +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/customer/gateway/CreditGateway.java @@ -0,0 +1,8 @@ +package com.alibaba.demo.domain.customer.gateway; + +import com.alibaba.demo.domain.customer.Credit; + +//Assume that the credit info is in another distributed Service +public interface CreditGateway { + Credit getCredit(String customerId); +} diff --git a/demo-web-domain/src/main/java/com/alibaba/demo/domain/customer/gateway/CustomerGateway.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/customer/gateway/CustomerGateway.java new file mode 100644 index 0000000..5abf2c5 --- /dev/null +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/customer/gateway/CustomerGateway.java @@ -0,0 +1,7 @@ +package com.alibaba.demo.domain.customer.gateway; + +import com.alibaba.demo.domain.customer.Customer; + +public interface CustomerGateway { + Customer getByById(String customerId); +} diff --git a/demo-web-domain/src/main/java/com/alibaba/demo/domain/order/Order.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/order/Order.java new file mode 100644 index 0000000..f3d7832 --- /dev/null +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/order/Order.java @@ -0,0 +1,5 @@ +package com.alibaba.demo.domain.order; + +public class Order{ + +} diff --git a/demo-web-domain/src/main/java/com/alibaba/demo/domain/package-info.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/package-info.java new file mode 100644 index 0000000..08180c9 --- /dev/null +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/package-info.java @@ -0,0 +1,6 @@ +/** + * This is domain module, the core business logic is implemented here. + * + * @author fulan.zjf + */ +package com.alibaba.demo.domain; \ No newline at end of file diff --git a/demo-web-domain/src/test/java/com/alibaba/demo/domain/CustomerEntityTest.java b/demo-web-domain/src/test/java/com/alibaba/demo/domain/CustomerEntityTest.java new file mode 100644 index 0000000..862acfe --- /dev/null +++ b/demo-web-domain/src/test/java/com/alibaba/demo/domain/CustomerEntityTest.java @@ -0,0 +1,9 @@ +package com.alibaba.demo.domain; + + +public class CustomerEntityTest { + + public void testCustomerConflict() { + System.out.println("Please mock gatewayimpl, test pure Domain Knowledge"); + } +} diff --git a/demo-web-infrastructure/pom.xml b/demo-web-infrastructure/pom.xml new file mode 100644 index 0000000..d8a0f13 --- /dev/null +++ b/demo-web-infrastructure/pom.xml @@ -0,0 +1,39 @@ + + + 4.0.0 + + com.alibaba.cola.demo.web + demo-web-parent + 1.0.0-SNAPSHOT + ../pom.xml + + + demo-web-infrastructure + jar + demo-web-infrastructure + + + + com.alibaba.cola.demo.web + demo-web-domain + + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + + + mysql + mysql-connector-java + + + com.alibaba + fastjson + + + org.springframework.boot + spring-boot-starter-test + test + + + diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/config/DiamondConfig.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/config/DiamondConfig.java new file mode 100644 index 0000000..0020c1f --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/config/DiamondConfig.java @@ -0,0 +1,5 @@ +package com.alibaba.demo.config; + +public class DiamondConfig { + public final static String DummyConfig = "DummyConfig"; +} \ No newline at end of file diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/customer/CreditGatewayImpl.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/customer/CreditGatewayImpl.java new file mode 100644 index 0000000..aa92d72 --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/customer/CreditGatewayImpl.java @@ -0,0 +1,10 @@ +package com.alibaba.demo.customer; + +import com.alibaba.demo.domain.customer.Credit; +import com.alibaba.demo.domain.customer.gateway.CreditGateway; + +public class CreditGatewayImpl implements CreditGateway { + public Credit getCredit(String customerId){ + return null; + } +} diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/customer/CustomerDO.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/customer/CustomerDO.java new file mode 100644 index 0000000..cb1b48f --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/customer/CustomerDO.java @@ -0,0 +1,12 @@ +package com.alibaba.demo.customer; + +import lombok.Data; + +@Data +public class CustomerDO{ + private String customerId; + private String memberId; + private String globalId; + private long registeredCapital; + private String companyName; +} diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/customer/CustomerGatewayImpl.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/customer/CustomerGatewayImpl.java new file mode 100644 index 0000000..058f89c --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/customer/CustomerGatewayImpl.java @@ -0,0 +1,19 @@ +package com.alibaba.demo.customer; + +import com.alibaba.demo.domain.customer.Customer; +import com.alibaba.demo.domain.customer.gateway.CustomerGateway; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class CustomerGatewayImpl implements CustomerGateway { + @Autowired + private CustomerMapper customerMapper; + + public Customer getByById(String customerId){ + CustomerDO customerDO = customerMapper.getById(customerId); + //Convert to Customer + return null; + } +} diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/customer/CustomerMapper.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/customer/CustomerMapper.java new file mode 100644 index 0000000..2ed962d --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/customer/CustomerMapper.java @@ -0,0 +1,9 @@ +package com.alibaba.demo.customer; + +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface CustomerMapper{ + + CustomerDO getById(String customerId); +} diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/order/OrderGatewayImpl.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/order/OrderGatewayImpl.java new file mode 100644 index 0000000..1d9e43a --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/order/OrderGatewayImpl.java @@ -0,0 +1,5 @@ +package com.alibaba.demo.order; + +public class OrderGatewayImpl{ + +} diff --git a/demo-web-infrastructure/src/main/resources/logback-spring.xml b/demo-web-infrastructure/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..38a1553 --- /dev/null +++ b/demo-web-infrastructure/src/main/resources/logback-spring.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + ${LOG_FILE} + + ${FILE_LOG_PATTERN} + + + ${LOG_FILE}.%d{yyyy-MM-dd}.%i.log + 7 + 50MB + 20GB + + + + + + ${CONSOLE_LOG_PATTERN} + utf8 + + + + + + + + diff --git a/demo-web-infrastructure/src/main/resources/mybatis/customer-mapper.xml b/demo-web-infrastructure/src/main/resources/mybatis/customer-mapper.xml new file mode 100644 index 0000000..46d7b8d --- /dev/null +++ b/demo-web-infrastructure/src/main/resources/mybatis/customer-mapper.xml @@ -0,0 +1,14 @@ + + + + + + + + + + diff --git a/demo-web-infrastructure/src/main/resources/mybatis/mybatis-config.xml b/demo-web-infrastructure/src/main/resources/mybatis/mybatis-config.xml new file mode 100644 index 0000000..f7c8d88 --- /dev/null +++ b/demo-web-infrastructure/src/main/resources/mybatis/mybatis-config.xml @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/demo-web-infrastructure/src/test/java/com/alibaba/demo/repository/CustomerMapperTest.java b/demo-web-infrastructure/src/test/java/com/alibaba/demo/repository/CustomerMapperTest.java new file mode 100644 index 0000000..8f03c29 --- /dev/null +++ b/demo-web-infrastructure/src/test/java/com/alibaba/demo/repository/CustomerMapperTest.java @@ -0,0 +1,9 @@ +package com.alibaba.demo.repository; + + +public class CustomerMapperTest { + + public void testFindByID() { + System.out.println("Write your test here"); + } +} diff --git a/demo-web-infrastructure/src/test/resources/sample.properties b/demo-web-infrastructure/src/test/resources/sample.properties new file mode 100644 index 0000000..e69de29 diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..8a8c57d --- /dev/null +++ b/pom.xml @@ -0,0 +1,157 @@ + + + 4.0.0 + + cola-dummy-aggregation-parent + com.alibaba.cola + dummy-SNAPSHOT + + + com.alibaba.cola.demo.web + demo-web-parent + 1.0.0-SNAPSHOT + pom + demo-web + + + 1.8 + ${maven.compiler.source} + UTF-8 + UTF-8 + true + + 4.3.2 + + 2.7.2 + 2.2.2 + + + + demo-web-client + demo-web-adapter + demo-web-app + demo-web-domain + demo-web-infrastructure + start + + + + + org.projectlombok + lombok + provided + + + junit + junit + test + + + + + + + + com.alibaba.cola.demo.web + demo-web-adapter + ${project.version} + + + com.alibaba.cola.demo.web + demo-web-client + ${project.version} + + + com.alibaba.cola.demo.web + demo-web-app + ${project.version} + + + com.alibaba.cola.demo.web + demo-web-domain + ${project.version} + + + com.alibaba.cola.demo.web + demo-web-infrastructure + ${project.version} + + + + + com.alibaba.cola + cola-components-bom + ${cola.components.version} + pom + import + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + ${mybatis-starter.version} + + + + + + javax.el + javax.el-api + 3.0.0 + + + + + + com.alibaba + fastjson + 1.2.83 + + + + + + + + + + maven-resources-plugin + 3.3.0 + + + maven-compiler-plugin + 3.10.1 + + + maven-source-plugin + 3.2.1 + + + maven-javadoc-plugin + 3.4.0 + + + maven-deploy-plugin + 3.0.0 + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + + + + diff --git a/start/pom.xml b/start/pom.xml new file mode 100644 index 0000000..7a4d930 --- /dev/null +++ b/start/pom.xml @@ -0,0 +1,39 @@ + + + 4.0.0 + + com.alibaba.cola.demo.web + demo-web-parent + 1.0.0-SNAPSHOT + ../pom.xml + + + start + jar + start + + + + com.alibaba.cola.demo.web + demo-web-adapter + + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-test + test + + + diff --git a/start/src/main/java/com/alibaba/demo/Application.java b/start/src/main/java/com/alibaba/demo/Application.java new file mode 100644 index 0000000..d74c6f5 --- /dev/null +++ b/start/src/main/java/com/alibaba/demo/Application.java @@ -0,0 +1,18 @@ +package com.alibaba.demo; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * Spring Boot Starter + * + * @author Frank Zhang + */ +@SpringBootApplication(scanBasePackages = {"com.alibaba.demo", "com.alibaba.cola"}) +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/start/src/main/resources/application.properties b/start/src/main/resources/application.properties new file mode 100644 index 0000000..12ae3de --- /dev/null +++ b/start/src/main/resources/application.properties @@ -0,0 +1,7 @@ +project.name=start +server.port=18080 + +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver +spring.datasource.url=jdbc:mysql://localhost:3306/lotteryDemo +spring.datasource.username=root +spring.datasource.password=123456 diff --git a/start/src/main/resources/logback-spring.xml b/start/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..b4d90e2 --- /dev/null +++ b/start/src/main/resources/logback-spring.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + ${LOG_FILE} + + ${FILE_LOG_PATTERN} + + + ${LOG_FILE}.%d{yyyy-MM-dd}.%i.log + 7 + 50MB + 20GB + + + + + + ${CONSOLE_LOG_PATTERN} + utf8 + + + + + + + + + + + + + + + + + + + + + + diff --git a/start/src/test/java/com/alibaba/demo/TestApplication.java b/start/src/test/java/com/alibaba/demo/TestApplication.java new file mode 100644 index 0000000..0bf4fcb --- /dev/null +++ b/start/src/test/java/com/alibaba/demo/TestApplication.java @@ -0,0 +1,11 @@ +package com.alibaba.demo; + +import org.springframework.boot.SpringApplication; +import org.springframework.context.ApplicationContext; + +public class TestApplication { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/start/src/test/java/com/alibaba/demo/test/CustomerServiceTest.java b/start/src/test/java/com/alibaba/demo/test/CustomerServiceTest.java new file mode 100644 index 0000000..9016472 --- /dev/null +++ b/start/src/test/java/com/alibaba/demo/test/CustomerServiceTest.java @@ -0,0 +1,63 @@ +package com.alibaba.demo.test; + +import com.alibaba.cola.dto.Response; +import com.alibaba.demo.api.CustomerServiceI; +import com.alibaba.demo.dto.CustomerAddCmd; +import com.alibaba.demo.dto.data.CustomerDTO; +import com.alibaba.demo.dto.data.ErrorCode; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +/** + * This is for integration test. + * + * Created by fulan.zjf on 2017/11/29. + */ +@RunWith(SpringRunner.class) +@SpringBootTest +public class CustomerServiceTest { + + @Autowired + private CustomerServiceI customerService; + + + @Before + public void setUp() { + + } + + @Test + public void testCustomerAddSuccess(){ + //1.prepare + CustomerAddCmd customerAddCmd = new CustomerAddCmd(); + CustomerDTO customerDTO = new CustomerDTO(); + customerDTO.setCompanyName("NormalName"); + customerAddCmd.setCustomerDTO(customerDTO); + + //2.execute + Response response = customerService.addCustomer(customerAddCmd); + + //3.assert + Assert.assertTrue(response.isSuccess()); + } + + @Test + public void testCustomerAddCompanyNameConflict(){ + //1.prepare + CustomerAddCmd customerAddCmd = new CustomerAddCmd(); + CustomerDTO customerDTO = new CustomerDTO(); + customerDTO.setCompanyName("ConflictCompanyName"); + customerAddCmd.setCustomerDTO(customerDTO); + + //2.execute + Response response = customerService.addCustomer(customerAddCmd); + + //3.assert error + Assert.assertEquals(ErrorCode.B_CUSTOMER_companyNameConflict.getErrCode(), response.getErrCode()); + } +} diff --git a/start/src/test/resources/logback-test.xml b/start/src/test/resources/logback-test.xml new file mode 100644 index 0000000..b4d90e2 --- /dev/null +++ b/start/src/test/resources/logback-test.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + ${LOG_FILE} + + ${FILE_LOG_PATTERN} + + + ${LOG_FILE}.%d{yyyy-MM-dd}.%i.log + 7 + 50MB + 20GB + + + + + + ${CONSOLE_LOG_PATTERN} + utf8 + + + + + + + + + + + + + + + + + + + + + + diff --git a/start/src/test/resources/test.properties b/start/src/test/resources/test.properties new file mode 100644 index 0000000..e81b2a3 --- /dev/null +++ b/start/src/test/resources/test.properties @@ -0,0 +1,23 @@ + + +#tddl +spring.tddl.app=TDDL6_APP +spring.tddl.sharding=false +mybatis.config-location=classpath:mybatis/mybatis-config.xml + +#app +spring.hsf.group=HSF +spring.hsf.version=1.0.0.DAILY +spring.hsf.timeout=2000 + +#tair +spring.tair.config-id=mdbcomm-daily +spring.tair.dynamic-config=true + +#notify +spring.notify.subscriber.group-id=S-pb-test-subscriber1 +spring.notify.subscriber.messageListener=messageListener +spring.notify.subscriber.binding.key=type +spring.notify.subscriber.binding.topic=pandora-boot-test-topic +spring.notify.publisher.group-id=P-pb-test +spring.notify.publisher.topics=pandora-boot-test-topic2, pandora-boot-test-topic -- Gitee From a6f699936e52e4b73c54292b408ee30e3114948d Mon Sep 17 00:00:00 2001 From: ranyu1998 <2772602769@qq.com> Date: Thu, 29 Feb 2024 18:17:37 +0800 Subject: [PATCH 2/4] =?UTF-8?q?feat(init):=20=E5=AE=8C=E6=88=90=E5=A5=96?= =?UTF-8?q?=E5=93=81=E6=A8=A1=E5=9D=97=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../alibaba/demo/web/CustomerController.java | 4 +- .../admin/AdminActivityConfigController.java | 48 +++++++++ .../demo/web/admin/AdminPrizeController.java | 59 +++++++++++ demo-web-app/pom.xml | 5 + .../activity/ActivityConfigServiceImpl.java | 98 +++++++++++++++++++ .../activity/command/ActivityAddCmdExe.java | 29 ++++++ .../demo/assembler/ActivityAssembler.java | 68 +++++++++++++ .../demo/assembler/AwardAssembler.java | 41 ++++++++ .../demo/assembler/PrizeAssembler.java | 34 +++++++ .../demo/award/command/AwardAddCmdExe.java | 48 +++++++++ .../demo/award/command/AwardUpdateCmdExe.java | 25 +++++ .../alibaba/demo/prize/PrizeServiceImpl.java | 51 ++++++++++ .../demo/prize/command/PrizeAddCmdExe.java | 32 ++++++ .../demo/prize/command/PrizeUpdateCmdExe.java | 30 ++++++ .../prize/query/PrizeListByParamQueryExe.java | 34 +++++++ demo-web-base/pom.xml | 30 ++++++ .../demo/web/config/validate/AddGroup.java | 4 + .../demo/web/config/validate/UpdateGroup.java | 4 + .../cola/demo/web/enums/LdExceptionEnum.java | 29 ++++++ .../cola/demo/web/enums/RecordStatusEnum.java | 35 +++++++ .../demo/web/exception/LdCodeException.java | 37 +++++++ .../cola/demo/web/exception/LdException.java | 19 ++++ .../web/exception/TokenAuthException.java | 19 ++++ .../demo/web/handler/SysExceptionHandler.java | 98 +++++++++++++++++++ .../cola/demo/web/util/AssertUtil.java | 35 +++++++ .../cola/demo/web/util/SecurityUtil.java | 49 ++++++++++ .../alibaba/cola/demo/web/vo/FailInfo.java | 35 +++++++ .../cola/demo/web/vo/PageResultInfo.java | 71 ++++++++++++++ .../alibaba/cola/demo/web/vo/ResultInfo.java | 31 ++++++ .../alibaba/cola/demo/web/vo/SuccessInfo.java | 29 ++++++ demo-web-client/pom.xml | 4 + .../demo/api/IActivityConfigService.java | 23 +++++ .../com/alibaba/demo/api/IPrizeService.java | 45 +++++++++ .../com/alibaba/demo/dto/ActivityAddCmd.java | 52 ++++++++++ .../demo/dto/ActivityConfigAddCmd.java | 32 ++++++ .../demo/dto/ActivityConfigUpdateCmd.java | 22 +++++ .../com/alibaba/demo/dto/AwardAddCmd.java | 41 ++++++++ .../com/alibaba/demo/dto/PrizeAddCmd.java | 47 +++++++++ .../demo/dto/data/ActivityConfigVO.java | 30 ++++++ .../com/alibaba/demo/dto/data/ActivityVO.java | 58 +++++++++++ .../com/alibaba/demo/dto/data/AwardVO.java | 63 ++++++++++++ .../com/alibaba/demo/dto/data/PrizeVO.java | 62 ++++++++++++ .../com/alibaba/demo/dto/data/RuleVO.java | 50 ++++++++++ .../demo/dto/query/PrizeListByParamQuery.java | 20 ++++ .../domain/acceptprize/AcceptPrizeEntity.java | 57 +++++++++++ .../demo/domain/activity/ActivityEntity.java | 53 ++++++++++ .../domain/activity/ActivityStatusEnum.java | 25 +++++ .../demo/domain/activity/ActivityTime.java | 60 ++++++++++++ .../activityrule/ActivityRuleEntity.java | 50 ++++++++++ .../demo/domain/award/AwardEntity.java | 74 ++++++++++++++ .../demo/domain/award/AwardNumber.java | 26 +++++ .../demo/domain/gateway/ActivityGateway.java | 19 ++++ .../demo/domain/gateway/AwardGateway.java | 19 ++++ .../demo/domain/gateway/PrizeGateway.java | 31 ++++++ .../alibaba/demo/domain/prize/Inventory.java | 25 +++++ .../demo/domain/prize/PrizeEntity.java | 63 ++++++++++++ .../demo/domain/record/RecordEntity.java | 77 +++++++++++++++ .../demo/domain/record/RecordStatus.java | 57 +++++++++++ demo-web-infrastructure/pom.xml | 18 ++++ .../demo/converter/ActivityConvertor.java | 23 +++++ .../demo/converter/PrizeConvertor.java | 30 ++++++ .../demo/database/dataobject/ActivityDO.java | 67 +++++++++++++ .../dataobject}/CustomerDO.java | 2 +- .../demo/database/dataobject/PrizeDO.java | 67 +++++++++++++ .../gateway/impl/ActivityGatewayImpl.java | 54 ++++++++++ .../demo/gateway/impl/AwardGateWayImpl.java | 29 ++++++ .../impl}/CreditGatewayImpl.java | 2 +- .../impl}/CustomerGatewayImpl.java | 4 +- .../impl}/OrderGatewayImpl.java | 2 +- .../demo/gateway/impl/PrizeGateWayImpl.java | 80 +++++++++++++++ .../alibaba/demo/mapper/ActivityMapper.java | 21 ++++ .../{customer => mapper}/CustomerMapper.java | 3 +- .../com/alibaba/demo/mapper/PrizeMapper.java | 20 ++++ pom.xml | 64 +++++++++++- start/pom.xml | 5 + .../src/main/resources/application.properties | 7 -- start/src/main/resources/application.yml | 31 ++++++ 77 files changed, 2831 insertions(+), 14 deletions(-) create mode 100644 demo-web-adapter/src/main/java/com/alibaba/demo/web/admin/AdminActivityConfigController.java create mode 100644 demo-web-adapter/src/main/java/com/alibaba/demo/web/admin/AdminPrizeController.java create mode 100644 demo-web-app/src/main/java/com/alibaba/demo/activity/ActivityConfigServiceImpl.java create mode 100644 demo-web-app/src/main/java/com/alibaba/demo/activity/command/ActivityAddCmdExe.java create mode 100644 demo-web-app/src/main/java/com/alibaba/demo/assembler/ActivityAssembler.java create mode 100644 demo-web-app/src/main/java/com/alibaba/demo/assembler/AwardAssembler.java create mode 100644 demo-web-app/src/main/java/com/alibaba/demo/assembler/PrizeAssembler.java create mode 100644 demo-web-app/src/main/java/com/alibaba/demo/award/command/AwardAddCmdExe.java create mode 100644 demo-web-app/src/main/java/com/alibaba/demo/award/command/AwardUpdateCmdExe.java create mode 100644 demo-web-app/src/main/java/com/alibaba/demo/prize/PrizeServiceImpl.java create mode 100644 demo-web-app/src/main/java/com/alibaba/demo/prize/command/PrizeAddCmdExe.java create mode 100644 demo-web-app/src/main/java/com/alibaba/demo/prize/command/PrizeUpdateCmdExe.java create mode 100644 demo-web-app/src/main/java/com/alibaba/demo/prize/query/PrizeListByParamQueryExe.java create mode 100644 demo-web-base/pom.xml create mode 100644 demo-web-base/src/main/java/com/alibaba/cola/demo/web/config/validate/AddGroup.java create mode 100644 demo-web-base/src/main/java/com/alibaba/cola/demo/web/config/validate/UpdateGroup.java create mode 100644 demo-web-base/src/main/java/com/alibaba/cola/demo/web/enums/LdExceptionEnum.java create mode 100644 demo-web-base/src/main/java/com/alibaba/cola/demo/web/enums/RecordStatusEnum.java create mode 100644 demo-web-base/src/main/java/com/alibaba/cola/demo/web/exception/LdCodeException.java create mode 100644 demo-web-base/src/main/java/com/alibaba/cola/demo/web/exception/LdException.java create mode 100644 demo-web-base/src/main/java/com/alibaba/cola/demo/web/exception/TokenAuthException.java create mode 100644 demo-web-base/src/main/java/com/alibaba/cola/demo/web/handler/SysExceptionHandler.java create mode 100644 demo-web-base/src/main/java/com/alibaba/cola/demo/web/util/AssertUtil.java create mode 100644 demo-web-base/src/main/java/com/alibaba/cola/demo/web/util/SecurityUtil.java create mode 100644 demo-web-base/src/main/java/com/alibaba/cola/demo/web/vo/FailInfo.java create mode 100644 demo-web-base/src/main/java/com/alibaba/cola/demo/web/vo/PageResultInfo.java create mode 100644 demo-web-base/src/main/java/com/alibaba/cola/demo/web/vo/ResultInfo.java create mode 100644 demo-web-base/src/main/java/com/alibaba/cola/demo/web/vo/SuccessInfo.java create mode 100644 demo-web-client/src/main/java/com/alibaba/demo/api/IActivityConfigService.java create mode 100644 demo-web-client/src/main/java/com/alibaba/demo/api/IPrizeService.java create mode 100644 demo-web-client/src/main/java/com/alibaba/demo/dto/ActivityAddCmd.java create mode 100644 demo-web-client/src/main/java/com/alibaba/demo/dto/ActivityConfigAddCmd.java create mode 100644 demo-web-client/src/main/java/com/alibaba/demo/dto/ActivityConfigUpdateCmd.java create mode 100644 demo-web-client/src/main/java/com/alibaba/demo/dto/AwardAddCmd.java create mode 100644 demo-web-client/src/main/java/com/alibaba/demo/dto/PrizeAddCmd.java create mode 100644 demo-web-client/src/main/java/com/alibaba/demo/dto/data/ActivityConfigVO.java create mode 100644 demo-web-client/src/main/java/com/alibaba/demo/dto/data/ActivityVO.java create mode 100644 demo-web-client/src/main/java/com/alibaba/demo/dto/data/AwardVO.java create mode 100644 demo-web-client/src/main/java/com/alibaba/demo/dto/data/PrizeVO.java create mode 100644 demo-web-client/src/main/java/com/alibaba/demo/dto/data/RuleVO.java create mode 100644 demo-web-client/src/main/java/com/alibaba/demo/dto/query/PrizeListByParamQuery.java create mode 100644 demo-web-domain/src/main/java/com/alibaba/demo/domain/acceptprize/AcceptPrizeEntity.java create mode 100644 demo-web-domain/src/main/java/com/alibaba/demo/domain/activity/ActivityEntity.java create mode 100644 demo-web-domain/src/main/java/com/alibaba/demo/domain/activity/ActivityStatusEnum.java create mode 100644 demo-web-domain/src/main/java/com/alibaba/demo/domain/activity/ActivityTime.java create mode 100644 demo-web-domain/src/main/java/com/alibaba/demo/domain/activityrule/ActivityRuleEntity.java create mode 100644 demo-web-domain/src/main/java/com/alibaba/demo/domain/award/AwardEntity.java create mode 100644 demo-web-domain/src/main/java/com/alibaba/demo/domain/award/AwardNumber.java create mode 100644 demo-web-domain/src/main/java/com/alibaba/demo/domain/gateway/ActivityGateway.java create mode 100644 demo-web-domain/src/main/java/com/alibaba/demo/domain/gateway/AwardGateway.java create mode 100644 demo-web-domain/src/main/java/com/alibaba/demo/domain/gateway/PrizeGateway.java create mode 100644 demo-web-domain/src/main/java/com/alibaba/demo/domain/prize/Inventory.java create mode 100644 demo-web-domain/src/main/java/com/alibaba/demo/domain/prize/PrizeEntity.java create mode 100644 demo-web-domain/src/main/java/com/alibaba/demo/domain/record/RecordEntity.java create mode 100644 demo-web-domain/src/main/java/com/alibaba/demo/domain/record/RecordStatus.java create mode 100644 demo-web-infrastructure/src/main/java/com/alibaba/demo/converter/ActivityConvertor.java create mode 100644 demo-web-infrastructure/src/main/java/com/alibaba/demo/converter/PrizeConvertor.java create mode 100644 demo-web-infrastructure/src/main/java/com/alibaba/demo/database/dataobject/ActivityDO.java rename demo-web-infrastructure/src/main/java/com/alibaba/demo/{customer => database/dataobject}/CustomerDO.java (81%) create mode 100644 demo-web-infrastructure/src/main/java/com/alibaba/demo/database/dataobject/PrizeDO.java create mode 100644 demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/ActivityGatewayImpl.java create mode 100644 demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/AwardGateWayImpl.java rename demo-web-infrastructure/src/main/java/com/alibaba/demo/{customer => gateway/impl}/CreditGatewayImpl.java (86%) rename demo-web-infrastructure/src/main/java/com/alibaba/demo/{customer => gateway/impl}/CustomerGatewayImpl.java (78%) rename demo-web-infrastructure/src/main/java/com/alibaba/demo/{order => gateway/impl}/OrderGatewayImpl.java (47%) create mode 100644 demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/PrizeGateWayImpl.java create mode 100644 demo-web-infrastructure/src/main/java/com/alibaba/demo/mapper/ActivityMapper.java rename demo-web-infrastructure/src/main/java/com/alibaba/demo/{customer => mapper}/CustomerMapper.java (59%) create mode 100644 demo-web-infrastructure/src/main/java/com/alibaba/demo/mapper/PrizeMapper.java delete mode 100644 start/src/main/resources/application.properties create mode 100644 start/src/main/resources/application.yml diff --git a/demo-web-adapter/src/main/java/com/alibaba/demo/web/CustomerController.java b/demo-web-adapter/src/main/java/com/alibaba/demo/web/CustomerController.java index 01bd9ef..bb012fd 100644 --- a/demo-web-adapter/src/main/java/com/alibaba/demo/web/CustomerController.java +++ b/demo-web-adapter/src/main/java/com/alibaba/demo/web/CustomerController.java @@ -8,7 +8,9 @@ import com.alibaba.demo.dto.CustomerListByNameQry; import com.alibaba.demo.dto.data.CustomerDTO; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; - +/** + * 自定义接口 + **/ @RestController public class CustomerController { diff --git a/demo-web-adapter/src/main/java/com/alibaba/demo/web/admin/AdminActivityConfigController.java b/demo-web-adapter/src/main/java/com/alibaba/demo/web/admin/AdminActivityConfigController.java new file mode 100644 index 0000000..59b8c7a --- /dev/null +++ b/demo-web-adapter/src/main/java/com/alibaba/demo/web/admin/AdminActivityConfigController.java @@ -0,0 +1,48 @@ +package com.alibaba.demo.web.admin; + +import com.alibaba.demo.api.IActivityConfigService; +import com.alibaba.demo.dto.ActivityConfigAddCmd; +import com.alibaba.demo.dto.data.ActivityConfigVO; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 活动配置接口 + * @ClassName AdminActivityConfigController + * @Description 活动配置接口 + * @Author guocheng + * @Date 2024/2/28 16:58 + * @Version 1.0 + **/ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("/admin/v1/activityConfig") +public class AdminActivityConfigController { + + private final IActivityConfigService activityConfigService; + + /** + * 添加活动配置 + **/ + @PostMapping("/add") + public ActivityConfigVO add(@Validated @RequestBody ActivityConfigAddCmd cmd){ + return activityConfigService.add(cmd); + } + + /** + * 查看活动配置 + **/ + @GetMapping("/one") + public ActivityConfigVO one(@RequestParam("id") Long id){ + return activityConfigService.one(id); + } + +// @GetMapping("/copy") +// public ActivityConfigCopyVO copy(@RequestParam("id") Long id){ +// +//// return activityConfigService.copy(id); +// } +} diff --git a/demo-web-adapter/src/main/java/com/alibaba/demo/web/admin/AdminPrizeController.java b/demo-web-adapter/src/main/java/com/alibaba/demo/web/admin/AdminPrizeController.java new file mode 100644 index 0000000..d119f3b --- /dev/null +++ b/demo-web-adapter/src/main/java/com/alibaba/demo/web/admin/AdminPrizeController.java @@ -0,0 +1,59 @@ +package com.alibaba.demo.web.admin; + +import com.alibaba.cola.demo.web.vo.PageResultInfo; +import com.alibaba.demo.api.IPrizeService; +import com.alibaba.demo.dto.PrizeAddCmd; +import com.alibaba.demo.dto.data.PrizeVO; +import com.alibaba.demo.dto.query.PrizeListByParamQuery; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 奖品接口 + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("/admin/v1/prize") +public class AdminPrizeController { + + private final IPrizeService prizeService; + + + /** + * 添加奖品 + **/ + @PostMapping("/add") + public PrizeVO add(@Validated @RequestBody PrizeAddCmd cmd) { + return prizeService.add(cmd); + } + + /** + * 修改奖品 + **/ + @PostMapping("/update") + public PrizeVO update(@Validated @RequestBody PrizeAddCmd cmd) { + return prizeService.update(cmd); + } + + + /** + * 分页奖品 + **/ + @PostMapping("/page") + public PageResultInfo page(@RequestBody PrizeListByParamQuery query) { + return prizeService.page(query); + } + + + /** + * 查看奖品 + **/ + @PostMapping("/{id}") + public PrizeVO one(@PathVariable(name = "id") Long id) { + return prizeService.one(id); + } + +} diff --git a/demo-web-app/pom.xml b/demo-web-app/pom.xml index a1f9354..96ee377 100644 --- a/demo-web-app/pom.xml +++ b/demo-web-app/pom.xml @@ -41,5 +41,10 @@ jakarta.el + + + cn.hutool + hutool-all + diff --git a/demo-web-app/src/main/java/com/alibaba/demo/activity/ActivityConfigServiceImpl.java b/demo-web-app/src/main/java/com/alibaba/demo/activity/ActivityConfigServiceImpl.java new file mode 100644 index 0000000..528811e --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/activity/ActivityConfigServiceImpl.java @@ -0,0 +1,98 @@ +package com.alibaba.demo.activity; + +import cn.hutool.core.collection.CollectionUtil; +import com.alibaba.cola.demo.web.util.AssertUtil; +import com.alibaba.demo.activity.command.ActivityAddCmdExe; +import com.alibaba.demo.api.IActivityConfigService; +import com.alibaba.demo.award.command.AwardAddCmdExe; +import com.alibaba.demo.dto.ActivityConfigAddCmd; +import com.alibaba.demo.dto.ActivityConfigUpdateCmd; +import com.alibaba.demo.dto.AwardAddCmd; +import com.alibaba.demo.dto.data.ActivityConfigVO; +import com.alibaba.demo.dto.data.ActivityVO; +import com.alibaba.demo.dto.data.AwardVO; +import com.alibaba.demo.dto.data.RuleVO; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @ClassName ActivityConfigServiceImpl + * @Description TODO + * @Author Jincheng.Guo + * @Date 2024/2/28 17:35 + * @Version 1.0 + **/ +@Slf4j +@Service +@AllArgsConstructor +public class ActivityConfigServiceImpl implements IActivityConfigService { + + private final ActivityAddCmdExe activityAddCmdExe; + private final AwardAddCmdExe awardAddCmdExe; + + + @Transactional(rollbackFor = Exception.class) + @Override + public ActivityConfigVO add(ActivityConfigAddCmd cmd) { + // 添加活动 + ActivityVO activityVO = activityAddCmdExe.execute(cmd.getActivityAddCmd()); + // 添加活动规则 todo + +// List ruleVOList = addActivityRule(activityVO, cmd.getRuleIdList()); + // 添加奖项信息 + List awardVOList = addAward(activityVO, cmd.getAwardAddCmdList()); + + ActivityConfigVO activityConfigVO = new ActivityConfigVO(); + activityConfigVO.setActivityVO(activityVO); + activityConfigVO.setRuleVOList(null); + activityConfigVO.setAwardVOList(awardVOList); + + // 发布活动创建事件 + + return activityConfigVO; + } + + @Override + public ActivityConfigVO update(ActivityConfigUpdateCmd cmd) { + return null; + } + + @Override + public ActivityConfigVO one(Long id) { + return null; + } + + +// private List addActivityRule(ActivityVO activityVO, List ruleIdList) { +// +// List cmdList = new ArrayList<>(); +// for (Long ruleId : ruleIdList) { +// ActivityRuleAddCmd activityRuleAddCmd = new ActivityRuleAddCmd(); +// activityRuleAddCmd.setActivityId(activityVO.getId()); +// activityRuleAddCmd.setRuleId(ruleId); +// cmdList.add(activityRuleAddCmd); +// } +// List activityRuleVOList = activityRuleAddCmdExe.execute(cmdList); +// +// return getRuleVOList(activityRuleVOList.stream().map(ActivityRuleVO::getRuleId).collect(Collectors.toList())); +// } + + + private List addAward(ActivityVO activityVO, List awardAddCmdList) { + AssertUtil.isTrue(CollectionUtil.isEmpty(awardAddCmdList), "奖项不为空!"); + + List result = new ArrayList<>(); + for (AwardAddCmd awardAddCmd : awardAddCmdList) { + awardAddCmd.setActivityId(activityVO.getId()); + result.add(awardAddCmdExe.execute(awardAddCmd)); + } + + return result; + } +} diff --git a/demo-web-app/src/main/java/com/alibaba/demo/activity/command/ActivityAddCmdExe.java b/demo-web-app/src/main/java/com/alibaba/demo/activity/command/ActivityAddCmdExe.java new file mode 100644 index 0000000..47fa957 --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/activity/command/ActivityAddCmdExe.java @@ -0,0 +1,29 @@ +package com.alibaba.demo.activity.command; + +import com.alibaba.demo.assembler.ActivityAssembler; +import com.alibaba.demo.domain.activity.ActivityEntity; +import com.alibaba.demo.domain.gateway.ActivityGateway; +import com.alibaba.demo.dto.ActivityAddCmd; +import com.alibaba.demo.dto.data.ActivityVO; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.luckyapp.activity.command + * @createTime 2022/12/2 - 23:58 + * @description + */ +@Slf4j +@Component +@AllArgsConstructor +public class ActivityAddCmdExe { + + private final ActivityGateway activityGateway; + + public ActivityVO execute(ActivityAddCmd cmd) { + ActivityEntity entity = activityGateway.save(ActivityAssembler.toAddEntity(cmd)); + return ActivityAssembler.toActivityVO(entity); + } +} diff --git a/demo-web-app/src/main/java/com/alibaba/demo/assembler/ActivityAssembler.java b/demo-web-app/src/main/java/com/alibaba/demo/assembler/ActivityAssembler.java new file mode 100644 index 0000000..25275f0 --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/assembler/ActivityAssembler.java @@ -0,0 +1,68 @@ +package com.alibaba.demo.assembler; + +import com.alibaba.cola.demo.web.util.SecurityUtil; +import com.alibaba.demo.domain.activity.ActivityEntity; +import com.alibaba.demo.domain.activity.ActivityTime; +import com.alibaba.demo.dto.ActivityAddCmd; +import com.alibaba.demo.dto.data.ActivityVO; + +import java.time.LocalDateTime; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.luckyapp.assembler + * @createTime 2022/12/3 - 0:03 + * @description + */ +public class ActivityAssembler { + public static ActivityEntity toAddEntity(ActivityAddCmd cmd) { + ActivityEntity activityEntity = new ActivityEntity(); + activityEntity.setActivityName(cmd.getActivityName()); + activityEntity.setActivityTime(new ActivityTime(cmd.getStartTime(), cmd.getEndTime())); + activityEntity.setDescribe(cmd.getDescribe()); + activityEntity.setCreateTime(LocalDateTime.now()); + activityEntity.setCreator(SecurityUtil.getName()); + activityEntity.setUpdateTime(LocalDateTime.now()); + activityEntity.setUpdater(SecurityUtil.getName()); + + return activityEntity; + } + + public static ActivityVO toActivityVO(ActivityEntity entity) { + ActivityVO activityVO = new ActivityVO(); + activityVO.setId(entity.getId()); + activityVO.setActivityName(entity.getActivityName()); + activityVO.setStartTime(entity.getActivityTime().getStartTime()); + activityVO.setEndTime(entity.getActivityTime().getEndTime()); + activityVO.setDescribe(entity.getDescribe()); + activityVO.setCreateTime(entity.getCreateTime()); + activityVO.setCreator(entity.getCreator()); + activityVO.setUpdateTime(entity.getUpdateTime()); + activityVO.setUpdater(entity.getUpdater()); + activityVO.setStatus(entity.getActivityTime().getStatus().getValue()); + + return activityVO; + } + +// public static ActivityEntity toUpdateEntity(ActivityUpdateCmd cmd) { +// ActivityEntity activityEntity = new ActivityEntity(); +// activityEntity.setId(cmd.getId()); +// activityEntity.setActivityName(cmd.getActivityName()); +// activityEntity.setActivityTime(new ActivityTime(cmd.getStartTime(), cmd.getEndTime())); +// activityEntity.setDescribe(cmd.getDescribe()); +// activityEntity.setUpdateTime(LocalDateTime.now()); +// activityEntity.setUpdater(SecurityUtil.getName()); +// +// return activityEntity; +// } + + public static ActivityAddCmd toActivityAddCmd(ActivityVO activityVO) { + ActivityAddCmd activityAddCmd = new ActivityAddCmd(); + activityAddCmd.setActivityName(activityVO.getActivityName()); + activityAddCmd.setStartTime(activityVO.getStartTime()); + activityAddCmd.setEndTime(activityVO.getEndTime()); + activityAddCmd.setDescribe(activityVO.getDescribe()); + + return activityAddCmd; + } +} diff --git a/demo-web-app/src/main/java/com/alibaba/demo/assembler/AwardAssembler.java b/demo-web-app/src/main/java/com/alibaba/demo/assembler/AwardAssembler.java new file mode 100644 index 0000000..5af1ba5 --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/assembler/AwardAssembler.java @@ -0,0 +1,41 @@ +package com.alibaba.demo.assembler; + +import com.alibaba.demo.database.dataobject.ActivityDO; +import com.alibaba.demo.domain.activity.ActivityEntity; +import com.alibaba.demo.domain.award.AwardEntity; +import com.alibaba.demo.domain.award.AwardNumber; +import com.alibaba.demo.dto.AwardAddCmd; +import com.alibaba.demo.dto.data.AwardVO; +import org.mapstruct.Mapper; + +import java.time.LocalDateTime; + +/** + * @Author guocheng + * @Description TODO + * @Date 20:04 2024/2/28 + * @Param + * @return + **/ +@Mapper(componentModel = "spring") +public interface AwardAssembler { + + AwardEntity toAddEntity(AwardAddCmd cmd); + + AwardVO toAwardVO(AwardEntity entity) ; + +// AwardEntity toUpdateEntity(AwardUpdateCmd cmd) ; + + AwardAddCmd toAwardAddCmd(AwardVO awardVO); + + AwardEntity toAwardEntity(AwardVO awardVO) ; + + + default AwardNumber awardNumber(Integer number){ + return new AwardNumber(number); + } + + default Integer awardNumberV2(AwardNumber awardNumber){ + return awardNumber.getNumber(); + } +} diff --git a/demo-web-app/src/main/java/com/alibaba/demo/assembler/PrizeAssembler.java b/demo-web-app/src/main/java/com/alibaba/demo/assembler/PrizeAssembler.java new file mode 100644 index 0000000..e325016 --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/assembler/PrizeAssembler.java @@ -0,0 +1,34 @@ +package com.alibaba.demo.assembler; + +import com.alibaba.demo.domain.award.AwardEntity; +import com.alibaba.demo.domain.prize.PrizeEntity; +import com.alibaba.demo.dto.AwardAddCmd; +import com.alibaba.demo.dto.PrizeAddCmd; +import com.alibaba.demo.dto.data.AwardVO; +import com.alibaba.demo.dto.data.PrizeVO; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; + +/** + * @Author guocheng + * @Description TODO + * @Date 20:04 2024/2/28 + * @Param + * @return + **/ +@Mapper(componentModel = "spring") +public interface PrizeAssembler { + + + + @Mapping(target = "inventory.inventory",source = "inventory") + PrizeEntity toAddEntity(PrizeAddCmd cmd); + + @Mapping(target = "inventory",source = "inventory.inventory") + PrizeVO toPrizeVO(PrizeEntity entity) ; + + + + + +} diff --git a/demo-web-app/src/main/java/com/alibaba/demo/award/command/AwardAddCmdExe.java b/demo-web-app/src/main/java/com/alibaba/demo/award/command/AwardAddCmdExe.java new file mode 100644 index 0000000..70d8c24 --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/award/command/AwardAddCmdExe.java @@ -0,0 +1,48 @@ +package com.alibaba.demo.award.command; + +import com.alibaba.cola.demo.web.util.AssertUtil; +import com.alibaba.demo.assembler.AwardAssembler; +import com.alibaba.demo.domain.award.AwardEntity; +import com.alibaba.demo.domain.gateway.AwardGateway; +import com.alibaba.demo.domain.gateway.PrizeGateway; +import com.alibaba.demo.dto.AwardAddCmd; +import com.alibaba.demo.dto.data.AwardVO; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.Objects; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.luckyapp.award.command + * @createTime 2022/12/2 - 22:46 + * @description + */ +@Slf4j +@Component +@AllArgsConstructor +public class AwardAddCmdExe { + + private final AwardGateway awardGateway; + private final PrizeGateway prizeGateway; + private final AwardAssembler awardAssembler; + + public AwardVO execute(AwardAddCmd cmd) { + AssertUtil.isTrue(Objects.isNull(cmd.getActivityId()), "奖项活动id不为空!"); + + // 保存奖项 + AwardEntity entity = awardGateway.save(awardAssembler.toAddEntity(cmd)); + + // 扣取奖品库存 + if (Boolean.FALSE.equals(entity.isPrize())) { + // 代表该奖项是谢谢参与一类,不需要扣减奖品库存 + return awardAssembler.toAwardVO(entity); + } + + int update = prizeGateway.deductionInventory(cmd.getPrizeId(), cmd.getNumber()); + AssertUtil.isTrue(update < 1, String.format("扣取奖品:%s, 出错,库存不足或奖品不存在!", cmd.getPrizeId())); + + return awardAssembler.toAwardVO(entity); + } +} diff --git a/demo-web-app/src/main/java/com/alibaba/demo/award/command/AwardUpdateCmdExe.java b/demo-web-app/src/main/java/com/alibaba/demo/award/command/AwardUpdateCmdExe.java new file mode 100644 index 0000000..a751ab3 --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/award/command/AwardUpdateCmdExe.java @@ -0,0 +1,25 @@ +package com.alibaba.demo.award.command; + +import com.alibaba.demo.domain.gateway.AwardGateway; +import com.alibaba.demo.dto.data.AwardVO; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.luckyapp.award.command + * @createTime 2022/12/2 - 22:47 + * @description + */ +@Slf4j +@Component +@AllArgsConstructor +public class AwardUpdateCmdExe { + private final AwardGateway awardGateway; +// public AwardVO execute(AwardUpdateCmd cmd) { +// AwardEntity entity = awardGateway.save(AwardAssembler.toUpdateEntity(cmd)); +// +// return AwardAssembler.toAwardVO(entity); +// } +} diff --git a/demo-web-app/src/main/java/com/alibaba/demo/prize/PrizeServiceImpl.java b/demo-web-app/src/main/java/com/alibaba/demo/prize/PrizeServiceImpl.java new file mode 100644 index 0000000..951b4a4 --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/prize/PrizeServiceImpl.java @@ -0,0 +1,51 @@ +package com.alibaba.demo.prize; + +import com.alibaba.cola.demo.web.vo.PageResultInfo; +import com.alibaba.demo.api.IPrizeService; +import com.alibaba.demo.dto.PrizeAddCmd; +import com.alibaba.demo.dto.data.PrizeVO; +import com.alibaba.demo.dto.query.PrizeListByParamQuery; +import com.alibaba.demo.prize.command.PrizeAddCmdExe; +import com.alibaba.demo.prize.command.PrizeUpdateCmdExe; +import com.alibaba.demo.prize.query.PrizeListByParamQueryExe; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * @ClassName PrizeServiceImpl + * @Description TODO + * @Author Jincheng.Guo + * @Date 2024/2/29 15:58 + * @Version 1.0 + **/ +@Slf4j +@Service +@AllArgsConstructor +public class PrizeServiceImpl implements IPrizeService { + + private final PrizeAddCmdExe prizeAddCmdExe; + private final PrizeUpdateCmdExe prizeUpdateCmdExe; + private final PrizeListByParamQueryExe prizeListByParamQueryExe; + + + @Override + public PrizeVO add(PrizeAddCmd cmd) { + return prizeAddCmdExe.execute(cmd); + } + + @Override + public PrizeVO update(PrizeAddCmd cmd) { + return prizeUpdateCmdExe.execute(cmd); + } + + @Override + public PageResultInfo page(PrizeListByParamQuery query) { + return prizeListByParamQueryExe.execute(query); + } + + @Override + public PrizeVO one(Long id) { + return null; + } +} diff --git a/demo-web-app/src/main/java/com/alibaba/demo/prize/command/PrizeAddCmdExe.java b/demo-web-app/src/main/java/com/alibaba/demo/prize/command/PrizeAddCmdExe.java new file mode 100644 index 0000000..3e37632 --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/prize/command/PrizeAddCmdExe.java @@ -0,0 +1,32 @@ +package com.alibaba.demo.prize.command; + +import com.alibaba.demo.assembler.PrizeAssembler; +import com.alibaba.demo.domain.gateway.PrizeGateway; +import com.alibaba.demo.domain.prize.PrizeEntity; +import com.alibaba.demo.dto.PrizeAddCmd; +import com.alibaba.demo.dto.data.PrizeVO; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.luckyapp.prize + * @createTime 2022/12/1 - 22:20 + * @description + */ +@Slf4j +@Component +@AllArgsConstructor +public class PrizeAddCmdExe { + + private final PrizeAssembler prizeAssembler; + + private final PrizeGateway prizeGateway; + + public PrizeVO execute(PrizeAddCmd cmd) { + PrizeEntity prizeEntity = prizeGateway.save(prizeAssembler.toAddEntity(cmd)); + + return prizeAssembler.toPrizeVO(prizeEntity); + } +} diff --git a/demo-web-app/src/main/java/com/alibaba/demo/prize/command/PrizeUpdateCmdExe.java b/demo-web-app/src/main/java/com/alibaba/demo/prize/command/PrizeUpdateCmdExe.java new file mode 100644 index 0000000..4a2ccc6 --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/prize/command/PrizeUpdateCmdExe.java @@ -0,0 +1,30 @@ +package com.alibaba.demo.prize.command; + +import com.alibaba.demo.assembler.PrizeAssembler; +import com.alibaba.demo.domain.gateway.PrizeGateway; +import com.alibaba.demo.domain.prize.PrizeEntity; +import com.alibaba.demo.dto.PrizeAddCmd; +import com.alibaba.demo.dto.data.PrizeVO; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.luckyapp.prize + * @createTime 2022/12/1 - 22:20 + * @description + */ +@Slf4j +@Component +@AllArgsConstructor +public class PrizeUpdateCmdExe { + + private final PrizeGateway prizeGateway; + private final PrizeAssembler prizeAssembler; + + public PrizeVO execute(PrizeAddCmd cmd) { + PrizeEntity prizeEntity = prizeGateway.save(prizeAssembler.toAddEntity(cmd)); + return prizeAssembler.toPrizeVO(prizeEntity); + } +} diff --git a/demo-web-app/src/main/java/com/alibaba/demo/prize/query/PrizeListByParamQueryExe.java b/demo-web-app/src/main/java/com/alibaba/demo/prize/query/PrizeListByParamQueryExe.java new file mode 100644 index 0000000..1a0ea4d --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/prize/query/PrizeListByParamQueryExe.java @@ -0,0 +1,34 @@ +package com.alibaba.demo.prize.query; + +import cn.hutool.core.util.PageUtil; +import com.alibaba.cola.demo.web.vo.PageResultInfo; +import com.alibaba.demo.assembler.PrizeAssembler; +import com.alibaba.demo.domain.gateway.PrizeGateway; +import com.alibaba.demo.domain.prize.PrizeEntity; +import com.alibaba.demo.dto.data.PrizeVO; +import com.alibaba.demo.dto.query.PrizeListByParamQuery; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.function.Function; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.luckyapp.prize.query + * @createTime 2022/12/1 - 22:21 + * @description + */ +@Slf4j +@Component +@AllArgsConstructor +public class PrizeListByParamQueryExe { + + private final PrizeGateway prizeGateway; + private final PrizeAssembler prizeAssembler; + + public PageResultInfo execute(PrizeListByParamQuery query) { + PageResultInfo page = prizeGateway.page(query); + return page.convert(prizeAssembler::toPrizeVO); + } +} diff --git a/demo-web-base/pom.xml b/demo-web-base/pom.xml new file mode 100644 index 0000000..802aff8 --- /dev/null +++ b/demo-web-base/pom.xml @@ -0,0 +1,30 @@ + + + + demo-web-parent + com.alibaba.cola.demo.web + 1.0.0-SNAPSHOT + + 4.0.0 + + demo-web-base + + + + + + + + com.fasterxml.jackson.core + jackson-databind + + + org.springframework.boot + spring-boot-starter-web + + + + + \ No newline at end of file diff --git a/demo-web-base/src/main/java/com/alibaba/cola/demo/web/config/validate/AddGroup.java b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/config/validate/AddGroup.java new file mode 100644 index 0000000..e7eb406 --- /dev/null +++ b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/config/validate/AddGroup.java @@ -0,0 +1,4 @@ +package com.alibaba.cola.demo.web.config.validate; + +public interface AddGroup { +} diff --git a/demo-web-base/src/main/java/com/alibaba/cola/demo/web/config/validate/UpdateGroup.java b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/config/validate/UpdateGroup.java new file mode 100644 index 0000000..fec761d --- /dev/null +++ b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/config/validate/UpdateGroup.java @@ -0,0 +1,4 @@ +package com.alibaba.cola.demo.web.config.validate; + +public interface UpdateGroup { +} diff --git a/demo-web-base/src/main/java/com/alibaba/cola/demo/web/enums/LdExceptionEnum.java b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/enums/LdExceptionEnum.java new file mode 100644 index 0000000..ae66361 --- /dev/null +++ b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/enums/LdExceptionEnum.java @@ -0,0 +1,29 @@ +package com.alibaba.cola.demo.web.enums; + +import com.alibaba.cola.demo.web.vo.FailInfo; +import lombok.Getter; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.config + * @createTime 2022/12/4 - 21:58 + * @description + */ +@Getter +public enum LdExceptionEnum { + + ADD_ERROR(FailInfo.DEFAULT_CODE, "保存数据失败!"), + + UPDATE_ERROR(FailInfo.DEFAULT_CODE, "保存数据失败!"), + + ; + private Integer code; + + private String description; + + LdExceptionEnum(Integer code, String description){ + this.code = code; + this.description = description; + } + +} diff --git a/demo-web-base/src/main/java/com/alibaba/cola/demo/web/enums/RecordStatusEnum.java b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/enums/RecordStatusEnum.java new file mode 100644 index 0000000..b5746ba --- /dev/null +++ b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/enums/RecordStatusEnum.java @@ -0,0 +1,35 @@ +package com.alibaba.cola.demo.web.enums; + +import lombok.Getter; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.luckydomain.record + * @createTime 2022/12/9 - 23:06 + * @description + */ +@Getter +public enum RecordStatusEnum { + + STATUE_0(0, "用户不可见"), + + STATUE_1(1, "待领取奖品"), + + STATUE_2(2, "待运营人员确认"), + + STATUE_3(3, "待用户签收"), + + STATUE_4(4, "流程结束"), + + ; + private Integer value; + + private String description; + + + RecordStatusEnum(Integer value, String description){ + this.value = value; + this.description = description; + } + +} diff --git a/demo-web-base/src/main/java/com/alibaba/cola/demo/web/exception/LdCodeException.java b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/exception/LdCodeException.java new file mode 100644 index 0000000..fbfe70b --- /dev/null +++ b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/exception/LdCodeException.java @@ -0,0 +1,37 @@ +package com.alibaba.cola.demo.web.exception; + + +import com.alibaba.cola.demo.web.vo.FailInfo; + +public class LdCodeException extends RuntimeException { + + private Integer code; + + public Integer getCode() { + return code; + } + + public LdCodeException() { + } + + public LdCodeException(Integer code, String message, Object... args) { + super(String.format(message, args)); + this.code = code; + } + + public LdCodeException(String message, Object... args) { + super(String.format(message, args)); + this.code = FailInfo.DEFAULT_CODE; + } + + public LdCodeException(String message, Throwable cause, Object... args) { + super(String.format(message, args), cause); + this.code = FailInfo.DEFAULT_CODE; + } + + public LdCodeException(Throwable cause) { + super(cause); + this.code = FailInfo.DEFAULT_CODE; + } + +} diff --git a/demo-web-base/src/main/java/com/alibaba/cola/demo/web/exception/LdException.java b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/exception/LdException.java new file mode 100644 index 0000000..306d3b9 --- /dev/null +++ b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/exception/LdException.java @@ -0,0 +1,19 @@ +package com.alibaba.cola.demo.web.exception; + + +public class LdException extends RuntimeException { + public LdException() { + } + public LdException(String message, Object... args) { + super(String.format(message, args)); + } + + public LdException(String message, Throwable cause, Object... args) { + super(String.format(message, args), cause); + } + + public LdException(Throwable cause) { + super(cause); + } + +} diff --git a/demo-web-base/src/main/java/com/alibaba/cola/demo/web/exception/TokenAuthException.java b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/exception/TokenAuthException.java new file mode 100644 index 0000000..63ec9b8 --- /dev/null +++ b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/exception/TokenAuthException.java @@ -0,0 +1,19 @@ +package com.alibaba.cola.demo.web.exception; + + +public class TokenAuthException extends RuntimeException { + public TokenAuthException() { + } + public TokenAuthException(String message, Object... args) { + super(String.format(message, args)); + } + + public TokenAuthException(String message, Throwable cause, Object... args) { + super(String.format(message, args), cause); + } + + public TokenAuthException(Throwable cause) { + super(cause); + } + +} diff --git a/demo-web-base/src/main/java/com/alibaba/cola/demo/web/handler/SysExceptionHandler.java b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/handler/SysExceptionHandler.java new file mode 100644 index 0000000..c9218ee --- /dev/null +++ b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/handler/SysExceptionHandler.java @@ -0,0 +1,98 @@ +package com.alibaba.cola.demo.web.handler; + +import com.alibaba.cola.demo.web.exception.LdCodeException; +import com.alibaba.cola.demo.web.exception.LdException; +import com.alibaba.cola.demo.web.exception.TokenAuthException; +import com.alibaba.cola.demo.web.vo.FailInfo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.BindException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import java.util.Objects; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.common.handler + * @createTime 2022/11/26 - 16:01 + * @description + */ +@Slf4j +@RestControllerAdvice +public class SysExceptionHandler { + + /** + * 最大的兜底错误处理 + * + * @param ex + * @return + */ + @ExceptionHandler(value = Exception.class) + public FailInfo exception(Exception ex) { + log.error("Exception_info:{}", ex.getMessage()); + log.error("Exception_info:", ex); + return FailInfo.builder().exception(ex.getMessage()).build(); + } + + /** + * 参数绑定错误 + * + * @param ex + * @return + */ + @ExceptionHandler(value = BindException.class) + public FailInfo exception(BindException ex) { + String defaultMessage = Objects.requireNonNull(ex.getBindingResult().getFieldError()).getDefaultMessage(); + log.error("Exception_info:{}", defaultMessage); + log.error("Exception_info:", ex); + return FailInfo.builder().exception(defaultMessage).build(); + } + + @ExceptionHandler(value = LdCodeException.class) + public FailInfo ldCodeException(LdCodeException ex) { + log.error("Exception_info:{}", ex.getMessage()); + log.error("Exception_info:", ex); + FailInfo failInfo = new FailInfo(ex.getCode(), ex.getMessage()); + return failInfo; + } + + @ExceptionHandler(value = LdException.class) + public FailInfo sysException(Exception ex) { + log.error("Exception_info:{}", ex.getMessage()); + log.error("Exception_info:", ex); + return FailInfo.builder().exception(ex.getMessage()).build(); + } + + @ExceptionHandler(value = TokenAuthException.class) + public FailInfo tokenAuthException(Exception ex) { + log.error("Exception_info:{}", ex.getMessage()); + log.error("Exception_info:", ex); + return FailInfo.builder().exception(ex.getMessage()).build(); + } + + +// @ExceptionHandler(value = MysqlDataTruncation.class) +// public FailInfo mysqlDataTruncation(Exception ex) { +// log.error("Exception_info:{}", ex.getMessage()); +// log.error("Exception_info:", ex); +// return new FailInfo(500, ex.getMessage()); +// } + +// @ExceptionHandler(value = DataIntegrityViolationException.class) +// public FailInfo dataIntegrityViolationException(Exception ex) { +// log.error("Exception_info:{}", ex.getMessage()); +// log.error("Exception_info:", ex); +// String message = ex.getMessage(); +// String[] split = message.split("\r\n###"); +// for (String str : split) { +// if (str.trim().isBlank() || str.trim().contains("Error")){ +// continue; +// } +// String[] split1 = str.split(":"); +// if (split1.length > 0) { +// message = split1[split1.length - 1].trim(); +// } +// } +// return new FailInfo(500, message); +// } +} diff --git a/demo-web-base/src/main/java/com/alibaba/cola/demo/web/util/AssertUtil.java b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/util/AssertUtil.java new file mode 100644 index 0000000..aa71512 --- /dev/null +++ b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/util/AssertUtil.java @@ -0,0 +1,35 @@ +package com.alibaba.cola.demo.web.util; + + +import com.alibaba.cola.demo.web.exception.LdException; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.config.util + * @createTime 2022/12/4 - 21:52 + * @description + */ +public class AssertUtil { + + /** + * 条件是 true,抛出消息 + * @param expression + * @param message + */ + public static void isTrue(Boolean expression, String message) { + if (expression) { + throw new LdException(message); + } + } + + /** + * 条件是 false,抛出消息 + * @param expression + * @param message + */ + public static void isFalse(Boolean expression, String message) { + if (!expression) { + throw new LdException(message); + } + } +} diff --git a/demo-web-base/src/main/java/com/alibaba/cola/demo/web/util/SecurityUtil.java b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/util/SecurityUtil.java new file mode 100644 index 0000000..5d46222 --- /dev/null +++ b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/util/SecurityUtil.java @@ -0,0 +1,49 @@ +package com.alibaba.cola.demo.web.util; + +import java.util.Map; +import java.util.Objects; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.config.util + * @createTime 2022/11/30 - 22:45 + * @description + */ +public class SecurityUtil { + + private static ThreadLocal> userThreadLocal = new ThreadLocal<>(); + + public static void addConfig(Map user) { + userThreadLocal.set(user); + } + + public static void remove() { + userThreadLocal.remove(); + } + + public static String getUserName() { + Object username = userThreadLocal.get().get("username"); + + return Objects.isNull(username) ? "" : username.toString(); + } + + public static String getName() { + return "GSean"; +// Object name = userThreadLocal.get().get("name"); + +// return Objects.isNull(name) ? "" : name.toString(); + } + + public static Long getUserId() { + Object userId = userThreadLocal.get().get("id"); + + return Objects.isNull(userId) ? 0L : Long.parseLong(userId.toString()); + } + + public static String get(String key) { + Object value = userThreadLocal.get().get(key); + + return Objects.isNull(value) ? "" : value.toString(); + } + +} diff --git a/demo-web-base/src/main/java/com/alibaba/cola/demo/web/vo/FailInfo.java b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/vo/FailInfo.java new file mode 100644 index 0000000..eced7fb --- /dev/null +++ b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/vo/FailInfo.java @@ -0,0 +1,35 @@ +package com.alibaba.cola.demo.web.vo; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.Builder; +import lombok.Getter; +import lombok.ToString; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.config.vo + * @createTime 2022/11/26 - 15:38 + * @description + */ +@Builder +@ToString +@Getter +public class FailInfo extends ResultInfo{ + + public static final Integer DEFAULT_CODE = 50000; + protected static final String DEFAULT_MESSAGE = "操作失败"; + + @JsonInclude(JsonInclude.Include.NON_NULL) + private final String exception; + + + public FailInfo(String exception) { + super(false, DEFAULT_CODE, DEFAULT_MESSAGE); + this.exception = exception; + } + + public FailInfo(Integer code, String exception) { + super(false, code, DEFAULT_MESSAGE); + this.exception = exception; + } +} diff --git a/demo-web-base/src/main/java/com/alibaba/cola/demo/web/vo/PageResultInfo.java b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/vo/PageResultInfo.java new file mode 100644 index 0000000..c626493 --- /dev/null +++ b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/vo/PageResultInfo.java @@ -0,0 +1,71 @@ +package com.alibaba.cola.demo.web.vo; + +import lombok.Builder; +import lombok.Getter; +import lombok.ToString; + +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.config.vo + * @createTime 2022/11/26 - 15:35 + * @description + */ +@Builder +@ToString +@Getter +public class PageResultInfo extends ResultInfo { + + protected static final Integer DEFAULT_CODE = 20000; + protected static final String DEFAULT_MESSAGE = "操作成功"; + + protected int totalCount = 0; + protected int pageSize = 1; + protected int pageIndex = 1; + protected List data; + + + protected PageResultInfo(int totalCount,int pageSize,int pageIndex,List data) { + super(true, DEFAULT_CODE, DEFAULT_MESSAGE); + this.totalCount=totalCount; + this.pageIndex=pageIndex; + this.pageSize=pageSize; + this.data=data; + } + + + + + + public PageResultInfo convert(Function mapper) { + List collect = (List)this.getData().stream().map(mapper).collect(Collectors.toList()); + return this.setDataV2(collect); + } + + public PageResultInfo setDataV2(List data) { + this.data = data; + return this; + } + + public static PageResultInfo pageConvert(Function mapper, List dataList){ + return pageConvert(mapper,dataList,1,0,1); + } + + public static PageResultInfo pageConvert(Function mapper, List dataList,long total,long pageIndex,long pageSize + ){ + return pageConvert(mapper,dataList,Long.valueOf(total).intValue(),Long.valueOf(pageIndex).intValue(),Long.valueOf(pageSize).intValue()); + } + + public static PageResultInfo pageConvert(Function mapper, List dataList,int total,int pageIndex,int pageSize + ){ + List collect = (List)dataList.stream().map(mapper).collect(Collectors.toList()); + return PageResultInfo.builder() + .pageIndex(pageIndex) + .pageSize(pageSize) + .totalCount(total) + .data(collect).build(); + } +} diff --git a/demo-web-base/src/main/java/com/alibaba/cola/demo/web/vo/ResultInfo.java b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/vo/ResultInfo.java new file mode 100644 index 0000000..4f6be63 --- /dev/null +++ b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/vo/ResultInfo.java @@ -0,0 +1,31 @@ +package com.alibaba.cola.demo.web.vo; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.Getter; + +import java.io.Serializable; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.config.vo + * @createTime 2022/11/26 - 15:35 + * @description + */ +@Getter +public class ResultInfo implements Serializable { + + protected Boolean result; + protected Integer code; + /** + * message = null , 不序列化出去 + */ + @JsonInclude(JsonInclude.Include.NON_NULL) + protected String message; + + protected ResultInfo(Boolean result, Integer code, String message) { + this.result = result; + this.code = code; + this.message = message; + } + +} diff --git a/demo-web-base/src/main/java/com/alibaba/cola/demo/web/vo/SuccessInfo.java b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/vo/SuccessInfo.java new file mode 100644 index 0000000..3da9c9d --- /dev/null +++ b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/vo/SuccessInfo.java @@ -0,0 +1,29 @@ +package com.alibaba.cola.demo.web.vo; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.Builder; +import lombok.Getter; +import lombok.ToString; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.config.vo + * @createTime 2022/11/26 - 15:38 + * @description + */ +@Builder +@ToString +@Getter +public class SuccessInfo extends ResultInfo{ + + protected static final Integer DEFAULT_CODE = 20000; + protected static final String DEFAULT_MESSAGE = "操作成功"; + + @JsonInclude(JsonInclude.Include.NON_NULL) + protected T data; + + protected SuccessInfo(T data) { + super(true, DEFAULT_CODE, DEFAULT_MESSAGE); + this.data = data; + } +} diff --git a/demo-web-client/pom.xml b/demo-web-client/pom.xml index 43f8c90..f55350e 100644 --- a/demo-web-client/pom.xml +++ b/demo-web-client/pom.xml @@ -21,5 +21,9 @@ javax.validation validation-api + + com.alibaba.cola.demo.web + demo-web-base + diff --git a/demo-web-client/src/main/java/com/alibaba/demo/api/IActivityConfigService.java b/demo-web-client/src/main/java/com/alibaba/demo/api/IActivityConfigService.java new file mode 100644 index 0000000..c7d7e26 --- /dev/null +++ b/demo-web-client/src/main/java/com/alibaba/demo/api/IActivityConfigService.java @@ -0,0 +1,23 @@ +package com.alibaba.demo.api; + + +import com.alibaba.demo.dto.ActivityConfigAddCmd; +import com.alibaba.demo.dto.ActivityConfigUpdateCmd; +import com.alibaba.demo.dto.data.ActivityConfigVO; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.luckyclient.api + * @createTime 2022/12/4 - 22:30 + * @description + */ +public interface IActivityConfigService { + + ActivityConfigVO add(ActivityConfigAddCmd cmd); + + ActivityConfigVO update(ActivityConfigUpdateCmd cmd); + + ActivityConfigVO one(Long id); + +// ActivityConfigCopyVO copy(Long id); +} diff --git a/demo-web-client/src/main/java/com/alibaba/demo/api/IPrizeService.java b/demo-web-client/src/main/java/com/alibaba/demo/api/IPrizeService.java new file mode 100644 index 0000000..cf9e248 --- /dev/null +++ b/demo-web-client/src/main/java/com/alibaba/demo/api/IPrizeService.java @@ -0,0 +1,45 @@ +package com.alibaba.demo.api; + + +import com.alibaba.cola.demo.web.vo.PageResultInfo; +import com.alibaba.cola.dto.PageResponse; +import com.alibaba.demo.dto.PrizeAddCmd; +import com.alibaba.demo.dto.data.PrizeVO; +import com.alibaba.demo.dto.query.PrizeListByParamQuery; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.luckyclient.api + * @createTime 2022/12/1 - 22:09 + * @description + */ +public interface IPrizeService { + + /** + * 添加 + * @param cmd + * @return + */ + PrizeVO add(PrizeAddCmd cmd); + + /** + * 修改 + * @param cmd + * @return + */ + PrizeVO update(PrizeAddCmd cmd); + + /** + * 查询 + * @param query + * @return + */ + PageResultInfo page(PrizeListByParamQuery query); + + /** + * 查询 + * @param id + * @return + */ + PrizeVO one(Long id); +} diff --git a/demo-web-client/src/main/java/com/alibaba/demo/dto/ActivityAddCmd.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/ActivityAddCmd.java new file mode 100644 index 0000000..40fbf43 --- /dev/null +++ b/demo-web-client/src/main/java/com/alibaba/demo/dto/ActivityAddCmd.java @@ -0,0 +1,52 @@ +package com.alibaba.demo.dto; + +import com.alibaba.cola.demo.web.config.validate.UpdateGroup; +import com.alibaba.cola.dto.Command; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +/** + * @ClassName ActivityAddCmdCmd + * @Description 活动添加命令 + * @Author guocheng + * @Date 2024/2/28 16:34 + * @Version 1.0 + **/ +@Data +public class ActivityAddCmd extends Command { + + + /** + * 活动Id + */ + @NotNull(message = "id不为空",groups = {UpdateGroup.class}) + private Long id; + + + + /** + * 活动名称 + */ + @NotNull(message = "活动名称不为空") + private String activityName; + /** + * 活动开始时间 + */ + @NotNull(message = "开始时间不为空") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime startTime; + /** + * 活动结束时间 + */ + @NotNull(message = "结束时间不为空") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime endTime; + /** + * 活动描述 + */ + @NotNull(message = "描述不为空") + private String describe; +} diff --git a/demo-web-client/src/main/java/com/alibaba/demo/dto/ActivityConfigAddCmd.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/ActivityConfigAddCmd.java new file mode 100644 index 0000000..2deb8a0 --- /dev/null +++ b/demo-web-client/src/main/java/com/alibaba/demo/dto/ActivityConfigAddCmd.java @@ -0,0 +1,32 @@ +package com.alibaba.demo.dto; + +import lombok.Data; + +import javax.validation.Valid; +import java.util.List; + +/** + * @ClassName ActivityConfigAddCmd + * @Description 活动配置添加命令 + * @Author guocheng + * @Date 2024/2/28 16:32 + * @Version 1.0 + **/ +@Data +public class ActivityConfigAddCmd { + + /** + * 活动添加命令 + */ + @Valid + private ActivityAddCmd activityAddCmd; + /** + * 规则ID集合 + */ + private List ruleIdList; + /** + * 奖项添加命令 + */ + @Valid + private List awardAddCmdList; +} diff --git a/demo-web-client/src/main/java/com/alibaba/demo/dto/ActivityConfigUpdateCmd.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/ActivityConfigUpdateCmd.java new file mode 100644 index 0000000..556e541 --- /dev/null +++ b/demo-web-client/src/main/java/com/alibaba/demo/dto/ActivityConfigUpdateCmd.java @@ -0,0 +1,22 @@ +package com.alibaba.demo.dto; + +import com.alibaba.cola.dto.Command; +import lombok.Data; + +import javax.validation.Valid; +import java.util.List; + +/** + * 活动配置更新命令 + */ +@Data +public class ActivityConfigUpdateCmd extends Command { + + @Valid + private ActivityAddCmd activityUpdateCmd; + + private List ruleIdList; + + @Valid + private List awardUpdateCmdList; +} diff --git a/demo-web-client/src/main/java/com/alibaba/demo/dto/AwardAddCmd.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/AwardAddCmd.java new file mode 100644 index 0000000..6ae66ee --- /dev/null +++ b/demo-web-client/src/main/java/com/alibaba/demo/dto/AwardAddCmd.java @@ -0,0 +1,41 @@ +package com.alibaba.demo.dto; + +import com.alibaba.cola.demo.web.config.validate.UpdateGroup; +import com.alibaba.cola.dto.Command; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @ClassName AwardAddCmdListCmd + * @Description 奖项添加命令 + * @Author guocheng + * @Date 2024/2/28 16:34 + * @Version 1.0 + **/ +@Data +public class AwardAddCmd extends Command { + + @NotNull(message = "id不为空",groups = {UpdateGroup.class}) + private Long id; + /** + * 奖品ID + */ + private Long prizeId; + /** + * 活动ID + */ + private Long activityId; + /** + * 数量 + */ + private Integer number; + /** + * 奖项名称 + */ + private String awardName; + /** + * 概率 + */ + private Double probability; +} diff --git a/demo-web-client/src/main/java/com/alibaba/demo/dto/PrizeAddCmd.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/PrizeAddCmd.java new file mode 100644 index 0000000..fdacb61 --- /dev/null +++ b/demo-web-client/src/main/java/com/alibaba/demo/dto/PrizeAddCmd.java @@ -0,0 +1,47 @@ +package com.alibaba.demo.dto; + +import com.alibaba.cola.demo.web.config.validate.UpdateGroup; +import com.alibaba.cola.dto.Command; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.luckyclient.dto + * @createTime 2022/12/1 - 22:11 + * @description + */ +@Data +public class PrizeAddCmd extends Command { + + + @NotNull(message = "id不为空",groups = {UpdateGroup.class}) + private Long id; + + /** + * 奖品名称 + */ + @NotNull(message = "奖品名称不为空") + private String prizeName; + + /** + * 库存 + */ + @NotNull(message = "库存不为空") + private Integer inventory; + + /** + * 金额 + */ + @NotNull(message = "金额不为空") + private BigDecimal money; + + /** + * 类型(1:商品,2:金钱) + */ + @NotNull(message = "类型不为空") + private Integer type; + +} diff --git a/demo-web-client/src/main/java/com/alibaba/demo/dto/data/ActivityConfigVO.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/data/ActivityConfigVO.java new file mode 100644 index 0000000..b231fd0 --- /dev/null +++ b/demo-web-client/src/main/java/com/alibaba/demo/dto/data/ActivityConfigVO.java @@ -0,0 +1,30 @@ +package com.alibaba.demo.dto.data; + +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * @ClassName ActivityConfigVO + * @Description 活动配置 + * @Author guocheng + * @Date 2024/2/28 17:01 + * @Version 1.0 + **/ +@NoArgsConstructor +@Data +public class ActivityConfigVO { + /** + * 活动信息 + */ + private ActivityVO activityVO; + /** + * 规则列表 + */ + private List ruleVOList; + /** + * 奖项列表 + */ + private List awardVOList; +} diff --git a/demo-web-client/src/main/java/com/alibaba/demo/dto/data/ActivityVO.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/data/ActivityVO.java new file mode 100644 index 0000000..cf7a5f5 --- /dev/null +++ b/demo-web-client/src/main/java/com/alibaba/demo/dto/data/ActivityVO.java @@ -0,0 +1,58 @@ +package com.alibaba.demo.dto.data; + +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +/** + * @ClassName ActivityVOVO + * @Description 活动信息 + * @Author guocheng + * @Date 2024/2/28 17:02 + * @Version 1.0 + **/ +@NoArgsConstructor +@Data +public class ActivityVO { + /** + * 活动ID + */ + private Long id; + /** + * 活动名称 + */ + private String activityName; + /** + * 活动开始时间 + */ + private LocalDateTime startTime; + /** + * 活动结束时间 + */ + private LocalDateTime endTime; + /** + * 活动描述 + */ + private String describe; + /** + * 状态 + */ + private Integer status; + /** + * createTime + */ + private LocalDateTime createTime; + /** + * creator + */ + private String creator; + /** + * updateTime + */ + private LocalDateTime updateTime; + /** + * updater + */ + private String updater; +} diff --git a/demo-web-client/src/main/java/com/alibaba/demo/dto/data/AwardVO.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/data/AwardVO.java new file mode 100644 index 0000000..df2e5bf --- /dev/null +++ b/demo-web-client/src/main/java/com/alibaba/demo/dto/data/AwardVO.java @@ -0,0 +1,63 @@ +package com.alibaba.demo.dto.data; + +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.nio.DoubleBuffer; +import java.time.LocalDateTime; + +/** + * @ClassName AwardVOListVO + * @Description TODO + * @Author guocheng + * @Date 2024/2/28 17:02 + * @Version 1.0 + **/ +@NoArgsConstructor +@Data +public class AwardVO { + /** + * id + */ + private Long id; + /** + * 奖品ID + */ + private Long prizeId; + /** + * 奖品名称 + */ + private String prizeName; + /** + * 活动ID + */ + private Long activityId; + /** + * 数量 + */ + private Integer number; + /** + * 奖项名称 + */ + private String awardName; + /** + * 概率(1,0.001) + */ + private Double probability; + /** + * createTime + */ + private LocalDateTime createTime; + /** + * creator + */ + private String creator; + /** + * updateTime + */ + private LocalDateTime updateTime; + /** + * updater + */ + private String updater; +} diff --git a/demo-web-client/src/main/java/com/alibaba/demo/dto/data/PrizeVO.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/data/PrizeVO.java new file mode 100644 index 0000000..b083059 --- /dev/null +++ b/demo-web-client/src/main/java/com/alibaba/demo/dto/data/PrizeVO.java @@ -0,0 +1,62 @@ +package com.alibaba.demo.dto.data; + +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.luckyclient.dto.data + * @createTime 2022/12/1 - 22:09 + * @description + */ +@Data +public class PrizeVO { + + /** + * + */ + private Long id; + + /** + * 奖品名称 + */ + private String prizeName; + + /** + * 库存 + */ + private Integer inventory; + + /** + * 金额 + */ + private BigDecimal money; + + /** + * 类型(1:商品,2:金钱) + */ + private Integer type; + + /** + * + */ + private LocalDateTime createTime; + + /** + * + */ + private String creator; + + /** + * + */ + private LocalDateTime updateTime; + + /** + * + */ + private String updater; + +} diff --git a/demo-web-client/src/main/java/com/alibaba/demo/dto/data/RuleVO.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/data/RuleVO.java new file mode 100644 index 0000000..0724106 --- /dev/null +++ b/demo-web-client/src/main/java/com/alibaba/demo/dto/data/RuleVO.java @@ -0,0 +1,50 @@ +package com.alibaba.demo.dto.data; + +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +/** + * @ClassName RuleVOListVO + * @Description 活动规则信息 + * @Author guocheng + * @Date 2024/2/28 17:02 + * @Version 1.0 + **/ +@NoArgsConstructor +@Data +public class RuleVO { + /** + * id + */ + private Long id; + /** + * 规则名称 + */ + private String ruleName; + /** + * 最大可参与次数 + */ + private Integer maxJoinNumber; + /** + * 最大可中奖次数 + */ + private Integer maxWinningNumber; + /** + * createTime + */ + private LocalDateTime createTime; + /** + * creator + */ + private String creator; + /** + * updateTime + */ + private LocalDateTime updateTime; + /** + * updater + */ + private String updater; +} diff --git a/demo-web-client/src/main/java/com/alibaba/demo/dto/query/PrizeListByParamQuery.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/query/PrizeListByParamQuery.java new file mode 100644 index 0000000..9328552 --- /dev/null +++ b/demo-web-client/src/main/java/com/alibaba/demo/dto/query/PrizeListByParamQuery.java @@ -0,0 +1,20 @@ +package com.alibaba.demo.dto.query; + +import com.alibaba.cola.dto.PageQuery; +import lombok.Data; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.luckyclient.dto.query + * @createTime 2022/12/1 - 22:12 + * @description + */ +@Data +public class PrizeListByParamQuery extends PageQuery { + + private Long id; + + private String prizeName; + + private Integer type; +} diff --git a/demo-web-domain/src/main/java/com/alibaba/demo/domain/acceptprize/AcceptPrizeEntity.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/acceptprize/AcceptPrizeEntity.java new file mode 100644 index 0000000..07ac252 --- /dev/null +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/acceptprize/AcceptPrizeEntity.java @@ -0,0 +1,57 @@ + +package com.alibaba.demo.domain.acceptprize; + +import com.alibaba.cola.domain.Entity; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.luckydomain.acceptprize + * @createTime 2022/12/26 - 22:59 + * @description + */ +@Entity +@Data +public class AcceptPrizeEntity { + /** + * + */ + private Long id; + + /** + * 抽奖记录id + */ + private Long recordId; + + /** + * 电话 + */ + private String phone; + + /** + * 地址 + */ + private String address; + + /** + * + */ + private LocalDateTime createTime; + + /** + * + */ + private String creator; + + /** + * + */ + private LocalDateTime updateTime; + + /** + * + */ + private String updater; +} diff --git a/demo-web-domain/src/main/java/com/alibaba/demo/domain/activity/ActivityEntity.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/activity/ActivityEntity.java new file mode 100644 index 0000000..ed527d7 --- /dev/null +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/activity/ActivityEntity.java @@ -0,0 +1,53 @@ +package com.alibaba.demo.domain.activity; + +import com.alibaba.cola.domain.Entity; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @ClassName ActivityEntity + * @Description 活动实体 + * @Author guocheng + * @Date 2024/2/28 15:19 + * @Version 1.0 + **/ + +@Entity +@Data +public class ActivityEntity { + + + /** + * id + */ + private Long id; + /** + * 活动名称 + */ + private String activityName; + /** + * 活动时间 + */ + private ActivityTime activityTime; + /** + * 活动描述 + */ + private String describe; + /** + * 活动创建时间 + */ + private LocalDateTime createTime; + /** + * 创建人 + */ + private String creator; + /** + * 更新时间 + */ + private LocalDateTime updateTime; + /** + * 更新人 + */ + private String updater; +} diff --git a/demo-web-domain/src/main/java/com/alibaba/demo/domain/activity/ActivityStatusEnum.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/activity/ActivityStatusEnum.java new file mode 100644 index 0000000..d5e1fd2 --- /dev/null +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/activity/ActivityStatusEnum.java @@ -0,0 +1,25 @@ +package com.alibaba.demo.domain.activity; + +import lombok.Getter; + + +@Getter +public enum ActivityStatusEnum { + + NOT_START(0, "未开始"), + + START(1, "进行中"), + + END(2, "已结束"), + + ; + + private Integer value; + + private String description; + + ActivityStatusEnum(Integer value, String description) { + this.value = value; + this.description = description; + } +} diff --git a/demo-web-domain/src/main/java/com/alibaba/demo/domain/activity/ActivityTime.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/activity/ActivityTime.java new file mode 100644 index 0000000..c35da27 --- /dev/null +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/activity/ActivityTime.java @@ -0,0 +1,60 @@ +package com.alibaba.demo.domain.activity; + +import com.alibaba.cola.demo.web.exception.LdException; +import lombok.Getter; + +import java.time.LocalDateTime; +import java.util.Objects; + +/** + * @ClassName ActivityTimeEntity + * @Description TODO + * @Author guocheng + * @Date 2024/2/28 15:27 + * @Version 1.0 + **/ +@Getter +public class ActivityTime { + /** + * startTime + */ + private LocalDateTime startTime; + /** + * endTime + */ + private LocalDateTime endTime; + + + public ActivityTime(LocalDateTime startTime, LocalDateTime endTime) { + + if (Objects.isNull(startTime) || Objects.isNull(endTime)) { + throw new LdException("活动时间不为空"); + } + + if (startTime.isAfter(endTime)) { + //throw new ldException("活动时间非法!"); + throw new LdException("活动时间非法"); + } + + this.startTime = startTime; + this.endTime = endTime; + } + + + public ActivityStatusEnum getStatus() { + return getStatus(LocalDateTime.now()); + } + + public ActivityStatusEnum getStatus(LocalDateTime now) { + + if (now.isBefore(this.startTime)) { + return ActivityStatusEnum.NOT_START; + } + + if (now.isAfter(this.startTime) && now.isBefore(this.endTime)) { + return ActivityStatusEnum.START; + } + + return ActivityStatusEnum.END; + } +} diff --git a/demo-web-domain/src/main/java/com/alibaba/demo/domain/activityrule/ActivityRuleEntity.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/activityrule/ActivityRuleEntity.java new file mode 100644 index 0000000..debecd5 --- /dev/null +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/activityrule/ActivityRuleEntity.java @@ -0,0 +1,50 @@ +package com.alibaba.demo.domain.activityrule; + +import com.alibaba.cola.domain.Entity; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.luckydomain.activityrule + * @createTime 2022/12/4 - 23:02 + * @description + */ +@Entity +@Data +public class ActivityRuleEntity { + + private Long id; + + /** + * 活动id + */ + private Long activityId; + + /** + * 规则id + */ + private Long ruleId; + + /** + * + */ + private LocalDateTime createTime; + + /** + * + */ + private String creator; + + /** + * + */ + private LocalDateTime updateTime; + + /** + * + */ + private String updater; + +} diff --git a/demo-web-domain/src/main/java/com/alibaba/demo/domain/award/AwardEntity.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/award/AwardEntity.java new file mode 100644 index 0000000..cb51651 --- /dev/null +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/award/AwardEntity.java @@ -0,0 +1,74 @@ +package com.alibaba.demo.domain.award; + +import com.alibaba.cola.domain.Entity; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.luckydomain.award + * @createTime 2022/12/2 - 22:25 + * @description + */ +@Entity +@Data +public class AwardEntity { + + /** + * + */ + private Long id; + + /** + * 奖品名称 + */ + private Long prizeId; + private String prizeName; + private Long activityId; + + /** + * 数量(这个属性肯定是要进行判断的,只有符合的值才能设置) + */ + private AwardNumber number; + + /** + * 奖项名称 + */ + private String awardName; + + /** + * 概率 + */ + private Double probability; + + /** + * + */ + private LocalDateTime createTime; + + /** + * + */ + private String creator; + + /** + * + */ + private LocalDateTime updateTime; + + /** + * + */ + private String updater; + + + /** + * 判断该奖项是否是一个奖品,也即该奖项是否中奖 + * + * @return + */ + public Boolean isPrize() { + return !"0".equals(this.prizeId.toString()); + } +} diff --git a/demo-web-domain/src/main/java/com/alibaba/demo/domain/award/AwardNumber.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/award/AwardNumber.java new file mode 100644 index 0000000..4ed3741 --- /dev/null +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/award/AwardNumber.java @@ -0,0 +1,26 @@ +package com.alibaba.demo.domain.award; + +import com.alibaba.cola.demo.web.exception.LdException; +import lombok.Getter; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.luckydomain.award + * @createTime 2022/12/2 - 22:33 + * @description + */ +@Getter +public class AwardNumber { + + private Integer number; + + public AwardNumber(Integer number) { + + if (number < 0) { + throw new LdException("奖项数量不合法,需大于等于 0"); + } + + this.number = number; + } + +} diff --git a/demo-web-domain/src/main/java/com/alibaba/demo/domain/gateway/ActivityGateway.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/gateway/ActivityGateway.java new file mode 100644 index 0000000..9a1fac9 --- /dev/null +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/gateway/ActivityGateway.java @@ -0,0 +1,19 @@ +package com.alibaba.demo.domain.gateway; + + +import com.alibaba.demo.domain.activity.ActivityEntity; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.luckydomain.gateway + * @createTime 2022/12/3 - 0:01 + * @description + */ +public interface ActivityGateway { + + ActivityEntity save(ActivityEntity entity); + + +// IPage page(ActivityListByParamQuery query); + +} diff --git a/demo-web-domain/src/main/java/com/alibaba/demo/domain/gateway/AwardGateway.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/gateway/AwardGateway.java new file mode 100644 index 0000000..ce04b37 --- /dev/null +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/gateway/AwardGateway.java @@ -0,0 +1,19 @@ +package com.alibaba.demo.domain.gateway; + + +import com.alibaba.demo.domain.award.AwardEntity; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.luckydomain.gateway + * @createTime 2022/12/2 - 22:55 + * @description + */ +public interface AwardGateway { + + AwardEntity save(AwardEntity entity); + +// IPage page(AwardListByParamQuery query); + + int deductionAwardNumber(Long awardId, Integer number); +} diff --git a/demo-web-domain/src/main/java/com/alibaba/demo/domain/gateway/PrizeGateway.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/gateway/PrizeGateway.java new file mode 100644 index 0000000..b31ad12 --- /dev/null +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/gateway/PrizeGateway.java @@ -0,0 +1,31 @@ +package com.alibaba.demo.domain.gateway; + + +import com.alibaba.cola.demo.web.vo.PageResultInfo; +import com.alibaba.demo.domain.prize.PrizeEntity; +import com.alibaba.demo.dto.query.PrizeListByParamQuery; + +/** + * @description + */ +public interface PrizeGateway { + + PrizeEntity save(PrizeEntity entity); + + PageResultInfo page(PrizeListByParamQuery query); + +// default PrizeEntity one(Long id) { +// final var query = new PrizeListByParamQuery(); +// query.setId(id); +// PrizeEntity prizeEntity = null; +// try { +// prizeEntity = page(query).getRecords().get(0); +// } catch (Exception e) { +// //错误处理 +// throw new LdException(String.format("奖品id:%s,不存在!", id)); +// } +// return prizeEntity; +// } + + int deductionInventory(Long prizeId, Integer number); +} diff --git a/demo-web-domain/src/main/java/com/alibaba/demo/domain/prize/Inventory.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/prize/Inventory.java new file mode 100644 index 0000000..47b3f13 --- /dev/null +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/prize/Inventory.java @@ -0,0 +1,25 @@ +package com.alibaba.demo.domain.prize; + +import com.alibaba.cola.demo.web.exception.LdException; +import lombok.Getter; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.luckydomain.prize + * @createTime 2022/12/1 - 22:06 + * @description + */ +@Getter +public class Inventory { + + private Integer inventory; + + public Inventory(Integer inventory) { + if (inventory < 0) { + throw new LdException("库存数量请大于等于 0"); + } + this.inventory = inventory; + } + + +} diff --git a/demo-web-domain/src/main/java/com/alibaba/demo/domain/prize/PrizeEntity.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/prize/PrizeEntity.java new file mode 100644 index 0000000..bd47cea --- /dev/null +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/prize/PrizeEntity.java @@ -0,0 +1,63 @@ +package com.alibaba.demo.domain.prize; + +import com.alibaba.cola.domain.Entity; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.luckydomain.prize + * @createTime 2022/12/1 - 22:04 + * @description + */ +@Entity +@Data +public class PrizeEntity { + + /** + * + */ + private Long id; + + /** + * 奖品名称 + */ + private String prizeName; + + /** + * 库存 + */ + private Inventory inventory; + + /** + * 金额 + */ + private BigDecimal money; + + /** + * 类型(1:商品,2:金钱) + */ + private Integer type; + + /** + * + */ + private LocalDateTime createTime; + + /** + * + */ + private String creator; + + /** + * + */ + private LocalDateTime updateTime; + + /** + * + */ + private String updater; +} diff --git a/demo-web-domain/src/main/java/com/alibaba/demo/domain/record/RecordEntity.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/record/RecordEntity.java new file mode 100644 index 0000000..d337722 --- /dev/null +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/record/RecordEntity.java @@ -0,0 +1,77 @@ +package com.alibaba.demo.domain.record; + +import com.alibaba.cola.domain.Entity; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.luckydomain.record + * @createTime 2022/12/9 - 23:04 + * @description + */ +@Entity +@Data +public class RecordEntity { + /** + * + */ + private Long id; + + /** + * 用户id + */ + private Long userId; + + /** + * 活动id + */ + private Long activityId; + + private String activityName; + + /** + * 奖项id + */ + private Long awardId; + + private String awardName; + + private String prizeName; + + private Integer prizeType; + + + /** + * 是否中奖:0未中奖,1中奖 + */ + private Integer isWinning; + + /** + * 状态(0,1,2,3) + */ + private RecordStatus state; + + /** + * + */ + private LocalDateTime createTime; + + /** + * + */ + private String creator; + + /** + * + */ + private LocalDateTime updateTime; + + /** + * + */ + private String updater; + + +} diff --git a/demo-web-domain/src/main/java/com/alibaba/demo/domain/record/RecordStatus.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/record/RecordStatus.java new file mode 100644 index 0000000..e29a0e2 --- /dev/null +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/record/RecordStatus.java @@ -0,0 +1,57 @@ +package com.alibaba.demo.domain.record; + + +import com.alibaba.cola.demo.web.enums.RecordStatusEnum; +import com.alibaba.cola.demo.web.util.AssertUtil; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.luckydomain.record + * @createTime 2022/12/9 - 23:06 + * @description + */ +public class RecordStatus { + + /** + * 状态(0,1,2,3) + */ + private RecordStatusEnum state; + + public Integer getState(){ + return this.state.getValue(); + } + + + public RecordStatus(Integer state) { + AssertUtil.isTrue(state < 0, "记录状态无效!"); + + if (RecordStatusEnum.STATUE_0.getValue() == state){ + this.state = RecordStatusEnum.STATUE_1; + return; + } + + if (RecordStatusEnum.STATUE_1.getValue() == state){ + this.state = RecordStatusEnum.STATUE_1; + return; + } + + if (RecordStatusEnum.STATUE_2.getValue() == state){ + this.state = RecordStatusEnum.STATUE_2; + return; + } + + if (RecordStatusEnum.STATUE_3.getValue() == state){ + this.state = RecordStatusEnum.STATUE_3; + return; + } + + if (RecordStatusEnum.STATUE_4.getValue() == state){ + this.state = RecordStatusEnum.STATUE_4; + return; + } + + AssertUtil.isTrue(true, "记录状态无效!"); + } + + +} diff --git a/demo-web-infrastructure/pom.xml b/demo-web-infrastructure/pom.xml index d8a0f13..d2a6f44 100644 --- a/demo-web-infrastructure/pom.xml +++ b/demo-web-infrastructure/pom.xml @@ -35,5 +35,23 @@ spring-boot-starter-test test + + com.baomidou + mybatis-plus-boot-starter + + + org.mapstruct + mapstruct + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/converter/ActivityConvertor.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/converter/ActivityConvertor.java new file mode 100644 index 0000000..61c11ec --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/converter/ActivityConvertor.java @@ -0,0 +1,23 @@ +package com.alibaba.demo.converter; + +import com.alibaba.demo.database.dataobject.ActivityDO; +import com.alibaba.demo.domain.activity.ActivityEntity; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.luckyinfrastructure.convertor + * @createTime 2022/12/3 - 0:09 + * @description + */ +@Mapper(componentModel = "spring") +public interface ActivityConvertor { + @Mapping(target = "startTime",source = "activityTime.startTime") + @Mapping(target = "endTime",source = "activityTime.endTime") + ActivityDO toActivityDO(ActivityEntity entity); + + @Mapping(target = "activityTime.startTime",source = "startTime") + @Mapping(target = "activityTime.endTime",source = "endTime") + ActivityEntity toEntity(ActivityDO activityDO); +} diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/converter/PrizeConvertor.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/converter/PrizeConvertor.java new file mode 100644 index 0000000..49288e6 --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/converter/PrizeConvertor.java @@ -0,0 +1,30 @@ +package com.alibaba.demo.converter; + +import com.alibaba.cola.demo.web.vo.PageResultInfo; +import com.alibaba.demo.database.dataobject.PrizeDO; +import com.alibaba.demo.domain.prize.PrizeEntity; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; + +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.luckyinfrastructure.convertor + * @createTime 2022/12/3 - 0:09 + * @description + */ +@Mapper(componentModel = "spring") +public interface PrizeConvertor { + @Mapping(target = "inventory",source = "inventory.inventory") + PrizeDO toPrizeDO(PrizeEntity entity); + @Mapping(target = "inventory.inventory",source = "inventory") + PrizeEntity toEntity(PrizeDO activityDO); + + + +} diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/database/dataobject/ActivityDO.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/database/dataobject/ActivityDO.java new file mode 100644 index 0000000..17c4068 --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/database/dataobject/ActivityDO.java @@ -0,0 +1,67 @@ +package com.alibaba.demo.database.dataobject; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * + * @TableName bld_activity + */ +@TableName(value ="activity") +@Data +public class ActivityDO implements Serializable { + /** + * + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 活动名称 + */ + private String activityName; + + /** + * 开始时间 + */ + private LocalDateTime startTime; + + /** + * 结束时间 + */ + private LocalDateTime endTime; + + /** + * 描述 + */ + @TableField("`describe`") + private String describe; + + /** + * + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * + */ + private String creator; + + /** + * + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + /** + * + */ + private String updater; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/customer/CustomerDO.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/database/dataobject/CustomerDO.java similarity index 81% rename from demo-web-infrastructure/src/main/java/com/alibaba/demo/customer/CustomerDO.java rename to demo-web-infrastructure/src/main/java/com/alibaba/demo/database/dataobject/CustomerDO.java index cb1b48f..da9d446 100644 --- a/demo-web-infrastructure/src/main/java/com/alibaba/demo/customer/CustomerDO.java +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/database/dataobject/CustomerDO.java @@ -1,4 +1,4 @@ -package com.alibaba.demo.customer; +package com.alibaba.demo.database.dataobject; import lombok.Data; diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/database/dataobject/PrizeDO.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/database/dataobject/PrizeDO.java new file mode 100644 index 0000000..6e44e8b --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/database/dataobject/PrizeDO.java @@ -0,0 +1,67 @@ +package com.alibaba.demo.database.dataobject; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * + * @TableName bld_prize + */ +@TableName(value ="prize") +@Data +public class PrizeDO implements Serializable { + /** + * + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 奖品名称 + */ + private String prizeName; + + /** + * 库存 + */ + private Integer inventory; + + /** + * 金额 + */ + private BigDecimal money; + + /** + * 类型(1:商品,2:金钱) + */ + private Integer type; + + /** + * + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * + */ + private String creator; + + /** + * + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + /** + * + */ + private String updater; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/ActivityGatewayImpl.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/ActivityGatewayImpl.java new file mode 100644 index 0000000..6b947e2 --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/ActivityGatewayImpl.java @@ -0,0 +1,54 @@ +package com.alibaba.demo.gateway.impl; + +import com.alibaba.cola.demo.web.enums.LdExceptionEnum; +import com.alibaba.cola.demo.web.util.AssertUtil; +import com.alibaba.demo.converter.ActivityConvertor; +import com.alibaba.demo.database.dataobject.ActivityDO; +import com.alibaba.demo.domain.activity.ActivityEntity; +import com.alibaba.demo.domain.gateway.ActivityGateway; +import com.alibaba.demo.mapper.ActivityMapper; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.Objects; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.luckyinfrastructure.gateway.impl + * @createTime 2022/12/3 - 0:08 + * @description + */ +@Slf4j +@Component +@AllArgsConstructor +public class ActivityGatewayImpl implements ActivityGateway { + + private final ActivityMapper activityMapper; + private final ActivityConvertor activityConvertor; + + @Override + public ActivityEntity save(ActivityEntity entity) { + if (Objects.isNull(entity.getId())) { + return addActivity(entity); + } + return updateActivity(entity); + } + + private ActivityEntity updateActivity(ActivityEntity entity) { + ActivityDO activityDB = activityConvertor.toActivityDO(entity); + AssertUtil.isTrue(activityMapper.updateById(activityDB) <= 0, LdExceptionEnum.UPDATE_ERROR.getDescription()); + return activityConvertor.toEntity(activityDB); + } + + + + private ActivityEntity addActivity(ActivityEntity entity) { + ActivityDO activityDB = activityConvertor.toActivityDO(entity); + AssertUtil.isTrue(activityMapper.insert(activityDB) <= 0, LdExceptionEnum.ADD_ERROR.getDescription()); + return activityConvertor.toEntity(activityDB); + } + + + +} diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/AwardGateWayImpl.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/AwardGateWayImpl.java new file mode 100644 index 0000000..1c3368a --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/AwardGateWayImpl.java @@ -0,0 +1,29 @@ +package com.alibaba.demo.gateway.impl; + +import com.alibaba.demo.domain.award.AwardEntity; +import com.alibaba.demo.domain.gateway.AwardGateway; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * @ClassName AwardGateWayImpl + * @Description TODO + * @Author Jincheng.Guo + * @Date 2024/2/28 22:43 + * @Version 1.0 + **/ +@Slf4j +@Component +@AllArgsConstructor +public class AwardGateWayImpl implements AwardGateway { + @Override + public AwardEntity save(AwardEntity entity) { + return null; + } + + @Override + public int deductionAwardNumber(Long awardId, Integer number) { + return 0; + } +} diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/customer/CreditGatewayImpl.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/CreditGatewayImpl.java similarity index 86% rename from demo-web-infrastructure/src/main/java/com/alibaba/demo/customer/CreditGatewayImpl.java rename to demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/CreditGatewayImpl.java index aa92d72..8d40a44 100644 --- a/demo-web-infrastructure/src/main/java/com/alibaba/demo/customer/CreditGatewayImpl.java +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/CreditGatewayImpl.java @@ -1,4 +1,4 @@ -package com.alibaba.demo.customer; +package com.alibaba.demo.gateway.impl; import com.alibaba.demo.domain.customer.Credit; import com.alibaba.demo.domain.customer.gateway.CreditGateway; diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/customer/CustomerGatewayImpl.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/CustomerGatewayImpl.java similarity index 78% rename from demo-web-infrastructure/src/main/java/com/alibaba/demo/customer/CustomerGatewayImpl.java rename to demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/CustomerGatewayImpl.java index 058f89c..ea7cdf1 100644 --- a/demo-web-infrastructure/src/main/java/com/alibaba/demo/customer/CustomerGatewayImpl.java +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/CustomerGatewayImpl.java @@ -1,8 +1,10 @@ -package com.alibaba.demo.customer; +package com.alibaba.demo.gateway.impl; +import com.alibaba.demo.database.dataobject.CustomerDO; import com.alibaba.demo.domain.customer.Customer; import com.alibaba.demo.domain.customer.gateway.CustomerGateway; +import com.alibaba.demo.mapper.CustomerMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/order/OrderGatewayImpl.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/OrderGatewayImpl.java similarity index 47% rename from demo-web-infrastructure/src/main/java/com/alibaba/demo/order/OrderGatewayImpl.java rename to demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/OrderGatewayImpl.java index 1d9e43a..73de19d 100644 --- a/demo-web-infrastructure/src/main/java/com/alibaba/demo/order/OrderGatewayImpl.java +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/OrderGatewayImpl.java @@ -1,4 +1,4 @@ -package com.alibaba.demo.order; +package com.alibaba.demo.gateway.impl; public class OrderGatewayImpl{ diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/PrizeGateWayImpl.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/PrizeGateWayImpl.java new file mode 100644 index 0000000..88b4dc8 --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/PrizeGateWayImpl.java @@ -0,0 +1,80 @@ +package com.alibaba.demo.gateway.impl; + +import com.alibaba.cola.demo.web.enums.LdExceptionEnum; +import com.alibaba.cola.demo.web.util.AssertUtil; +import com.alibaba.cola.demo.web.vo.PageResultInfo; +import com.alibaba.demo.converter.PrizeConvertor; +import com.alibaba.demo.database.dataobject.PrizeDO; +import com.alibaba.demo.domain.gateway.PrizeGateway; +import com.alibaba.demo.domain.prize.PrizeEntity; +import com.alibaba.demo.dto.query.PrizeListByParamQuery; +import com.alibaba.demo.mapper.PrizeMapper; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.Objects; + +/** + * @ClassName PrizeGateWayImpl + * @Description TODO + * @Author Jincheng.Guo + * @Date 2024/2/28 22:43 + * @Version 1.0 + **/ +@Slf4j +@Component +@AllArgsConstructor +public class PrizeGateWayImpl implements PrizeGateway { + + private final PrizeMapper prizeMapper; + private final PrizeConvertor prizeConvertor; + + + @Override + public PrizeEntity save(PrizeEntity entity) { + if (Objects.isNull(entity.getId())){ + return addPrize(entity); + } + return updatePrize(entity); + } + + @Override + public PageResultInfo page(PrizeListByParamQuery query) { + LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery() + .eq(Objects.nonNull(query.getPrizeName()), PrizeDO::getPrizeName, query.getPrizeName()) + .eq(Objects.nonNull(query.getType()), PrizeDO::getType, query.getType()) + .eq(Objects.nonNull(query.getId()), PrizeDO::getId, query.getId()); + Page queryPage = Page.of(query.getPageIndex(), query.getPageSize()); + IPage page = prizeMapper.selectPage(queryPage, queryWrapper); + return PageResultInfo.pageConvert(prizeConvertor::toEntity,page.getRecords(),page.getTotal(),page.getCurrent(),page.getSize()); + } + + + private PrizeEntity updatePrize(PrizeEntity entity) { + PrizeDO prizeDB = prizeConvertor.toPrizeDO(entity); + + AssertUtil.isTrue(prizeMapper.updateById(prizeDB) <= 0, + LdExceptionEnum.UPDATE_ERROR.getDescription()); + + return prizeConvertor.toEntity(prizeDB); + } + + private PrizeEntity addPrize(PrizeEntity entity) { + PrizeDO prizeDB = prizeConvertor.toPrizeDO(entity); + + AssertUtil.isTrue(prizeMapper.insert(prizeDB) <= 0, + LdExceptionEnum.ADD_ERROR.getDescription()); + + return prizeConvertor.toEntity(prizeDB); + } + + @Override + public int deductionInventory(Long prizeId, Integer number) { + return 0; + } +} diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/mapper/ActivityMapper.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/mapper/ActivityMapper.java new file mode 100644 index 0000000..9607ac0 --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/mapper/ActivityMapper.java @@ -0,0 +1,21 @@ +package com.alibaba.demo.mapper; + +import com.alibaba.demo.database.dataobject.ActivityDO; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** +* @author Administrator +* @description 针对表【bld_activity】的数据库操作Mapper +* @createDate 2022-11-26 23:02:19 +* @Entity cn.j3code.lduser.po.Activity +*/ +@Mapper +public interface ActivityMapper extends BaseMapper { + +// IPage page(@Param("activityDBPage") Page activityDBPage, @Param("query") ActivityListByParamQuery query); +} + + + + diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/customer/CustomerMapper.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/mapper/CustomerMapper.java similarity index 59% rename from demo-web-infrastructure/src/main/java/com/alibaba/demo/customer/CustomerMapper.java rename to demo-web-infrastructure/src/main/java/com/alibaba/demo/mapper/CustomerMapper.java index 2ed962d..ed40826 100644 --- a/demo-web-infrastructure/src/main/java/com/alibaba/demo/customer/CustomerMapper.java +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/mapper/CustomerMapper.java @@ -1,5 +1,6 @@ -package com.alibaba.demo.customer; +package com.alibaba.demo.mapper; +import com.alibaba.demo.database.dataobject.CustomerDO; import org.apache.ibatis.annotations.Mapper; @Mapper diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/mapper/PrizeMapper.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/mapper/PrizeMapper.java new file mode 100644 index 0000000..ed96eeb --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/mapper/PrizeMapper.java @@ -0,0 +1,20 @@ +package com.alibaba.demo.mapper; + +import com.alibaba.demo.database.dataobject.PrizeDO; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** +* @description 针对表【bld_activity】的数据库操作Mapper +*/ +@Mapper +public interface PrizeMapper extends BaseMapper { + + + + +} + + + + diff --git a/pom.xml b/pom.xml index 8a8c57d..9ce8b66 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ demo-web - 1.8 + 11 ${maven.compiler.source} UTF-8 UTF-8 @@ -24,6 +24,11 @@ 2.7.2 2.2.2 + + 1.4.2.Final + 5.2.0 + 3.4.3.4 + 1.18.10 @@ -33,6 +38,7 @@ demo-web-domain demo-web-infrastructure start + demo-web-base @@ -46,6 +52,7 @@ junit test + @@ -76,6 +83,11 @@ demo-web-infrastructure ${project.version} + + com.alibaba.cola.demo.web + demo-web-base + ${project.version} + @@ -98,6 +110,27 @@ ${mybatis-starter.version} + + + com.baomidou + mybatis-plus-boot-starter + ${mybatis-plus.version} + + + + + cn.hutool + hutool-all + ${hutool.version} + + + + + org.mapstruct + mapstruct + ${org.mapstruct.version} + + + + + + org.projectlombok + lombok + ${lombok.version} + + + + maven-compiler-plugin + + @@ -132,6 +177,23 @@ maven-compiler-plugin 3.10.1 + + 11 + 11 + + + org.projectlombok + lombok + ${lombok.version} + + + org.mapstruct + mapstruct-processor + ${org.mapstruct.version} + + + + maven-source-plugin diff --git a/start/pom.xml b/start/pom.xml index 7a4d930..4071457 100644 --- a/start/pom.xml +++ b/start/pom.xml @@ -35,5 +35,10 @@ spring-boot-starter-test test + + com.github.xiaoymin + knife4j-openapi2-spring-boot-starter + 4.4.0 + diff --git a/start/src/main/resources/application.properties b/start/src/main/resources/application.properties deleted file mode 100644 index 12ae3de..0000000 --- a/start/src/main/resources/application.properties +++ /dev/null @@ -1,7 +0,0 @@ -project.name=start -server.port=18080 - -spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver -spring.datasource.url=jdbc:mysql://localhost:3306/lotteryDemo -spring.datasource.username=root -spring.datasource.password=123456 diff --git a/start/src/main/resources/application.yml b/start/src/main/resources/application.yml new file mode 100644 index 0000000..e667d70 --- /dev/null +++ b/start/src/main/resources/application.yml @@ -0,0 +1,31 @@ +project: + name: start +server: + port: 18080 +spring: + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + password: 123456 + url: jdbc:mysql://localhost:3306/lotteryDemo + username: root + + +knife4j: + enable: true + openapi: + title: Knife4j官方文档 + description: "`我是测试`,**你知道吗** + # aaa" + email: xiaoymin@foxmail.com + concat: 八一菜刀 + url: https://docs.xiaominfo.com + version: v4.0 + license: Apache 2.0 + license-url: https://stackoverflow.com/ + terms-of-service-url: https://stackoverflow.com/ + group: + test1: + group-name: 分组名称 + api-rule: package + api-rule-resources: + - com.alibaba.demo.web -- Gitee From c859d2b5a8ddfcbbd259f6f86b2f6ea723ee28b1 Mon Sep 17 00:00:00 2001 From: ranyu1998 <2772602769@qq.com> Date: Thu, 7 Mar 2024 17:54:27 +0800 Subject: [PATCH 3/4] =?UTF-8?q?feat(init):=20=E5=AE=8C=E6=88=90=E5=A5=96?= =?UTF-8?q?=E5=93=81=E6=8A=BD=E5=A5=96=E5=B9=B6=E5=8F=91=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../alibaba/demo/web/ActivityController.java | 63 +++++++ .../admin/AdminActivityConfigController.java | 22 ++- .../demo/web/admin/AdminAwardController.java | 59 +++++++ .../demo/web/admin/AdminPrizeController.java | 6 +- demo-web-app/pom.xml | 2 + .../activity/ActivityConfigServiceImpl.java | 81 ++++++++- .../demo/activity/ActivityServiceImpl.java | 113 +++++++++++++ .../activity/command/ActivityAddCmdExe.java | 5 +- .../demo/activity/command/BaseDrawCmdExe.java | 69 ++++++++ .../CacheDeductionAwardInventoryDrawExe.java | 73 ++++++++ .../activity/command/DefaultDrawCmdExe.java | 158 ++++++++++++++++++ .../query/ActivityListByParamQueryExe.java | 31 ++++ .../demo/assembler/ActivityAssembler.java | 62 ++----- .../demo/assembler/RecordAssembler.java | 30 ++++ .../alibaba/demo/award/AwardServiceImpl.java | 50 ++++++ .../demo/award/command/AwardAddCmdExe.java | 34 +++- .../award/command/AwardAlgorithmCmdExe.java | 17 ++ .../WeightRandomAwardAlgorithmCmdExe.java | 32 ++++ .../award/query/AwardListByParamQueryExe.java | 31 ++++ .../demo/context/ActivityDrawContext.java | 39 +++++ .../AwardInventory2CacheListener.java | 46 +++++ .../listener/event/ActivityCreatedEvent.java | 25 +++ .../demo/listener/event/UserWinEvent.java | 27 +++ .../alibaba/demo/prize/PrizeServiceImpl.java | 14 +- .../demo/prize/command/PrizeAddCmdExe.java | 1 - .../demo/record/command/RecordAddCmdExe.java | 25 +++ .../ActivityConfigServiceImplTest.java | 103 ++++++++++++ .../cola/demo/web/enums/RecordStatusEnum.java | 8 + .../web/handler/ResponseResultHandler.java | 66 ++++++++ .../cola/demo/web/util/SecurityUtil.java | 7 +- .../cola/demo/web/vo/PageResultInfo.java | 13 +- .../demo/api/ActivityDecoratorService.java | 43 +++++ .../demo/api/IActivityConfigService.java | 4 + .../alibaba/demo/api/IActivityService.java | 28 ++++ .../com/alibaba/demo/api/IAwardService.java | 20 +++ .../com/alibaba/demo/dto/ActivityAddCmd.java | 3 + .../com/alibaba/demo/dto/ActivityDrawCmd.java | 31 ++++ .../com/alibaba/demo/dto/AwardAddCmd.java | 4 + .../com/alibaba/demo/dto/PrizeAddCmd.java | 3 + .../com/alibaba/demo/dto/RecordAddCmd.java | 46 +++++ .../alibaba/demo/dto/data/DrawResultVO.java | 16 ++ .../com/alibaba/demo/dto/data/RecordVO.java | 68 ++++++++ .../dto/query/ActivityListByParamQuery.java | 39 +++++ .../demo/dto/query/AwardListByParamQuery.java | 22 +++ .../dto/query/RecordListByParamQuery.java | 28 ++++ .../demo/domain/activity/ActivityTime.java | 5 +- .../demo/domain/award/AwardEntity.java | 8 +- .../domain/gateway/ActivityCacheGateWay.java | 39 +++++ .../demo/domain/gateway/ActivityGateway.java | 4 +- .../domain/gateway/AwardCacheGateWay.java | 39 +++++ .../demo/domain/gateway/AwardGateway.java | 4 +- .../demo/domain/gateway/RecordGateway.java | 19 +++ .../demo/domain/prize/PrizeEntity.java | 7 + .../demo/domain/record/RecordStatus.java | 5 + demo-web-infrastructure/pom.xml | 8 + .../demo/config/MyMetaObjectHandler.java | 37 ++++ .../demo/config/MybatisPlusConfig.java | 28 ++++ .../com/alibaba/demo/config/RedisConfig.java | 107 ++++++++++++ .../demo/converter/AwardConvertor.java | 21 +++ .../demo/converter/RecordConvertor.java | 26 +++ .../demo/database/dataobject/ActivityDO.java | 26 +-- .../demo/database/dataobject/AwardDO.java | 46 +++++ .../demo/database/dataobject/BaseDO.java | 43 +++++ .../demo/database/dataobject/PrizeDO.java | 26 +-- .../demo/database/dataobject/RecordDO.java | 60 +++++++ .../gateway/impl/ActivityGatewayImpl.java | 19 +++ .../impl/ActivityRedisCacheGatewayImpl.java | 58 +++++++ .../demo/gateway/impl/AwardGateWayImpl.java | 58 ++++++- .../impl/AwardRedisCacheGatewayImpl.java | 115 +++++++++++++ .../demo/gateway/impl/PrizeGateWayImpl.java | 4 +- .../demo/gateway/impl/RecordGatewayImpl.java | 49 ++++++ .../com/alibaba/demo/mapper/AwardMapper.java | 28 ++++ .../com/alibaba/demo/mapper/PrizeMapper.java | 5 + .../com/alibaba/demo/mapper/RecordMapper.java | 27 +++ .../{mybatis => }/mybatis-config.xml | 0 .../main/resources/mybatis/AwardMapper.xml | 11 ++ .../main/resources/mybatis/PrizeMapper.xml | 10 ++ .../impl/AwardRedisCacheGatewayImplTest.java | 78 +++++++++ .../alibaba/demo/mapper/AwardMapperTest.java | 50 ++++++ .../alibaba/demo/mapper/PrizeMapperTest.java | 33 ++++ .../alibaba/demo/mapper/RecordMapperTest.java | 38 +++++ .../demo/repository/RedisCacheTest.java | 76 +++++++++ .../test/resources/lua/stock_deduction.lua | 15 ++ .../src/test/resources/lua/stock_rollback.lua | 7 + .../src/test/resources/mybatis-config.xml | 22 +++ .../AwardMapperTestConfiguration.xml | 25 +++ .../RecordMapperTestConfiguration.xml | 25 +++ pom.xml | 32 ++++ .../main/java/com/alibaba/demo/HelloWorld.lua | 3 + start/src/main/resources/application.yml | 4 + start/src/main/resources/lua/HelloWorld.lua | 9 + .../main/resources/lua/stock_deduction.lua | 16 ++ .../src/main/resources/lua/stock_rollback.lua | 9 + 93 files changed, 2926 insertions(+), 125 deletions(-) create mode 100644 demo-web-adapter/src/main/java/com/alibaba/demo/web/ActivityController.java create mode 100644 demo-web-adapter/src/main/java/com/alibaba/demo/web/admin/AdminAwardController.java create mode 100644 demo-web-app/src/main/java/com/alibaba/demo/activity/ActivityServiceImpl.java create mode 100644 demo-web-app/src/main/java/com/alibaba/demo/activity/command/BaseDrawCmdExe.java create mode 100644 demo-web-app/src/main/java/com/alibaba/demo/activity/command/CacheDeductionAwardInventoryDrawExe.java create mode 100644 demo-web-app/src/main/java/com/alibaba/demo/activity/command/DefaultDrawCmdExe.java create mode 100644 demo-web-app/src/main/java/com/alibaba/demo/activity/query/ActivityListByParamQueryExe.java create mode 100644 demo-web-app/src/main/java/com/alibaba/demo/assembler/RecordAssembler.java create mode 100644 demo-web-app/src/main/java/com/alibaba/demo/award/AwardServiceImpl.java create mode 100644 demo-web-app/src/main/java/com/alibaba/demo/award/command/AwardAlgorithmCmdExe.java create mode 100644 demo-web-app/src/main/java/com/alibaba/demo/award/command/WeightRandomAwardAlgorithmCmdExe.java create mode 100644 demo-web-app/src/main/java/com/alibaba/demo/award/query/AwardListByParamQueryExe.java create mode 100644 demo-web-app/src/main/java/com/alibaba/demo/context/ActivityDrawContext.java create mode 100644 demo-web-app/src/main/java/com/alibaba/demo/listener/AwardInventory2CacheListener.java create mode 100644 demo-web-app/src/main/java/com/alibaba/demo/listener/event/ActivityCreatedEvent.java create mode 100644 demo-web-app/src/main/java/com/alibaba/demo/listener/event/UserWinEvent.java create mode 100644 demo-web-app/src/main/java/com/alibaba/demo/record/command/RecordAddCmdExe.java create mode 100644 demo-web-app/src/test/java/com/alibaba/demo/activity/ActivityConfigServiceImplTest.java create mode 100644 demo-web-base/src/main/java/com/alibaba/cola/demo/web/handler/ResponseResultHandler.java create mode 100644 demo-web-client/src/main/java/com/alibaba/demo/api/ActivityDecoratorService.java create mode 100644 demo-web-client/src/main/java/com/alibaba/demo/api/IActivityService.java create mode 100644 demo-web-client/src/main/java/com/alibaba/demo/api/IAwardService.java create mode 100644 demo-web-client/src/main/java/com/alibaba/demo/dto/ActivityDrawCmd.java create mode 100644 demo-web-client/src/main/java/com/alibaba/demo/dto/RecordAddCmd.java create mode 100644 demo-web-client/src/main/java/com/alibaba/demo/dto/data/DrawResultVO.java create mode 100644 demo-web-client/src/main/java/com/alibaba/demo/dto/data/RecordVO.java create mode 100644 demo-web-client/src/main/java/com/alibaba/demo/dto/query/ActivityListByParamQuery.java create mode 100644 demo-web-client/src/main/java/com/alibaba/demo/dto/query/AwardListByParamQuery.java create mode 100644 demo-web-client/src/main/java/com/alibaba/demo/dto/query/RecordListByParamQuery.java create mode 100644 demo-web-domain/src/main/java/com/alibaba/demo/domain/gateway/ActivityCacheGateWay.java create mode 100644 demo-web-domain/src/main/java/com/alibaba/demo/domain/gateway/AwardCacheGateWay.java create mode 100644 demo-web-domain/src/main/java/com/alibaba/demo/domain/gateway/RecordGateway.java create mode 100644 demo-web-infrastructure/src/main/java/com/alibaba/demo/config/MyMetaObjectHandler.java create mode 100644 demo-web-infrastructure/src/main/java/com/alibaba/demo/config/MybatisPlusConfig.java create mode 100644 demo-web-infrastructure/src/main/java/com/alibaba/demo/config/RedisConfig.java create mode 100644 demo-web-infrastructure/src/main/java/com/alibaba/demo/converter/AwardConvertor.java create mode 100644 demo-web-infrastructure/src/main/java/com/alibaba/demo/converter/RecordConvertor.java create mode 100644 demo-web-infrastructure/src/main/java/com/alibaba/demo/database/dataobject/AwardDO.java create mode 100644 demo-web-infrastructure/src/main/java/com/alibaba/demo/database/dataobject/BaseDO.java create mode 100644 demo-web-infrastructure/src/main/java/com/alibaba/demo/database/dataobject/RecordDO.java create mode 100644 demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/ActivityRedisCacheGatewayImpl.java create mode 100644 demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/AwardRedisCacheGatewayImpl.java create mode 100644 demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/RecordGatewayImpl.java create mode 100644 demo-web-infrastructure/src/main/java/com/alibaba/demo/mapper/AwardMapper.java create mode 100644 demo-web-infrastructure/src/main/java/com/alibaba/demo/mapper/RecordMapper.java rename demo-web-infrastructure/src/main/resources/{mybatis => }/mybatis-config.xml (100%) create mode 100644 demo-web-infrastructure/src/main/resources/mybatis/AwardMapper.xml create mode 100644 demo-web-infrastructure/src/main/resources/mybatis/PrizeMapper.xml create mode 100644 demo-web-infrastructure/src/test/java/com/alibaba/demo/gateway/impl/AwardRedisCacheGatewayImplTest.java create mode 100644 demo-web-infrastructure/src/test/java/com/alibaba/demo/mapper/AwardMapperTest.java create mode 100644 demo-web-infrastructure/src/test/java/com/alibaba/demo/mapper/PrizeMapperTest.java create mode 100644 demo-web-infrastructure/src/test/java/com/alibaba/demo/mapper/RecordMapperTest.java create mode 100644 demo-web-infrastructure/src/test/java/com/alibaba/demo/repository/RedisCacheTest.java create mode 100644 demo-web-infrastructure/src/test/resources/lua/stock_deduction.lua create mode 100644 demo-web-infrastructure/src/test/resources/lua/stock_rollback.lua create mode 100644 demo-web-infrastructure/src/test/resources/mybatis-config.xml create mode 100644 demo-web-infrastructure/src/test/resources/mybatisTestConfiguration/AwardMapperTestConfiguration.xml create mode 100644 demo-web-infrastructure/src/test/resources/mybatisTestConfiguration/RecordMapperTestConfiguration.xml create mode 100644 start/src/main/java/com/alibaba/demo/HelloWorld.lua create mode 100644 start/src/main/resources/lua/HelloWorld.lua create mode 100644 start/src/main/resources/lua/stock_deduction.lua create mode 100644 start/src/main/resources/lua/stock_rollback.lua diff --git a/demo-web-adapter/src/main/java/com/alibaba/demo/web/ActivityController.java b/demo-web-adapter/src/main/java/com/alibaba/demo/web/ActivityController.java new file mode 100644 index 0000000..222dfb7 --- /dev/null +++ b/demo-web-adapter/src/main/java/com/alibaba/demo/web/ActivityController.java @@ -0,0 +1,63 @@ +package com.alibaba.demo.web; + +import com.alibaba.cola.demo.web.vo.PageResultInfo; +import com.alibaba.demo.api.ActivityDecoratorService; +import com.alibaba.demo.api.IActivityConfigService; +import com.alibaba.demo.api.IActivityService; +import com.alibaba.demo.dto.data.ActivityConfigVO; +import com.alibaba.demo.dto.data.ActivityVO; +import com.alibaba.demo.dto.data.DrawResultVO; +import com.alibaba.demo.dto.query.ActivityListByParamQuery; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.web.bind.annotation.*; + +/** + * 活动接口-用户端 + * @package cn.j3code.luckyadapter.web + * @createTime 2022/12/6 - 22:47 + * @description + */ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("/v1/activity") +public class ActivityController { + + + + @Autowired + @Qualifier("activityService") + private ActivityDecoratorService activityService; + + + + + /** + * 活动分页 + **/ + @PostMapping("/page") + public PageResultInfo page(@RequestBody ActivityListByParamQuery query) { + return activityService.page(query); + } + + /** + * 活动详情 + **/ + @GetMapping("/one") + public ActivityConfigVO one(@RequestParam("id") Long id) { + return activityService.one(id); + } + + + /** + * 活动抽奖 + **/ + @GetMapping("/draw") + public DrawResultVO draw(@RequestParam("activityId") Long activityId) { + return activityService.draw(activityId); + } + +} diff --git a/demo-web-adapter/src/main/java/com/alibaba/demo/web/admin/AdminActivityConfigController.java b/demo-web-adapter/src/main/java/com/alibaba/demo/web/admin/AdminActivityConfigController.java index 59b8c7a..5370e1e 100644 --- a/demo-web-adapter/src/main/java/com/alibaba/demo/web/admin/AdminActivityConfigController.java +++ b/demo-web-adapter/src/main/java/com/alibaba/demo/web/admin/AdminActivityConfigController.java @@ -1,10 +1,13 @@ package com.alibaba.demo.web.admin; +import com.alibaba.cola.demo.web.config.validate.AddGroup; import com.alibaba.demo.api.IActivityConfigService; import com.alibaba.demo.dto.ActivityConfigAddCmd; import com.alibaba.demo.dto.data.ActivityConfigVO; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -22,13 +25,15 @@ import org.springframework.web.bind.annotation.*; @RequestMapping("/admin/v1/activityConfig") public class AdminActivityConfigController { - private final IActivityConfigService activityConfigService; + @Qualifier("activityConfigService") + @Autowired + private IActivityConfigService activityConfigService; /** * 添加活动配置 **/ @PostMapping("/add") - public ActivityConfigVO add(@Validated @RequestBody ActivityConfigAddCmd cmd){ + public ActivityConfigVO add(@Validated(value = {AddGroup.class}) @RequestBody ActivityConfigAddCmd cmd){ return activityConfigService.add(cmd); } @@ -45,4 +50,17 @@ public class AdminActivityConfigController { // //// return activityConfigService.copy(id); // } + + + /** + * 刷新活动奖项库存 + **/ + @PostMapping("/refresh-inventory/{id}") + public Boolean refreshInventory(@PathVariable(name = "id") Long activityId) { + return activityConfigService.refreshInventory(activityId); + } + + + + } diff --git a/demo-web-adapter/src/main/java/com/alibaba/demo/web/admin/AdminAwardController.java b/demo-web-adapter/src/main/java/com/alibaba/demo/web/admin/AdminAwardController.java new file mode 100644 index 0000000..cc729a7 --- /dev/null +++ b/demo-web-adapter/src/main/java/com/alibaba/demo/web/admin/AdminAwardController.java @@ -0,0 +1,59 @@ +package com.alibaba.demo.web.admin; + +import com.alibaba.cola.demo.web.vo.PageResultInfo; +import com.alibaba.demo.api.IAwardService; +import com.alibaba.demo.dto.AwardAddCmd; +import com.alibaba.demo.dto.data.AwardVO; +import com.alibaba.demo.dto.query.AwardListByParamQuery; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +/** + * 奖项配置接口 + **/ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("/admin/v1/award") +public class AdminAwardController { + + private final IAwardService awardService; + + /** + * 添加奖项 + **/ + @PostMapping("/add") + public AwardVO add(@Validated @RequestBody AwardAddCmd cmd) { + return awardService.add(cmd); + } + + /** + * 更新奖项 + **/ + @PostMapping("/update") + public AwardVO update(@Validated @RequestBody AwardAddCmd cmd) { + return awardService.update(cmd); + } + + /** + * 奖项详情 + **/ + @GetMapping("/{id}") + public AwardVO one(@PathVariable(name = "id") Long id) { + return awardService.one(id); + } + + /** + * 奖项分页 + **/ + @PostMapping("/page") + public PageResultInfo page(@RequestBody AwardListByParamQuery query) { + return awardService.page(query); + } + + + + + +} diff --git a/demo-web-adapter/src/main/java/com/alibaba/demo/web/admin/AdminPrizeController.java b/demo-web-adapter/src/main/java/com/alibaba/demo/web/admin/AdminPrizeController.java index d119f3b..cfac27b 100644 --- a/demo-web-adapter/src/main/java/com/alibaba/demo/web/admin/AdminPrizeController.java +++ b/demo-web-adapter/src/main/java/com/alibaba/demo/web/admin/AdminPrizeController.java @@ -1,5 +1,7 @@ package com.alibaba.demo.web.admin; +import com.alibaba.cola.demo.web.config.validate.AddGroup; +import com.alibaba.cola.demo.web.config.validate.UpdateGroup; import com.alibaba.cola.demo.web.vo.PageResultInfo; import com.alibaba.demo.api.IPrizeService; import com.alibaba.demo.dto.PrizeAddCmd; @@ -26,7 +28,7 @@ public class AdminPrizeController { * 添加奖品 **/ @PostMapping("/add") - public PrizeVO add(@Validated @RequestBody PrizeAddCmd cmd) { + public PrizeVO add(@Validated(value = {AddGroup.class}) @RequestBody PrizeAddCmd cmd) { return prizeService.add(cmd); } @@ -34,7 +36,7 @@ public class AdminPrizeController { * 修改奖品 **/ @PostMapping("/update") - public PrizeVO update(@Validated @RequestBody PrizeAddCmd cmd) { + public PrizeVO update(@Validated(value = {UpdateGroup.class}) @RequestBody PrizeAddCmd cmd) { return prizeService.update(cmd); } diff --git a/demo-web-app/pom.xml b/demo-web-app/pom.xml index 96ee377..2104a79 100644 --- a/demo-web-app/pom.xml +++ b/demo-web-app/pom.xml @@ -46,5 +46,7 @@ cn.hutool hutool-all + + diff --git a/demo-web-app/src/main/java/com/alibaba/demo/activity/ActivityConfigServiceImpl.java b/demo-web-app/src/main/java/com/alibaba/demo/activity/ActivityConfigServiceImpl.java index 528811e..4afe529 100644 --- a/demo-web-app/src/main/java/com/alibaba/demo/activity/ActivityConfigServiceImpl.java +++ b/demo-web-app/src/main/java/com/alibaba/demo/activity/ActivityConfigServiceImpl.java @@ -1,10 +1,17 @@ package com.alibaba.demo.activity; import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.NumberUtil; +import com.alibaba.cola.demo.web.exception.LdException; import com.alibaba.cola.demo.web.util.AssertUtil; +import com.alibaba.cola.demo.web.vo.PageResultInfo; import com.alibaba.demo.activity.command.ActivityAddCmdExe; +import com.alibaba.demo.activity.query.ActivityListByParamQueryExe; import com.alibaba.demo.api.IActivityConfigService; import com.alibaba.demo.award.command.AwardAddCmdExe; +import com.alibaba.demo.award.query.AwardListByParamQueryExe; +import com.alibaba.demo.domain.gateway.AwardCacheGateWay; +import com.alibaba.demo.domain.gateway.AwardGateway; import com.alibaba.demo.dto.ActivityConfigAddCmd; import com.alibaba.demo.dto.ActivityConfigUpdateCmd; import com.alibaba.demo.dto.AwardAddCmd; @@ -12,13 +19,20 @@ import com.alibaba.demo.dto.data.ActivityConfigVO; import com.alibaba.demo.dto.data.ActivityVO; import com.alibaba.demo.dto.data.AwardVO; import com.alibaba.demo.dto.data.RuleVO; +import com.alibaba.demo.dto.query.ActivityListByParamQuery; +import com.alibaba.demo.dto.query.AwardListByParamQuery; +import com.alibaba.demo.listener.event.ActivityCreatedEvent; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.context.event.ApplicationEventMulticaster; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.time.Duration; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; /** @@ -29,12 +43,16 @@ import java.util.stream.Collectors; * @Version 1.0 **/ @Slf4j -@Service +@Service("activityConfigService") @AllArgsConstructor public class ActivityConfigServiceImpl implements IActivityConfigService { private final ActivityAddCmdExe activityAddCmdExe; private final AwardAddCmdExe awardAddCmdExe; + private final ActivityListByParamQueryExe activityListByParamQueryExe; + private final AwardListByParamQueryExe awardListByParamQueryExe; + private final ApplicationEventMulticaster applicationEventMulticaster; + private final AwardCacheGateWay awardCacheGateWay; @Transactional(rollbackFor = Exception.class) @@ -52,9 +70,11 @@ public class ActivityConfigServiceImpl implements IActivityConfigService { activityConfigVO.setActivityVO(activityVO); activityConfigVO.setRuleVOList(null); activityConfigVO.setAwardVOList(awardVOList); - // 发布活动创建事件 + // 发送活动创建事件 + applicationEventMulticaster.multicastEvent(new ActivityCreatedEvent("", activityConfigVO)); + return activityConfigVO; } @@ -65,7 +85,42 @@ public class ActivityConfigServiceImpl implements IActivityConfigService { @Override public ActivityConfigVO one(Long id) { - return null; + // 查询活动信息 + ActivityListByParamQuery activityListByParamQuery = new ActivityListByParamQuery(); + activityListByParamQuery.setId(id); + PageResultInfo pageResultInfo = activityListByParamQueryExe.execute(activityListByParamQuery); + List activityVOS = Optional.ofNullable(pageResultInfo).map(PageResultInfo::getData) + .orElseGet(ArrayList::new); + AssertUtil.isTrue(CollectionUtil.isEmpty(activityVOS), "数据不存在!"); + ActivityVO activityVO = activityVOS.get(0); + // 查询活动规则信息 todo + + // 查询活动奖项信息 + AwardListByParamQuery awardListByParamQuery = new AwardListByParamQuery(); + awardListByParamQuery.setActivityId(activityVO.getId()); + awardListByParamQuery.setPageSize(100); + List awardVOList = Optional.ofNullable(awardListByParamQueryExe.execute(awardListByParamQuery)) + .map(PageResultInfo::getData) + .orElseGet(ArrayList::new); + + + ActivityConfigVO activityConfigVO = new ActivityConfigVO(); + activityConfigVO.setActivityVO(activityVO); +// activityConfigVO.setRuleVOList(ruleVOList); + activityConfigVO.setAwardVOList(awardVOList); + return activityConfigVO; + } + + @Override + public boolean refreshInventory(Long activityId) { + Optional activityConfigVO = Optional.ofNullable(one(activityId)); + LocalDateTime endTime = activityConfigVO.map(ActivityConfigVO::getActivityVO).map(ActivityVO::getEndTime).orElseThrow(() -> new LdException("活动信息不完整")); + Duration between = Duration.between(LocalDateTime.now(), endTime); + boolean awardInventory = awardCacheGateWay.setAwardInventory(activityConfigVO.map(ActivityConfigVO::getAwardVOList).orElseGet(ArrayList::new), between); + log.info("ActivityCreateEvent_ActivityId:{},存入Redis库存:{} ", + activityConfigVO.map(ActivityConfigVO::getActivityVO).map(ActivityVO::getId).orElse(null), + awardInventory); + return awardInventory; } @@ -86,7 +141,7 @@ public class ActivityConfigServiceImpl implements IActivityConfigService { private List addAward(ActivityVO activityVO, List awardAddCmdList) { AssertUtil.isTrue(CollectionUtil.isEmpty(awardAddCmdList), "奖项不为空!"); - + checkTotalProbabilityEqualOne(awardAddCmdList); List result = new ArrayList<>(); for (AwardAddCmd awardAddCmd : awardAddCmdList) { awardAddCmd.setActivityId(activityVO.getId()); @@ -95,4 +150,22 @@ public class ActivityConfigServiceImpl implements IActivityConfigService { return result; } + + /** + * @Author guocheng + * @Description 校验所有奖项概率和为1 + * @Date 11:32 2024/3/5 + * @Param [awardAddCmdList] + * @return void + **/ + private void checkTotalProbabilityEqualOne(List awardAddCmdList) { + double sumProbability = awardAddCmdList.stream() + .mapToDouble(AwardAddCmd::getProbability) + .sum(); + int compare = NumberUtil.compare(1, sumProbability); + if(compare<0){ + throw new LdException("奖项概率之和不能超过1"); + } + + } } diff --git a/demo-web-app/src/main/java/com/alibaba/demo/activity/ActivityServiceImpl.java b/demo-web-app/src/main/java/com/alibaba/demo/activity/ActivityServiceImpl.java new file mode 100644 index 0000000..050d763 --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/activity/ActivityServiceImpl.java @@ -0,0 +1,113 @@ +package com.alibaba.demo.activity; + +import cn.hutool.crypto.digest.DigestUtil; +import com.alibaba.cola.demo.web.util.AssertUtil; +import com.alibaba.cola.demo.web.vo.PageResultInfo; +import com.alibaba.demo.activity.command.BaseDrawCmdExe; +import com.alibaba.demo.activity.command.CacheDeductionAwardInventoryDrawExe; +import com.alibaba.demo.activity.query.ActivityListByParamQueryExe; +import com.alibaba.demo.api.ActivityDecoratorService; +import com.alibaba.demo.api.IActivityService; +import com.alibaba.demo.assembler.ActivityAssembler; +import com.alibaba.demo.context.ActivityDrawContext; +import com.alibaba.demo.domain.activity.ActivityEntity; +import com.alibaba.demo.domain.gateway.ActivityCacheGateWay; +import com.alibaba.demo.domain.gateway.ActivityGateway; +import com.alibaba.demo.dto.data.ActivityConfigVO; +import com.alibaba.demo.dto.data.ActivityVO; +import com.alibaba.demo.dto.data.DrawResultVO; +import com.alibaba.demo.dto.query.ActivityListByParamQuery; +import com.alibaba.fastjson.JSON; +import lombok.AllArgsConstructor; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.web.bind.annotation.RestController; + +import java.time.Duration; +import java.util.Objects; +import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +/** + * @ClassName ActivityServiceImpl + * @Description TODO + * @Author Jincheng.Guo + * @Date 2024/3/1 18:47 + * @Version 1.0 + **/ +@Slf4j +@Service("activityService") +@RequiredArgsConstructor +public class ActivityServiceImpl extends ActivityDecoratorService { + + private final ActivityListByParamQueryExe activityListByParamQueryExe; + private final ActivityCacheGateWay activityCacheGateWay; + private final ActivityGateway activityGateway; + private final ActivityAssembler activityAssembler; +// private final BaseDrawCmdExe drawCmdExe; + private final CacheDeductionAwardInventoryDrawExe drawCmdExe; + + + private ReentrantReadWriteLock reentrantReadWriteLock=new ReentrantReadWriteLock(); + private ReentrantReadWriteLock.ReadLock readLock=reentrantReadWriteLock.readLock(); + private ReentrantReadWriteLock.WriteLock writeLock=reentrantReadWriteLock.writeLock(); + + + @Override + public PageResultInfo page(ActivityListByParamQuery query) { + String cacheKey = "activityPageQuery_"+DigestUtil.md5Hex(JSON.toJSONString(query)); + // 查询缓存活动列表 + PageResultInfo pageResultInfoCache = activityCacheGateWay.page(cacheKey); + if(Objects.nonNull(pageResultInfoCache)){ + return pageResultInfoCache; + } + // 查询数据库酒店列表 + PageResultInfo page = activityGateway.page(query); + if(Objects.nonNull(page)){ + pageResultInfoCache=page.convert(activityAssembler::toActivityVO); + boolean cacheTag = activityCacheGateWay.setPage(pageResultInfoCache, cacheKey, Duration.ofMinutes(10)); + AssertUtil.isFalse(cacheTag,"缓存数据失败"); + } + return pageResultInfoCache; + } + + + @Override + public ActivityConfigVO one(Long id) { + // 查询详情缓存 + String cacheKey; + ActivityConfigVO activityConfigVO; + readLock.lock(); + try { + cacheKey = "activity_"+id; + activityConfigVO = activityCacheGateWay.one(cacheKey); + if(Objects.nonNull(activityConfigVO)){ + return activityConfigVO; + } + } finally { + this.readLock.unlock(); + } + // 查询详情数据库(同一个时间只允许一个人更新数据库) + boolean writeLockTag = writeLock.tryLock(); + AssertUtil.isFalse(writeLockTag,"缓存数据失败"); + try { + activityConfigVO = super.one(id); + boolean cacheTag = activityCacheGateWay.setOne(activityConfigVO, cacheKey, Duration.ofMinutes(10)); + AssertUtil.isFalse(cacheTag,"缓存数据失败"); + return activityConfigVO; + } finally { + writeLock.unlock(); + } + } + + @Override + public DrawResultVO draw(Long activityId) { + log.info("开始抽奖,活动:{}",activityId); + //查询活动详情 + ActivityConfigVO activityConfigVO = one(activityId); + ActivityDrawContext activityDrawContext = new ActivityDrawContext(); + activityDrawContext.setActivityConfigVO(activityConfigVO); + return drawCmdExe.execute(activityDrawContext); + } +} diff --git a/demo-web-app/src/main/java/com/alibaba/demo/activity/command/ActivityAddCmdExe.java b/demo-web-app/src/main/java/com/alibaba/demo/activity/command/ActivityAddCmdExe.java index 47fa957..60f1af2 100644 --- a/demo-web-app/src/main/java/com/alibaba/demo/activity/command/ActivityAddCmdExe.java +++ b/demo-web-app/src/main/java/com/alibaba/demo/activity/command/ActivityAddCmdExe.java @@ -21,9 +21,10 @@ import org.springframework.stereotype.Component; public class ActivityAddCmdExe { private final ActivityGateway activityGateway; + private final ActivityAssembler activityAssembler; public ActivityVO execute(ActivityAddCmd cmd) { - ActivityEntity entity = activityGateway.save(ActivityAssembler.toAddEntity(cmd)); - return ActivityAssembler.toActivityVO(entity); + ActivityEntity entity = activityGateway.save(activityAssembler.toAddEntity(cmd)); + return activityAssembler.toActivityVO(entity); } } diff --git a/demo-web-app/src/main/java/com/alibaba/demo/activity/command/BaseDrawCmdExe.java b/demo-web-app/src/main/java/com/alibaba/demo/activity/command/BaseDrawCmdExe.java new file mode 100644 index 0000000..0e4d93b --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/activity/command/BaseDrawCmdExe.java @@ -0,0 +1,69 @@ +package com.alibaba.demo.activity.command; + +import cn.hutool.core.collection.CollectionUtil; +import com.alibaba.demo.context.ActivityDrawContext; +import com.alibaba.demo.domain.prize.PrizeEntity; +import com.alibaba.demo.dto.data.ActivityConfigVO; +import com.alibaba.demo.dto.data.ActivityVO; +import com.alibaba.demo.dto.data.AwardVO; +import com.alibaba.demo.dto.data.DrawResultVO; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +public abstract class BaseDrawCmdExe { + + + + + + + + public final DrawResultVO execute(ActivityDrawContext context) { + //1 校验阶段 + // 1.1 校验活动时间 + checkActivityTime(context.getActivityConfigVO().getActivityVO()); + // 1.2 校验活动规则 + checkActivityRule(context.getActivityConfigVO()); + //2 抽奖阶段 + // 2.1 剔除库存为空的奖项 + List awardVOList = removeAwardInventoryNull(context.getActivityConfigVO().getAwardVOList()); + // 2.2 调用抽奖算法进行抽奖 + invokeDrawAlgorithm(context,awardVOList); + //3 中奖阶段 + // 3.1 中奖奖品库存扣减 + // 3.2 中奖记录插入 + drawAfter(context); + // 构建中奖结果 + return getDrawResultVO(context); + } + + + /** + * 钩子函数:奖项是否需要扣减库存(特殊奖品,比如谢谢惠顾不需要扣除库存) + **/ + protected abstract boolean needDeductNumber(ActivityDrawContext context) ; + + protected abstract void invokeDrawAlgorithm(ActivityDrawContext context,List awardVOList) ; + + + protected abstract DrawResultVO getDrawResultVO(ActivityDrawContext context); + + protected abstract void drawAfter(ActivityDrawContext context); + + private List removeAwardInventoryNull(List awardVOList) { + if (CollectionUtil.isEmpty(awardVOList)) { + return new ArrayList<>(); + } + return awardVOList.stream() + // 过滤库存大于0和谢谢惠顾奖项 + .filter(item -> item.getNumber() > 0 || PrizeEntity.THINKS_PRIZE_ID.equals(item.getPrizeId().toString())) + .collect(Collectors.toList()); + } + + protected abstract void checkActivityRule(ActivityConfigVO activityConfigVO) ; + + protected abstract void checkActivityTime(ActivityVO activityVO); +} diff --git a/demo-web-app/src/main/java/com/alibaba/demo/activity/command/CacheDeductionAwardInventoryDrawExe.java b/demo-web-app/src/main/java/com/alibaba/demo/activity/command/CacheDeductionAwardInventoryDrawExe.java new file mode 100644 index 0000000..525e626 --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/activity/command/CacheDeductionAwardInventoryDrawExe.java @@ -0,0 +1,73 @@ +package com.alibaba.demo.activity.command; + +import cn.hutool.core.io.resource.ResourceUtil; +import com.alibaba.cola.demo.web.util.AssertUtil; +import com.alibaba.demo.assembler.AwardAssembler; +import com.alibaba.demo.assembler.RecordAssembler; +import com.alibaba.demo.award.command.AwardAlgorithmCmdExe; +import com.alibaba.demo.context.ActivityDrawContext; +import com.alibaba.demo.domain.gateway.AwardCacheGateWay; +import com.alibaba.demo.domain.gateway.AwardGateway; +import com.alibaba.demo.domain.gateway.RecordGateway; +import com.alibaba.demo.dto.data.AwardVO; +import com.alibaba.fastjson.JSON; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.redis.core.script.DefaultRedisScript; +import org.springframework.data.redis.core.script.RedisScript; +import org.springframework.stereotype.Component; +import org.springframework.transaction.support.TransactionTemplate; + +import java.util.List; +import java.util.Objects; + +/** + * @ClassName CacheDeductionAwardInventoryDrawExe + * @Description TODO + * @Author Jincheng.Guo + * @Date 2024/3/5 22:31 + * @Version 1.0 + **/ +@Slf4j +@Component +public class CacheDeductionAwardInventoryDrawExe extends DefaultDrawCmdExe{ + private final AwardCacheGateWay awardCacheGateWay; + + + + + public CacheDeductionAwardInventoryDrawExe(AwardAlgorithmCmdExe awardAlgorithmCmdExe, TransactionTemplate transactionTemplate, AwardGateway awardGateway, RecordGateway recordGateway, RecordAssembler recordAssembler, AwardAssembler assembler, AwardCacheGateWay awardCacheGateWay) { + super(awardAlgorithmCmdExe, transactionTemplate, awardGateway, recordGateway, recordAssembler, assembler); + this.awardCacheGateWay = awardCacheGateWay; + } + + + @Override + protected void drawAfter(ActivityDrawContext context) { + boolean isWinTheLottery=false; + boolean invokeStockDeductionLua = false; + AwardVO awardVO = context.getAwardVO(); + try { + // lua脚本扣减库存 + if(needDeductNumber(context)){ + invokeStockDeductionLua = awardCacheGateWay.invokeStockDeductionLua(awardVO.getActivityId(), awardVO.getId()); + } + // 发布抽奖事件 + if(!needDeductNumber(context)||invokeStockDeductionLua){ + boolean sendInvokeStockDeductionEvent = sendInvokeStockDeductionEvent(awardVO); + AssertUtil.isFalse(sendInvokeStockDeductionEvent,"用户抽奖事件发送失败"); + } + isWinTheLottery=invokeStockDeductionLua; + } catch (Exception e) { + e.printStackTrace(); + awardCacheGateWay.invokeStockDeductionLuaRollback(awardVO.getActivityId(), awardVO.getId()); + } + context.setIsWinTheLottery(isWinTheLottery); + } + + private boolean sendInvokeStockDeductionEvent(AwardVO awardVO) { + log.info("发送用户中奖事件:{}", JSON.toJSON(awardVO)); + return true; + } + + +} diff --git a/demo-web-app/src/main/java/com/alibaba/demo/activity/command/DefaultDrawCmdExe.java b/demo-web-app/src/main/java/com/alibaba/demo/activity/command/DefaultDrawCmdExe.java new file mode 100644 index 0000000..c464140 --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/activity/command/DefaultDrawCmdExe.java @@ -0,0 +1,158 @@ +package com.alibaba.demo.activity.command; + +import com.alibaba.cola.demo.web.enums.RecordStatusEnum; +import com.alibaba.cola.demo.web.exception.LdException; +import com.alibaba.cola.demo.web.util.AssertUtil; +import com.alibaba.cola.demo.web.util.SecurityUtil; +import com.alibaba.demo.assembler.AwardAssembler; +import com.alibaba.demo.assembler.RecordAssembler; +import com.alibaba.demo.award.command.AwardAlgorithmCmdExe; +import com.alibaba.demo.context.ActivityDrawContext; +import com.alibaba.demo.domain.activity.ActivityEntity; +import com.alibaba.demo.domain.activity.ActivityStatusEnum; +import com.alibaba.demo.domain.activity.ActivityTime; +import com.alibaba.demo.domain.award.AwardEntity; +import com.alibaba.demo.domain.gateway.AwardGateway; +import com.alibaba.demo.domain.gateway.RecordGateway; +import com.alibaba.demo.dto.RecordAddCmd; +import com.alibaba.demo.dto.data.ActivityConfigVO; +import com.alibaba.demo.dto.data.ActivityVO; +import com.alibaba.demo.dto.data.AwardVO; +import com.alibaba.demo.dto.data.DrawResultVO; +import lombok.NoArgsConstructor; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.transaction.support.TransactionTemplate; + +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +/** + * @ClassName DefaultDrawCmdExe + * @Description TODO + * @Author Jincheng.Guo + * @Date 2024/3/3 17:14 + * @Version 1.0 + **/ +@Slf4j +@Component +@RequiredArgsConstructor +public class DefaultDrawCmdExe extends BaseDrawCmdExe{ + + + protected final AwardAlgorithmCmdExe awardAlgorithmCmdExe; + protected final TransactionTemplate transactionTemplate; + protected final AwardGateway awardGateway; + protected final RecordGateway recordGateway; + private final RecordAssembler recordAssembler; + private final AwardAssembler assembler; + + private Object lock =new Object(); + + + @Override + protected boolean needDeductNumber(ActivityDrawContext context) { + // 谢谢惠顾不需要扣减库存 + Optional awardEntity = Optional.ofNullable(context).map(ActivityDrawContext::getAwardEntity); + return awardEntity.map(AwardEntity::isPrize).orElse(false); + } + + @Override + protected void invokeDrawAlgorithm(ActivityDrawContext context, List awardVOList) { + context.setAwardVO(awardAlgorithmCmdExe.getAward(awardVOList)); + context.setAwardEntity(assembler.toAwardEntity(context.getAwardVO())); + } + + @Override + protected DrawResultVO getDrawResultVO(ActivityDrawContext context) { + DrawResultVO drawResultVO = new DrawResultVO(); + Boolean notThinksPrize = Optional.ofNullable(context).map(ActivityDrawContext::getAwardEntity).map(AwardEntity::isPrize).orElse(false); + if(!notThinksPrize||!context.getIsWinTheLottery()){ + // 谢谢惠顾或者未中奖均按返回谢谢惠顾 + drawResultVO=buildThinksDrawResult(); + return drawResultVO; + } + Optional awardEntity = Optional.ofNullable(context).map(ActivityDrawContext::getAwardEntity); + drawResultVO.setIsDraw(context.getIsWinTheLottery() && notThinksPrize); + drawResultVO.setAwardName(awardEntity.map(AwardEntity::getAwardName).orElse("")); + drawResultVO.setPrizeName(awardEntity.map(AwardEntity::getPrizeName).orElse("")); + return drawResultVO; + } + + private DrawResultVO buildThinksDrawResult() { + DrawResultVO drawResultVO = new DrawResultVO(); + drawResultVO.setIsDraw(false); + drawResultVO.setAwardName("谢谢惠顾"); + return drawResultVO; + } + + + @Override + protected void drawAfter(ActivityDrawContext context) { + // DB事务操作库存扣减和中奖记录插入 + Boolean execute = transactionTemplate.execute(status -> { + synchronized (lock) { + Boolean success = Boolean.TRUE; + int update = 0; + try { + // 扣减库存 + if (needDeductNumber(context)) { + update = awardGateway.deductionAwardNumber(context.getAwardVO().getId(), 1); + AssertUtil.isTrue(update != 1, "扣减库存失败!"); + } + // 添加中奖记录 + addRecord(context); + } catch (Exception e) { + log.error("开始回滚事务"); + //错误处理 + status.setRollbackOnly(); + if (update >= 0) { + // 回退库存 + awardGateway.deductionAwardNumber(context.getAwardVO().getId(), -1); + } + log.error("扣减库存和插入记录出错", e); + success = Boolean.FALSE; + } + return success; + } + }); + context.setIsWinTheLottery(execute); + } + + + + private void addRecord(ActivityDrawContext context) { + // 插入记录,默认记录可见 + if (Objects.isNull(context.getIsShow())) { + context.setIsShow(Boolean.TRUE); + } + RecordAddCmd recordAddCmd = new RecordAddCmd(); + recordAddCmd.setUserId(SecurityUtil.getUserId()); + recordAddCmd.setActivityId(context.getActivityConfigVO().getActivityVO().getId()); + recordAddCmd.setActivityName(context.getActivityConfigVO().getActivityVO().getActivityName()); + recordAddCmd.setAwardId(context.getAwardVO().getId()); + recordAddCmd.setIsWinning(Boolean.TRUE.equals(context.getAwardEntity().isPrize()) ? 1 : 0); + recordAddCmd.setState(context.getIsShow() ? RecordStatusEnum.STATUE_1.getValue() : RecordStatusEnum.STATUE_0.getValue()); + + context.setRecordId(recordGateway.save(recordAssembler.toAddEntity(recordAddCmd)).getId()); + + } + + @Override + protected void checkActivityRule(ActivityConfigVO activityConfigVO) { + + } + + @Override + protected void checkActivityTime(ActivityVO activityVO) { + ActivityEntity activityEntity = new ActivityEntity(); + activityEntity.setActivityTime(new ActivityTime(activityVO.getStartTime(), activityVO.getEndTime())); + ActivityStatusEnum activityStatus = activityEntity.getActivityTime().getStatus(); + if (!ActivityStatusEnum.START.equals(activityStatus)) { + throw new LdException(String.format("活动%s", activityStatus.getDescription())); + } + + } +} diff --git a/demo-web-app/src/main/java/com/alibaba/demo/activity/query/ActivityListByParamQueryExe.java b/demo-web-app/src/main/java/com/alibaba/demo/activity/query/ActivityListByParamQueryExe.java new file mode 100644 index 0000000..c720200 --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/activity/query/ActivityListByParamQueryExe.java @@ -0,0 +1,31 @@ +package com.alibaba.demo.activity.query; + +import com.alibaba.cola.demo.web.vo.PageResultInfo; +import com.alibaba.demo.assembler.ActivityAssembler; +import com.alibaba.demo.domain.activity.ActivityEntity; +import com.alibaba.demo.domain.gateway.ActivityGateway; +import com.alibaba.demo.dto.data.ActivityVO; +import com.alibaba.demo.dto.query.ActivityListByParamQuery; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.luckyapp.activity.query + * @createTime 2022/12/2 - 23:58 + * @description + */ +@Slf4j +@Component +@AllArgsConstructor +public class ActivityListByParamQueryExe { + + private final ActivityGateway activityGateway; + private final ActivityAssembler activityAssembler; + + public PageResultInfo execute(ActivityListByParamQuery query) { + PageResultInfo page = activityGateway.page(query); + return page.convert(activityAssembler::toActivityVO); + } +} diff --git a/demo-web-app/src/main/java/com/alibaba/demo/assembler/ActivityAssembler.java b/demo-web-app/src/main/java/com/alibaba/demo/assembler/ActivityAssembler.java index 25275f0..3376eb7 100644 --- a/demo-web-app/src/main/java/com/alibaba/demo/assembler/ActivityAssembler.java +++ b/demo-web-app/src/main/java/com/alibaba/demo/assembler/ActivityAssembler.java @@ -5,6 +5,9 @@ import com.alibaba.demo.domain.activity.ActivityEntity; import com.alibaba.demo.domain.activity.ActivityTime; import com.alibaba.demo.dto.ActivityAddCmd; import com.alibaba.demo.dto.data.ActivityVO; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Named; import java.time.LocalDateTime; @@ -14,55 +17,26 @@ import java.time.LocalDateTime; * @createTime 2022/12/3 - 0:03 * @description */ -public class ActivityAssembler { - public static ActivityEntity toAddEntity(ActivityAddCmd cmd) { - ActivityEntity activityEntity = new ActivityEntity(); - activityEntity.setActivityName(cmd.getActivityName()); - activityEntity.setActivityTime(new ActivityTime(cmd.getStartTime(), cmd.getEndTime())); - activityEntity.setDescribe(cmd.getDescribe()); - activityEntity.setCreateTime(LocalDateTime.now()); - activityEntity.setCreator(SecurityUtil.getName()); - activityEntity.setUpdateTime(LocalDateTime.now()); - activityEntity.setUpdater(SecurityUtil.getName()); +@Mapper(componentModel = "spring") +public interface ActivityAssembler { + @Mapping(target = "activityTime.startTime",source = "startTime") + @Mapping(target = "activityTime.endTime",source = "endTime") + ActivityEntity toAddEntity(ActivityAddCmd cmd); - return activityEntity; - } - public static ActivityVO toActivityVO(ActivityEntity entity) { - ActivityVO activityVO = new ActivityVO(); - activityVO.setId(entity.getId()); - activityVO.setActivityName(entity.getActivityName()); - activityVO.setStartTime(entity.getActivityTime().getStartTime()); - activityVO.setEndTime(entity.getActivityTime().getEndTime()); - activityVO.setDescribe(entity.getDescribe()); - activityVO.setCreateTime(entity.getCreateTime()); - activityVO.setCreator(entity.getCreator()); - activityVO.setUpdateTime(entity.getUpdateTime()); - activityVO.setUpdater(entity.getUpdater()); - activityVO.setStatus(entity.getActivityTime().getStatus().getValue()); + @Mapping(target = "startTime",source = "activityTime.startTime") + @Mapping(target = "endTime",source = "activityTime.endTime") + @Mapping(target = "status",source = "activityTime",qualifiedByName = {"status"}) + ActivityVO toActivityVO(ActivityEntity entity); - return activityVO; - } + ActivityEntity toUpdateEntity(ActivityAddCmd cmd); + + ActivityAddCmd toActivityAddCmd(ActivityVO activityVO); -// public static ActivityEntity toUpdateEntity(ActivityUpdateCmd cmd) { -// ActivityEntity activityEntity = new ActivityEntity(); -// activityEntity.setId(cmd.getId()); -// activityEntity.setActivityName(cmd.getActivityName()); -// activityEntity.setActivityTime(new ActivityTime(cmd.getStartTime(), cmd.getEndTime())); -// activityEntity.setDescribe(cmd.getDescribe()); -// activityEntity.setUpdateTime(LocalDateTime.now()); -// activityEntity.setUpdater(SecurityUtil.getName()); -// -// return activityEntity; -// } - public static ActivityAddCmd toActivityAddCmd(ActivityVO activityVO) { - ActivityAddCmd activityAddCmd = new ActivityAddCmd(); - activityAddCmd.setActivityName(activityVO.getActivityName()); - activityAddCmd.setStartTime(activityVO.getStartTime()); - activityAddCmd.setEndTime(activityVO.getEndTime()); - activityAddCmd.setDescribe(activityVO.getDescribe()); - return activityAddCmd; + @Named("status") + default Integer toStatus(ActivityTime activityTime){ + return activityTime.getStatus().getValue(); } } diff --git a/demo-web-app/src/main/java/com/alibaba/demo/assembler/RecordAssembler.java b/demo-web-app/src/main/java/com/alibaba/demo/assembler/RecordAssembler.java new file mode 100644 index 0000000..7118e12 --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/assembler/RecordAssembler.java @@ -0,0 +1,30 @@ +package com.alibaba.demo.assembler; + +import com.alibaba.cola.demo.web.enums.RecordStatusEnum; +import com.alibaba.demo.domain.record.RecordEntity; +import com.alibaba.demo.domain.record.RecordStatus; +import com.alibaba.demo.dto.RecordAddCmd; +import com.alibaba.demo.dto.data.RecordVO; +import org.mapstruct.Mapper; + +@Mapper(componentModel = "spring") +public interface RecordAssembler { + RecordEntity toAddEntity(RecordAddCmd cmd); + + + RecordVO toRecordVO(RecordEntity entity); + + + default RecordStatus toStatus(Integer status){ + return new RecordStatus(status); + } + + + default Integer getStatus(RecordStatus recordStatus){ + return recordStatus.getState(); + } + + + + +} diff --git a/demo-web-app/src/main/java/com/alibaba/demo/award/AwardServiceImpl.java b/demo-web-app/src/main/java/com/alibaba/demo/award/AwardServiceImpl.java new file mode 100644 index 0000000..a1fe796 --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/award/AwardServiceImpl.java @@ -0,0 +1,50 @@ +package com.alibaba.demo.award; + +import cn.hutool.core.collection.CollectionUtil; +import com.alibaba.cola.demo.web.vo.PageResultInfo; +import com.alibaba.demo.api.IAwardService; +import com.alibaba.demo.award.command.AwardAddCmdExe; +import com.alibaba.demo.award.query.AwardListByParamQueryExe; +import com.alibaba.demo.dto.AwardAddCmd; +import com.alibaba.demo.dto.data.AwardVO; +import com.alibaba.demo.dto.query.AwardListByParamQuery; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +@AllArgsConstructor +public class AwardServiceImpl implements IAwardService { + + private final AwardAddCmdExe awardAddCmdExe; + private final AwardListByParamQueryExe awardListByParamQueryExe; + + @Override + public AwardVO add(AwardAddCmd cmd) { + return awardAddCmdExe.execute(cmd); + } + + @Override + public AwardVO update(AwardAddCmd cmd) { + return awardAddCmdExe.execute(cmd); + } + + @Override + public AwardVO one(Long id) { + final var query = new AwardListByParamQuery(); + query.setId(id); + PageResultInfo page = page(query); + if (CollectionUtil.isEmpty(page.getData())) { + return null; + } + return page.getData().get(0); + } + + @Override + public PageResultInfo page(AwardListByParamQuery query) { + return awardListByParamQueryExe.execute(query); + } + + +} diff --git a/demo-web-app/src/main/java/com/alibaba/demo/award/command/AwardAddCmdExe.java b/demo-web-app/src/main/java/com/alibaba/demo/award/command/AwardAddCmdExe.java index 70d8c24..565e890 100644 --- a/demo-web-app/src/main/java/com/alibaba/demo/award/command/AwardAddCmdExe.java +++ b/demo-web-app/src/main/java/com/alibaba/demo/award/command/AwardAddCmdExe.java @@ -1,17 +1,24 @@ package com.alibaba.demo.award.command; +import cn.hutool.core.util.NumberUtil; +import com.alibaba.cola.demo.web.exception.LdException; import com.alibaba.cola.demo.web.util.AssertUtil; +import com.alibaba.cola.demo.web.vo.PageResultInfo; import com.alibaba.demo.assembler.AwardAssembler; import com.alibaba.demo.domain.award.AwardEntity; import com.alibaba.demo.domain.gateway.AwardGateway; import com.alibaba.demo.domain.gateway.PrizeGateway; import com.alibaba.demo.dto.AwardAddCmd; import com.alibaba.demo.dto.data.AwardVO; +import com.alibaba.demo.dto.query.AwardListByParamQuery; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; +import java.util.ArrayList; +import java.util.List; import java.util.Objects; +import java.util.Optional; /** * @author J3(about:https://j3code.cn) @@ -30,7 +37,7 @@ public class AwardAddCmdExe { public AwardVO execute(AwardAddCmd cmd) { AssertUtil.isTrue(Objects.isNull(cmd.getActivityId()), "奖项活动id不为空!"); - + checkTotalProbabilityEqualOne(cmd); // 保存奖项 AwardEntity entity = awardGateway.save(awardAssembler.toAddEntity(cmd)); @@ -45,4 +52,29 @@ public class AwardAddCmdExe { return awardAssembler.toAwardVO(entity); } + + + /** + * @Author guocheng + * @Description 校验所有奖项概率和为1 + * @Date 11:32 2024/3/5 + * @Param [awardAddCmdList] + * @return void + **/ + private void checkTotalProbabilityEqualOne(AwardAddCmd awardAddCmd) { + AwardListByParamQuery awardListByParamQuery=new AwardListByParamQuery(); + awardListByParamQuery.setActivityId(awardAddCmd.getActivityId()); + PageResultInfo awardEntityPageResultInfo = awardGateway.page(awardListByParamQuery); + List awardEntities = Optional.ofNullable(awardEntityPageResultInfo).map(PageResultInfo::getData) + .orElseGet(ArrayList::new); + awardEntities.add(awardAssembler.toAddEntity(awardAddCmd)); + double sumProbability = awardEntities.stream() + .mapToDouble(AwardEntity::getProbability) + .sum(); + int compare = NumberUtil.compare(1, sumProbability); + if(compare<0){ + throw new LdException("奖项概率之和不能超过1"); + } + + } } diff --git a/demo-web-app/src/main/java/com/alibaba/demo/award/command/AwardAlgorithmCmdExe.java b/demo-web-app/src/main/java/com/alibaba/demo/award/command/AwardAlgorithmCmdExe.java new file mode 100644 index 0000000..fe0abf7 --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/award/command/AwardAlgorithmCmdExe.java @@ -0,0 +1,17 @@ +package com.alibaba.demo.award.command; + +import com.alibaba.demo.dto.data.AwardVO; + +import java.util.List; + +public interface AwardAlgorithmCmdExe { + + /** + * @Author guocheng + * @Description 中奖算法获取奖品 + * @Date 17:26 2024/3/3 + * @Param [awardVOList] + * @return com.alibaba.demo.dto.data.AwardVO + **/ + AwardVO getAward(List awardVOList); +} diff --git a/demo-web-app/src/main/java/com/alibaba/demo/award/command/WeightRandomAwardAlgorithmCmdExe.java b/demo-web-app/src/main/java/com/alibaba/demo/award/command/WeightRandomAwardAlgorithmCmdExe.java new file mode 100644 index 0000000..6b34c53 --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/award/command/WeightRandomAwardAlgorithmCmdExe.java @@ -0,0 +1,32 @@ +package com.alibaba.demo.award.command; + +import cn.hutool.core.lang.WeightRandom; +import cn.hutool.core.util.RandomUtil; +import com.alibaba.demo.dto.data.AwardVO; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + +/** + * @ClassName WeightRandomAwardAlgorithmCmdExe + * @Description 权重随机获取奖品 + * @Author Jincheng.Guo + * @Date 2024/3/3 17:28 + * @Version 1.0 + **/ +@Slf4j +@Component +@AllArgsConstructor +public class WeightRandomAwardAlgorithmCmdExe implements AwardAlgorithmCmdExe{ + @Override + public AwardVO getAward(List awardVOList) { + List> weightList = new ArrayList<>(); + awardVOList.forEach(item -> weightList.add(new WeightRandom.WeightObj<>(item, item.getProbability()))); + //创建带有权重的随机生成器 + WeightRandom wr = RandomUtil.weightRandom(weightList); + return wr.next(); + } +} diff --git a/demo-web-app/src/main/java/com/alibaba/demo/award/query/AwardListByParamQueryExe.java b/demo-web-app/src/main/java/com/alibaba/demo/award/query/AwardListByParamQueryExe.java new file mode 100644 index 0000000..a275b09 --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/award/query/AwardListByParamQueryExe.java @@ -0,0 +1,31 @@ +package com.alibaba.demo.award.query; + +import com.alibaba.cola.demo.web.vo.PageResultInfo; +import com.alibaba.demo.assembler.AwardAssembler; +import com.alibaba.demo.domain.award.AwardEntity; +import com.alibaba.demo.domain.gateway.AwardGateway; +import com.alibaba.demo.dto.data.AwardVO; +import com.alibaba.demo.dto.query.AwardListByParamQuery; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.luckyapp.award.query + * @createTime 2022/12/2 - 22:47 + * @description + */ +@Slf4j +@Component +@AllArgsConstructor +public class AwardListByParamQueryExe { + private final AwardGateway awardGateway; + private final AwardAssembler awardAssembler; + + public PageResultInfo execute(AwardListByParamQuery query) { + PageResultInfo page = awardGateway.page(query); + + return page.convert(awardAssembler::toAwardVO); + } +} diff --git a/demo-web-app/src/main/java/com/alibaba/demo/context/ActivityDrawContext.java b/demo-web-app/src/main/java/com/alibaba/demo/context/ActivityDrawContext.java new file mode 100644 index 0000000..eb2d02f --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/context/ActivityDrawContext.java @@ -0,0 +1,39 @@ +package com.alibaba.demo.context; + +import com.alibaba.demo.domain.award.AwardEntity; +import com.alibaba.demo.dto.data.ActivityConfigVO; +import com.alibaba.demo.dto.data.AwardVO; +import lombok.Data; +import lombok.experimental.Accessors; + +@Data +@Accessors(chain = true) +public class ActivityDrawContext { + + private ActivityConfigVO activityConfigVO; + + /** + * 抽奖算法获得到的奖项 + */ + private AwardVO awardVO; + /** + * 抽奖算法获得到的奖项entity + */ + private AwardEntity awardEntity; + + /** + * 是否中奖,true:中奖 + */ + private Boolean isWinTheLottery; + + /** + * 是否可见,用户中奖日志是否可见 + */ + private Boolean isShow; + + /** + * 中奖记录id + */ + private Long recordId; + +} diff --git a/demo-web-app/src/main/java/com/alibaba/demo/listener/AwardInventory2CacheListener.java b/demo-web-app/src/main/java/com/alibaba/demo/listener/AwardInventory2CacheListener.java new file mode 100644 index 0000000..c8d2db0 --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/listener/AwardInventory2CacheListener.java @@ -0,0 +1,46 @@ +package com.alibaba.demo.listener; + +import cn.hutool.core.date.DateUnit; +import cn.hutool.core.date.DateUtil; +import com.alibaba.cola.demo.web.exception.LdException; +import com.alibaba.demo.domain.gateway.AwardCacheGateWay; +import com.alibaba.demo.dto.data.ActivityConfigVO; +import com.alibaba.demo.dto.data.ActivityVO; +import com.alibaba.demo.listener.event.ActivityCreatedEvent; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; + +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Date; +import java.util.Optional; + +/** + * @ClassName AwardInventory2CacheListener + * @Description 奖项库存缓存监听器 + * @Author Jincheng.Guo + * @Date 2024/3/5 21:14 + * @Version 1.0 + **/ +@Slf4j +@Component +@RequiredArgsConstructor +public class AwardInventory2CacheListener implements ApplicationListener { + private final AwardCacheGateWay awardCacheGateWay; + + @Override + public void onApplicationEvent(ActivityCreatedEvent event) { + log.info("ActivityCreateEvent_执行..."); + Optional activityConfigVO = Optional.ofNullable(event.getActivityConfigVO()); + LocalDateTime endTime = activityConfigVO.map(ActivityConfigVO::getActivityVO).map(ActivityVO::getEndTime).orElseThrow(() -> new LdException("活动信息不完整")); + Duration between = Duration.between(LocalDateTime.now(), endTime); + boolean awardInventory = awardCacheGateWay.setAwardInventory(activityConfigVO.map(ActivityConfigVO::getAwardVOList).orElseGet(ArrayList::new), between); + log.info("ActivityCreateEvent_ActivityId:{},存入Redis库存:{} ", + activityConfigVO.map(ActivityConfigVO::getActivityVO).map(ActivityVO::getId).orElse(null), + awardInventory); + + } +} diff --git a/demo-web-app/src/main/java/com/alibaba/demo/listener/event/ActivityCreatedEvent.java b/demo-web-app/src/main/java/com/alibaba/demo/listener/event/ActivityCreatedEvent.java new file mode 100644 index 0000000..cf01728 --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/listener/event/ActivityCreatedEvent.java @@ -0,0 +1,25 @@ +package com.alibaba.demo.listener.event; + +import com.alibaba.demo.dto.data.ActivityConfigVO; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationEvent; + +/** + * @ClassName ActivityCreatedEvent + * @Description 活动创建事件 + * @Author Jincheng.Guo + * @Date 2024/3/5 21:10 + * @Version 1.0 + **/ +@Slf4j +@Getter +public class ActivityCreatedEvent extends ApplicationEvent { + private final ActivityConfigVO activityConfigVO; + + + public ActivityCreatedEvent(Object source, ActivityConfigVO activityConfigVO) { + super(source); + this.activityConfigVO = activityConfigVO; + } +} diff --git a/demo-web-app/src/main/java/com/alibaba/demo/listener/event/UserWinEvent.java b/demo-web-app/src/main/java/com/alibaba/demo/listener/event/UserWinEvent.java new file mode 100644 index 0000000..36f0434 --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/listener/event/UserWinEvent.java @@ -0,0 +1,27 @@ +package com.alibaba.demo.listener.event; + +import com.alibaba.demo.dto.data.AwardVO; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationEvent; + +/** + * @ClassName ActivityCreatedEvent + * @Description 用户中奖事件 + * @Author Jincheng.Guo + * @Date 2024/3/5 21:10 + * @Version 1.0 + **/ +@Slf4j +@Getter +public class UserWinEvent extends ApplicationEvent { + private final AwardVO awardVO; + private final Long userId; + + + public UserWinEvent(Object source, AwardVO awardVO, Long userId) { + super(source); + this.awardVO = awardVO; + this.userId = userId; + } +} diff --git a/demo-web-app/src/main/java/com/alibaba/demo/prize/PrizeServiceImpl.java b/demo-web-app/src/main/java/com/alibaba/demo/prize/PrizeServiceImpl.java index 951b4a4..6f7b481 100644 --- a/demo-web-app/src/main/java/com/alibaba/demo/prize/PrizeServiceImpl.java +++ b/demo-web-app/src/main/java/com/alibaba/demo/prize/PrizeServiceImpl.java @@ -1,5 +1,6 @@ package com.alibaba.demo.prize; +import cn.hutool.core.collection.CollectionUtil; import com.alibaba.cola.demo.web.vo.PageResultInfo; import com.alibaba.demo.api.IPrizeService; import com.alibaba.demo.dto.PrizeAddCmd; @@ -12,6 +13,10 @@ import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + /** * @ClassName PrizeServiceImpl * @Description TODO @@ -46,6 +51,13 @@ public class PrizeServiceImpl implements IPrizeService { @Override public PrizeVO one(Long id) { - return null; + PrizeListByParamQuery query = new PrizeListByParamQuery(); + query.setId(id); + PageResultInfo page = page(query); + List prizeVOS = Optional.ofNullable(page).map(PageResultInfo::getData).orElseGet(ArrayList::new); + if (CollectionUtil.isEmpty(prizeVOS)) { + return null; + } + return prizeVOS.get(0); } } diff --git a/demo-web-app/src/main/java/com/alibaba/demo/prize/command/PrizeAddCmdExe.java b/demo-web-app/src/main/java/com/alibaba/demo/prize/command/PrizeAddCmdExe.java index 3e37632..f76a8d8 100644 --- a/demo-web-app/src/main/java/com/alibaba/demo/prize/command/PrizeAddCmdExe.java +++ b/demo-web-app/src/main/java/com/alibaba/demo/prize/command/PrizeAddCmdExe.java @@ -26,7 +26,6 @@ public class PrizeAddCmdExe { public PrizeVO execute(PrizeAddCmd cmd) { PrizeEntity prizeEntity = prizeGateway.save(prizeAssembler.toAddEntity(cmd)); - return prizeAssembler.toPrizeVO(prizeEntity); } } diff --git a/demo-web-app/src/main/java/com/alibaba/demo/record/command/RecordAddCmdExe.java b/demo-web-app/src/main/java/com/alibaba/demo/record/command/RecordAddCmdExe.java new file mode 100644 index 0000000..3de23a2 --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/record/command/RecordAddCmdExe.java @@ -0,0 +1,25 @@ +package com.alibaba.demo.record.command; + +import com.alibaba.demo.assembler.RecordAssembler; +import com.alibaba.demo.domain.gateway.RecordGateway; +import com.alibaba.demo.domain.record.RecordEntity; +import com.alibaba.demo.dto.RecordAddCmd; +import com.alibaba.demo.dto.data.RecordVO; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +@Slf4j +@Component +@AllArgsConstructor +public class RecordAddCmdExe { + + private final RecordGateway recordGateway; + private final RecordAssembler recordAssembler; + + public RecordVO execute(RecordAddCmd cmd) { + RecordEntity entity = recordGateway.save(recordAssembler.toAddEntity(cmd)); + + return recordAssembler.toRecordVO(entity); + } +} diff --git a/demo-web-app/src/test/java/com/alibaba/demo/activity/ActivityConfigServiceImplTest.java b/demo-web-app/src/test/java/com/alibaba/demo/activity/ActivityConfigServiceImplTest.java new file mode 100644 index 0000000..633c0d7 --- /dev/null +++ b/demo-web-app/src/test/java/com/alibaba/demo/activity/ActivityConfigServiceImplTest.java @@ -0,0 +1,103 @@ +package com.alibaba.demo.activity; + +import com.alibaba.cola.demo.web.exception.LdException; +import com.alibaba.cola.demo.web.vo.PageResultInfo; +import com.alibaba.demo.activity.command.ActivityAddCmdExe; +import com.alibaba.demo.activity.query.ActivityListByParamQueryExe; +import com.alibaba.demo.award.command.AwardAddCmdExe; +import com.alibaba.demo.award.query.AwardListByParamQueryExe; +import com.alibaba.demo.dto.ActivityConfigAddCmd; +import com.alibaba.demo.dto.ActivityConfigUpdateCmd; +import com.alibaba.demo.dto.AwardAddCmd; +import com.alibaba.demo.dto.data.ActivityConfigVO; +import com.alibaba.demo.dto.data.ActivityVO; +import com.alibaba.demo.dto.data.AwardVO; +import com.github.jsonzou.jmockdata.JMockData; +import org.assertj.core.api.Assertions; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.powermock.reflect.Whitebox; +import org.slf4j.Logger; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.when; +public class ActivityConfigServiceImplTest { + @Mock + ActivityAddCmdExe activityAddCmdExe; + @Mock + AwardAddCmdExe awardAddCmdExe; + @Mock + ActivityListByParamQueryExe activityListByParamQueryExe; + @Mock + AwardListByParamQueryExe awardListByParamQueryExe; + @Mock + Logger log; + @InjectMocks + ActivityConfigServiceImpl activityConfigServiceImpl; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void testAdd() throws Exception { + when(activityAddCmdExe.execute(any())).thenReturn(new ActivityVO()); + when(awardAddCmdExe.execute(any())).thenReturn(new AwardVO()); + + ActivityConfigVO result = activityConfigServiceImpl.add(new ActivityConfigAddCmd()); + Assert.assertEquals(new ActivityConfigVO(), result); + } + + @Test + public void testUpdate() throws Exception { + ActivityConfigVO result = activityConfigServiceImpl.update(new ActivityConfigUpdateCmd()); + Assert.assertEquals(new ActivityConfigVO(), result); + } + + @Test + public void testOne() throws Exception { + when(activityListByParamQueryExe.execute(any())).thenReturn(new PageResultInfo()); + when(awardListByParamQueryExe.execute(any())).thenReturn(new PageResultInfo()); + + ActivityConfigVO result = activityConfigServiceImpl.one(Long.valueOf(1)); + Assert.assertEquals(new ActivityConfigVO(), result); + } + + + @Test + public void testCheckTotalProbabilityEqualOne() throws Exception { + // 概率之和超过1 + List doubles = Arrays.asList(0.1, 0.2, 0.3, 0.9); + List awardAddCmds = doubles.stream() + .map(item -> { + AwardAddCmd mock = JMockData.mock(AwardAddCmd.class); + mock.setProbability(item); + return mock; + }).collect(Collectors.toList()); + Assertions.assertThatThrownBy(()->Whitebox.invokeMethod(activityConfigServiceImpl, "checkTotalProbabilityEqualOne", awardAddCmds)) + .isInstanceOf(LdException.class) + .hasMessageContaining("奖项概率之和不能超过1"); + + // 概率之和不超过1 + List doubles2 = Arrays.asList(0.1, 0.2, 0.3, 0.35); + List awardAddCmds2 = doubles2.stream() + .map(item -> { + AwardAddCmd mock = JMockData.mock(AwardAddCmd.class); + mock.setProbability(item); + return mock; + }).collect(Collectors.toList()); + Whitebox.invokeMethod(activityConfigServiceImpl, "checkTotalProbabilityEqualOne", awardAddCmds2); + + } +} + +//Generated with love by TestMe :) Please report issues and submit feature requests at: http://weirddev.com/forum#!/testme \ No newline at end of file diff --git a/demo-web-base/src/main/java/com/alibaba/cola/demo/web/enums/RecordStatusEnum.java b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/enums/RecordStatusEnum.java index b5746ba..e4e839d 100644 --- a/demo-web-base/src/main/java/com/alibaba/cola/demo/web/enums/RecordStatusEnum.java +++ b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/enums/RecordStatusEnum.java @@ -1,7 +1,10 @@ package com.alibaba.cola.demo.web.enums; +import com.alibaba.cola.demo.web.exception.LdException; import lombok.Getter; +import java.util.Arrays; + /** * @author J3(about:https://j3code.cn) * @package cn.j3code.luckydomain.record @@ -32,4 +35,9 @@ public enum RecordStatusEnum { this.description = description; } + public static RecordStatusEnum getStatus(Integer value){ + return Arrays.stream(RecordStatusEnum.values()).filter(recordStatusEnum -> recordStatusEnum.value.equals(value)) + .findFirst().orElseThrow(()->new LdException("未知记录状态")); + } + } diff --git a/demo-web-base/src/main/java/com/alibaba/cola/demo/web/handler/ResponseResultHandler.java b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/handler/ResponseResultHandler.java new file mode 100644 index 0000000..19bebc6 --- /dev/null +++ b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/handler/ResponseResultHandler.java @@ -0,0 +1,66 @@ +package com.alibaba.cola.demo.web.handler; + +import com.alibaba.cola.demo.web.vo.ResultInfo; +import com.alibaba.cola.demo.web.vo.SuccessInfo; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.AllArgsConstructor; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.springframework.core.MethodParameter; +import org.springframework.core.io.FileSystemResource; +import org.springframework.http.MediaType; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.server.ServerHttpRequest; +import org.springframework.http.server.ServerHttpResponse; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; + +import java.util.Objects; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.common.handler + * @createTime 2022/11/26 - 15:45 + * @description + */ +@Slf4j +@ControllerAdvice +@AllArgsConstructor +public class ResponseResultHandler implements ResponseBodyAdvice { + @Override + public boolean supports(MethodParameter methodParameter, Class> aClass) { + return true; + } + + @SneakyThrows + @Override + public Object beforeBodyWrite(Object data, + MethodParameter mediaType, + MediaType selectedContentType, + Class> selectedConverterType, + ServerHttpRequest request, + ServerHttpResponse serverHttpResponse) { + // 处理结果集 + var successInfo = SuccessInfo.builder() + .data(data) + .build(); + + ObjectMapper om = new ObjectMapper(); + // 如果已经是指定返回体不用处理 + if(data instanceof ResultInfo){ + return data; + } + + if ((data instanceof String) && !MediaType.APPLICATION_XML_VALUE.equals(mediaType.toString())) { + serverHttpResponse.getHeaders().set("Content-Type", "application/json"); + return om.writeValueAsString(successInfo); + } + + if (Objects.isNull(data) && MediaType.TEXT_HTML_VALUE.equals(mediaType.toString())) { + serverHttpResponse.getHeaders().set("Content-Type", "application/json"); + return om.writeValueAsString(successInfo); + } + + return successInfo; + } +} diff --git a/demo-web-base/src/main/java/com/alibaba/cola/demo/web/util/SecurityUtil.java b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/util/SecurityUtil.java index 5d46222..b7d012f 100644 --- a/demo-web-base/src/main/java/com/alibaba/cola/demo/web/util/SecurityUtil.java +++ b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/util/SecurityUtil.java @@ -35,9 +35,10 @@ public class SecurityUtil { } public static Long getUserId() { - Object userId = userThreadLocal.get().get("id"); - - return Objects.isNull(userId) ? 0L : Long.parseLong(userId.toString()); + return 1L; +// Object userId = userThreadLocal.get().get("id"); +// +// return Objects.isNull(userId) ? 0L : Long.parseLong(userId.toString()); } public static String get(String key) { diff --git a/demo-web-base/src/main/java/com/alibaba/cola/demo/web/vo/PageResultInfo.java b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/vo/PageResultInfo.java index c626493..54a2ccf 100644 --- a/demo-web-base/src/main/java/com/alibaba/cola/demo/web/vo/PageResultInfo.java +++ b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/vo/PageResultInfo.java @@ -1,8 +1,7 @@ package com.alibaba.cola.demo.web.vo; -import lombok.Builder; -import lombok.Getter; -import lombok.ToString; +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.*; import java.util.List; import java.util.function.Function; @@ -16,7 +15,7 @@ import java.util.stream.Collectors; */ @Builder @ToString -@Getter +@Data public class PageResultInfo extends ResultInfo { protected static final Integer DEFAULT_CODE = 20000; @@ -36,9 +35,9 @@ public class PageResultInfo extends ResultInfo { this.data=data; } - - - + public PageResultInfo() { + super(true, DEFAULT_CODE, DEFAULT_MESSAGE); + } public PageResultInfo convert(Function mapper) { List collect = (List)this.getData().stream().map(mapper).collect(Collectors.toList()); diff --git a/demo-web-client/src/main/java/com/alibaba/demo/api/ActivityDecoratorService.java b/demo-web-client/src/main/java/com/alibaba/demo/api/ActivityDecoratorService.java new file mode 100644 index 0000000..217c277 --- /dev/null +++ b/demo-web-client/src/main/java/com/alibaba/demo/api/ActivityDecoratorService.java @@ -0,0 +1,43 @@ +package com.alibaba.demo.api; + +import com.alibaba.demo.api.IActivityConfigService; +import com.alibaba.demo.dto.ActivityConfigAddCmd; +import com.alibaba.demo.dto.ActivityConfigUpdateCmd; +import com.alibaba.demo.dto.data.ActivityConfigVO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; + +/** + * @ClassName ActivityDecoratorService + * @Description TODO + * @Author Jincheng.Guo + * @Date 2024/3/1 18:46 + * @Version 1.0 + **/ +public abstract class ActivityDecoratorService implements IActivityConfigService,IActivityService { + + @Qualifier("activityConfigService") + @Autowired + protected IActivityConfigService iActivityConfigService; + + + @Override + public ActivityConfigVO add(ActivityConfigAddCmd cmd) { + return iActivityConfigService.add(cmd); + } + + @Override + public ActivityConfigVO update(ActivityConfigUpdateCmd cmd) { + return iActivityConfigService.update(cmd); + } + + @Override + public ActivityConfigVO one(Long id) { + return iActivityConfigService.one(id); + } + + @Override + public boolean refreshInventory(Long activityId) { + return iActivityConfigService.refreshInventory(activityId); + } +} diff --git a/demo-web-client/src/main/java/com/alibaba/demo/api/IActivityConfigService.java b/demo-web-client/src/main/java/com/alibaba/demo/api/IActivityConfigService.java index c7d7e26..1ba4f04 100644 --- a/demo-web-client/src/main/java/com/alibaba/demo/api/IActivityConfigService.java +++ b/demo-web-client/src/main/java/com/alibaba/demo/api/IActivityConfigService.java @@ -1,9 +1,11 @@ package com.alibaba.demo.api; +import com.alibaba.cola.demo.web.vo.PageResultInfo; import com.alibaba.demo.dto.ActivityConfigAddCmd; import com.alibaba.demo.dto.ActivityConfigUpdateCmd; import com.alibaba.demo.dto.data.ActivityConfigVO; +import com.alibaba.demo.dto.data.AwardVO; /** * @author J3(about:https://j3code.cn) @@ -20,4 +22,6 @@ public interface IActivityConfigService { ActivityConfigVO one(Long id); // ActivityConfigCopyVO copy(Long id); + + boolean refreshInventory(Long activityId); } diff --git a/demo-web-client/src/main/java/com/alibaba/demo/api/IActivityService.java b/demo-web-client/src/main/java/com/alibaba/demo/api/IActivityService.java new file mode 100644 index 0000000..4f16b3b --- /dev/null +++ b/demo-web-client/src/main/java/com/alibaba/demo/api/IActivityService.java @@ -0,0 +1,28 @@ +package com.alibaba.demo.api; + +import com.alibaba.cola.demo.web.vo.PageResultInfo; +import com.alibaba.demo.dto.data.ActivityVO; +import com.alibaba.demo.dto.data.DrawResultVO; +import com.alibaba.demo.dto.query.ActivityListByParamQuery; + +/** + * @ClassName IActivityService + * @Description 活动服务-用户端 + * @Author Jincheng.Guo + * @Date 2024/3/1 18:50 + * @Version 1.0 + **/ +public interface IActivityService { + + PageResultInfo page(ActivityListByParamQuery query); + + + /** + * 用户抽奖接口 + * @param activityId + * @return + */ + DrawResultVO draw(Long activityId); + + +} diff --git a/demo-web-client/src/main/java/com/alibaba/demo/api/IAwardService.java b/demo-web-client/src/main/java/com/alibaba/demo/api/IAwardService.java new file mode 100644 index 0000000..632c5a5 --- /dev/null +++ b/demo-web-client/src/main/java/com/alibaba/demo/api/IAwardService.java @@ -0,0 +1,20 @@ +package com.alibaba.demo.api; + +import com.alibaba.cola.demo.web.vo.PageResultInfo; +import com.alibaba.demo.dto.AwardAddCmd; +import com.alibaba.demo.dto.data.AwardVO; +import com.alibaba.demo.dto.query.AwardListByParamQuery; + +public interface IAwardService { + + AwardVO add(AwardAddCmd cmd); + + AwardVO update(AwardAddCmd cmd); + + AwardVO one(Long id); + + PageResultInfo page(AwardListByParamQuery query); + + + +} diff --git a/demo-web-client/src/main/java/com/alibaba/demo/dto/ActivityAddCmd.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/ActivityAddCmd.java index 40fbf43..d53579c 100644 --- a/demo-web-client/src/main/java/com/alibaba/demo/dto/ActivityAddCmd.java +++ b/demo-web-client/src/main/java/com/alibaba/demo/dto/ActivityAddCmd.java @@ -1,11 +1,13 @@ package com.alibaba.demo.dto; +import com.alibaba.cola.demo.web.config.validate.AddGroup; import com.alibaba.cola.demo.web.config.validate.UpdateGroup; import com.alibaba.cola.dto.Command; import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Data; import javax.validation.constraints.NotNull; +import javax.validation.constraints.Null; import java.time.LocalDateTime; /** @@ -23,6 +25,7 @@ public class ActivityAddCmd extends Command { * 活动Id */ @NotNull(message = "id不为空",groups = {UpdateGroup.class}) + @Null(message = "id需为空",groups = {AddGroup.class}) private Long id; diff --git a/demo-web-client/src/main/java/com/alibaba/demo/dto/ActivityDrawCmd.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/ActivityDrawCmd.java new file mode 100644 index 0000000..fc40ed8 --- /dev/null +++ b/demo-web-client/src/main/java/com/alibaba/demo/dto/ActivityDrawCmd.java @@ -0,0 +1,31 @@ +package com.alibaba.demo.dto; + +import com.alibaba.demo.dto.data.ActivityConfigVO; +import com.alibaba.demo.dto.data.AwardVO; +import lombok.Data; + +/** + * @ClassName ActivityDrawCmd + * @Description 抽奖命令 + * @Author Jincheng.Guo + * @Date 2024/3/3 14:56 + * @Version 1.0 + **/ +@Data +public class ActivityDrawCmd { + + private ActivityConfigVO activityConfigVO; + + /** + * 抽奖算法获得到的奖项 + */ + private AwardVO awardVO; + + + + /** + * 是否中奖,true:中奖 + */ + private Boolean isWinTheLottery; + +} diff --git a/demo-web-client/src/main/java/com/alibaba/demo/dto/AwardAddCmd.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/AwardAddCmd.java index 6ae66ee..6a1582a 100644 --- a/demo-web-client/src/main/java/com/alibaba/demo/dto/AwardAddCmd.java +++ b/demo-web-client/src/main/java/com/alibaba/demo/dto/AwardAddCmd.java @@ -1,10 +1,12 @@ package com.alibaba.demo.dto; +import com.alibaba.cola.demo.web.config.validate.AddGroup; import com.alibaba.cola.demo.web.config.validate.UpdateGroup; import com.alibaba.cola.dto.Command; import lombok.Data; import javax.validation.constraints.NotNull; +import javax.validation.constraints.Null; /** * @ClassName AwardAddCmdListCmd @@ -17,6 +19,7 @@ import javax.validation.constraints.NotNull; public class AwardAddCmd extends Command { @NotNull(message = "id不为空",groups = {UpdateGroup.class}) + @Null(message = "id需为空",groups = {AddGroup.class}) private Long id; /** * 奖品ID @@ -25,6 +28,7 @@ public class AwardAddCmd extends Command { /** * 活动ID */ + @NotNull(message = "活动ID不为空") private Long activityId; /** * 数量 diff --git a/demo-web-client/src/main/java/com/alibaba/demo/dto/PrizeAddCmd.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/PrizeAddCmd.java index fdacb61..7e08a2b 100644 --- a/demo-web-client/src/main/java/com/alibaba/demo/dto/PrizeAddCmd.java +++ b/demo-web-client/src/main/java/com/alibaba/demo/dto/PrizeAddCmd.java @@ -1,10 +1,12 @@ package com.alibaba.demo.dto; +import com.alibaba.cola.demo.web.config.validate.AddGroup; import com.alibaba.cola.demo.web.config.validate.UpdateGroup; import com.alibaba.cola.dto.Command; import lombok.Data; import javax.validation.constraints.NotNull; +import javax.validation.constraints.Null; import java.math.BigDecimal; /** @@ -18,6 +20,7 @@ public class PrizeAddCmd extends Command { @NotNull(message = "id不为空",groups = {UpdateGroup.class}) + @Null(message = "id需为空",groups = {AddGroup.class}) private Long id; /** diff --git a/demo-web-client/src/main/java/com/alibaba/demo/dto/RecordAddCmd.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/RecordAddCmd.java new file mode 100644 index 0000000..2011504 --- /dev/null +++ b/demo-web-client/src/main/java/com/alibaba/demo/dto/RecordAddCmd.java @@ -0,0 +1,46 @@ +package com.alibaba.demo.dto; + +import com.alibaba.cola.dto.Command; +import lombok.Data; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.luckyclient.dto + * @createTime 2022/12/9 - 23:19 + * @description + */ +@Data +public class RecordAddCmd extends Command { + + /** + * + */ + private Long id; + + /** + * 用户id + */ + private Long userId; + + /** + * 活动id + */ + private Long activityId; + + private String activityName; + + /** + * 奖项id + */ + private Long awardId; + + /** + * 是否中奖:0未中奖,1中奖 + */ + private Integer isWinning; + + /** + * 状态(0,1,2,3) + */ + private Integer state; +} diff --git a/demo-web-client/src/main/java/com/alibaba/demo/dto/data/DrawResultVO.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/data/DrawResultVO.java new file mode 100644 index 0000000..8def138 --- /dev/null +++ b/demo-web-client/src/main/java/com/alibaba/demo/dto/data/DrawResultVO.java @@ -0,0 +1,16 @@ +package com.alibaba.demo.dto.data; + +import lombok.Data; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.luckyclient.dto.data + * @createTime 2022/12/6 - 22:45 + * @description + */ +@Data +public class DrawResultVO { + private String awardName; + private String prizeName; + private Boolean isDraw; +} diff --git a/demo-web-client/src/main/java/com/alibaba/demo/dto/data/RecordVO.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/data/RecordVO.java new file mode 100644 index 0000000..ed0715e --- /dev/null +++ b/demo-web-client/src/main/java/com/alibaba/demo/dto/data/RecordVO.java @@ -0,0 +1,68 @@ +package com.alibaba.demo.dto.data; + +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class RecordVO { + + /** + * + */ + private Long id; + + /** + * 用户id + */ + private Long userId; + + /** + * 活动id + */ + private Long activityId; + + private String activityName; + + /** + * 奖项id + */ + private Long awardId; + + private String awardName; + + private String prizeName; + + private Integer prizeType; + + + /** + * 是否中奖:0未中奖,1中奖 + */ + private Integer isWinning; + + /** + * 状态(0,1,2,3) + */ + private Integer state; + + /** + * + */ + private LocalDateTime createTime; + + /** + * + */ + private String creator; + + /** + * + */ + private LocalDateTime updateTime; + + /** + * + */ + private String updater; +} diff --git a/demo-web-client/src/main/java/com/alibaba/demo/dto/query/ActivityListByParamQuery.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/query/ActivityListByParamQuery.java new file mode 100644 index 0000000..92cd550 --- /dev/null +++ b/demo-web-client/src/main/java/com/alibaba/demo/dto/query/ActivityListByParamQuery.java @@ -0,0 +1,39 @@ +package com.alibaba.demo.dto.query; + +import com.alibaba.cola.dto.PageQuery; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.luckyclient.dto.query + * @createTime 2022/12/2 - 23:52 + * @description + */ +@Data +public class ActivityListByParamQuery extends PageQuery { + + private Long id; + + private String activityName; + + /** + * 开始时间 + */ + @NotNull(message = "开始时间不为空") + private LocalDateTime startTime; + + /** + * 结束时间 + */ + @NotNull(message = "结束时间不为空") + private LocalDateTime endTime; + + /** + * 活动状态(0、1、2) + */ + private Integer status; + +} diff --git a/demo-web-client/src/main/java/com/alibaba/demo/dto/query/AwardListByParamQuery.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/query/AwardListByParamQuery.java new file mode 100644 index 0000000..1196ab8 --- /dev/null +++ b/demo-web-client/src/main/java/com/alibaba/demo/dto/query/AwardListByParamQuery.java @@ -0,0 +1,22 @@ +package com.alibaba.demo.dto.query; + +import com.alibaba.cola.dto.PageQuery; +import lombok.Data; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.luckyclient.dto.query + * @createTime 2022/12/2 - 22:38 + * @description + */ +@Data +public class AwardListByParamQuery extends PageQuery { + + private Long id; + + private Long activityId; + + private String activityName; + + private String awardName; +} diff --git a/demo-web-client/src/main/java/com/alibaba/demo/dto/query/RecordListByParamQuery.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/query/RecordListByParamQuery.java new file mode 100644 index 0000000..f7d2377 --- /dev/null +++ b/demo-web-client/src/main/java/com/alibaba/demo/dto/query/RecordListByParamQuery.java @@ -0,0 +1,28 @@ +package com.alibaba.demo.dto.query; + +import com.alibaba.cola.dto.PageQuery; +import lombok.Data; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.luckyclient.dto.query + * @createTime 2022/12/9 - 23:19 + * @description + */ +@Data +public class RecordListByParamQuery extends PageQuery { + + private Long recordId; + + private Long userId; + + private Long activityId; + + /** + * true:中奖,false:未中奖 + */ + private Boolean winTheLottery; + + + private Integer status; +} diff --git a/demo-web-domain/src/main/java/com/alibaba/demo/domain/activity/ActivityTime.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/activity/ActivityTime.java index c35da27..3e6cb48 100644 --- a/demo-web-domain/src/main/java/com/alibaba/demo/domain/activity/ActivityTime.java +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/activity/ActivityTime.java @@ -1,7 +1,9 @@ package com.alibaba.demo.domain.activity; import com.alibaba.cola.demo.web.exception.LdException; +import lombok.Data; import lombok.Getter; +import lombok.NoArgsConstructor; import java.time.LocalDateTime; import java.util.Objects; @@ -13,7 +15,8 @@ import java.util.Objects; * @Date 2024/2/28 15:27 * @Version 1.0 **/ -@Getter +@Data +@NoArgsConstructor public class ActivityTime { /** * startTime diff --git a/demo-web-domain/src/main/java/com/alibaba/demo/domain/award/AwardEntity.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/award/AwardEntity.java index cb51651..d4f94b8 100644 --- a/demo-web-domain/src/main/java/com/alibaba/demo/domain/award/AwardEntity.java +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/award/AwardEntity.java @@ -1,6 +1,7 @@ package com.alibaba.demo.domain.award; import com.alibaba.cola.domain.Entity; +import com.alibaba.demo.domain.prize.PrizeEntity; import lombok.Data; import java.time.LocalDateTime; @@ -15,6 +16,7 @@ import java.time.LocalDateTime; @Data public class AwardEntity { + /** * */ @@ -64,11 +66,13 @@ public class AwardEntity { /** - * 判断该奖项是否是一个奖品,也即该奖项是否中奖 + * 判断该奖项是否是一个奖品,也即该奖项是否中奖:谢谢惠顾的奖项ID为0 * * @return */ public Boolean isPrize() { - return !"0".equals(this.prizeId.toString()); + return !PrizeEntity.THINKS_PRIZE_ID.equals(this.prizeId.toString()); } + + } diff --git a/demo-web-domain/src/main/java/com/alibaba/demo/domain/gateway/ActivityCacheGateWay.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/gateway/ActivityCacheGateWay.java new file mode 100644 index 0000000..89b56ee --- /dev/null +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/gateway/ActivityCacheGateWay.java @@ -0,0 +1,39 @@ +package com.alibaba.demo.domain.gateway; + +import com.alibaba.cola.demo.web.vo.PageResultInfo; +import com.alibaba.demo.domain.activity.ActivityEntity; +import com.alibaba.demo.dto.data.ActivityConfigVO; +import com.alibaba.demo.dto.data.ActivityVO; +import com.alibaba.demo.dto.query.ActivityListByParamQuery; + +import java.time.Duration; + +/** + * @Author guocheng + * @Description 活动缓存防腐层 + * @Date 19:43 2024/3/1 + * @Param + * @return + **/ +public interface ActivityCacheGateWay { + + + PageResultInfo page(String queryKey); + + + + boolean setPage(PageResultInfo pageData, String cacheKey, Duration duration); + + + ActivityConfigVO one(String queryKey); + + + boolean setOne(ActivityConfigVO oneData,String cacheKey,Duration duration); + + + + + + + +} diff --git a/demo-web-domain/src/main/java/com/alibaba/demo/domain/gateway/ActivityGateway.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/gateway/ActivityGateway.java index 9a1fac9..4225efb 100644 --- a/demo-web-domain/src/main/java/com/alibaba/demo/domain/gateway/ActivityGateway.java +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/gateway/ActivityGateway.java @@ -1,7 +1,9 @@ package com.alibaba.demo.domain.gateway; +import com.alibaba.cola.demo.web.vo.PageResultInfo; import com.alibaba.demo.domain.activity.ActivityEntity; +import com.alibaba.demo.dto.query.ActivityListByParamQuery; /** * @author J3(about:https://j3code.cn) @@ -14,6 +16,6 @@ public interface ActivityGateway { ActivityEntity save(ActivityEntity entity); -// IPage page(ActivityListByParamQuery query); + PageResultInfo page(ActivityListByParamQuery query); } diff --git a/demo-web-domain/src/main/java/com/alibaba/demo/domain/gateway/AwardCacheGateWay.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/gateway/AwardCacheGateWay.java new file mode 100644 index 0000000..36612f4 --- /dev/null +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/gateway/AwardCacheGateWay.java @@ -0,0 +1,39 @@ +package com.alibaba.demo.domain.gateway; + +import com.alibaba.cola.demo.web.vo.PageResultInfo; +import com.alibaba.demo.dto.data.ActivityConfigVO; +import com.alibaba.demo.dto.data.ActivityVO; +import com.alibaba.demo.dto.data.AwardVO; + +import java.time.Duration; +import java.util.List; + +/** + * @Author guocheng + * @Description 奖项缓存防腐层 + * @Date 19:43 2024/3/1 + * @Param + * @return + **/ +public interface AwardCacheGateWay { + + + boolean setAwardInventory(List awardVOS,Duration duration); + + /** + * 扣减库存 + **/ + boolean invokeStockDeductionLua(Long activityId, Long awardId); + + /** + * 扣减库存回滚 + **/ + boolean invokeStockDeductionLuaRollback(Long activityId, Long awardId); + + + + + + + +} diff --git a/demo-web-domain/src/main/java/com/alibaba/demo/domain/gateway/AwardGateway.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/gateway/AwardGateway.java index ce04b37..05480b5 100644 --- a/demo-web-domain/src/main/java/com/alibaba/demo/domain/gateway/AwardGateway.java +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/gateway/AwardGateway.java @@ -1,7 +1,9 @@ package com.alibaba.demo.domain.gateway; +import com.alibaba.cola.demo.web.vo.PageResultInfo; import com.alibaba.demo.domain.award.AwardEntity; +import com.alibaba.demo.dto.query.AwardListByParamQuery; /** * @author J3(about:https://j3code.cn) @@ -13,7 +15,7 @@ public interface AwardGateway { AwardEntity save(AwardEntity entity); -// IPage page(AwardListByParamQuery query); + PageResultInfo page(AwardListByParamQuery query); int deductionAwardNumber(Long awardId, Integer number); } diff --git a/demo-web-domain/src/main/java/com/alibaba/demo/domain/gateway/RecordGateway.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/gateway/RecordGateway.java new file mode 100644 index 0000000..6798c25 --- /dev/null +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/gateway/RecordGateway.java @@ -0,0 +1,19 @@ +package com.alibaba.demo.domain.gateway; + + +import com.alibaba.cola.demo.web.vo.PageResultInfo; +import com.alibaba.demo.domain.record.RecordEntity; +import com.alibaba.demo.dto.query.RecordListByParamQuery; + +import java.math.BigDecimal; + +public interface RecordGateway { + + RecordEntity save(RecordEntity entity); + + PageResultInfo page(RecordListByParamQuery query); + + Boolean updateStatus(Long id, Integer status); + + BigDecimal getPrizeMoneyByRecordId(Long recordId); +} diff --git a/demo-web-domain/src/main/java/com/alibaba/demo/domain/prize/PrizeEntity.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/prize/PrizeEntity.java index bd47cea..fc97617 100644 --- a/demo-web-domain/src/main/java/com/alibaba/demo/domain/prize/PrizeEntity.java +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/prize/PrizeEntity.java @@ -15,6 +15,10 @@ import java.time.LocalDateTime; @Entity @Data public class PrizeEntity { + /** + * 谢谢惠顾奖品ID + **/ + public final static String THINKS_PRIZE_ID="0"; /** * @@ -60,4 +64,7 @@ public class PrizeEntity { * */ private String updater; + + + } diff --git a/demo-web-domain/src/main/java/com/alibaba/demo/domain/record/RecordStatus.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/record/RecordStatus.java index e29a0e2..75cfc36 100644 --- a/demo-web-domain/src/main/java/com/alibaba/demo/domain/record/RecordStatus.java +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/record/RecordStatus.java @@ -3,6 +3,7 @@ package com.alibaba.demo.domain.record; import com.alibaba.cola.demo.web.enums.RecordStatusEnum; import com.alibaba.cola.demo.web.util.AssertUtil; +import lombok.Getter; /** * @author J3(about:https://j3code.cn) @@ -10,6 +11,7 @@ import com.alibaba.cola.demo.web.util.AssertUtil; * @createTime 2022/12/9 - 23:06 * @description */ +@Getter public class RecordStatus { /** @@ -54,4 +56,7 @@ public class RecordStatus { } + + + } diff --git a/demo-web-infrastructure/pom.xml b/demo-web-infrastructure/pom.xml index d2a6f44..538d216 100644 --- a/demo-web-infrastructure/pom.xml +++ b/demo-web-infrastructure/pom.xml @@ -43,6 +43,14 @@ org.mapstruct mapstruct + + org.springframework.boot + spring-boot-starter-data-redis + + + cn.hutool + hutool-all + diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/config/MyMetaObjectHandler.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/config/MyMetaObjectHandler.java new file mode 100644 index 0000000..558d819 --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/config/MyMetaObjectHandler.java @@ -0,0 +1,37 @@ +package com.alibaba.demo.config; + +import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; +import lombok.extern.slf4j.Slf4j; +import org.apache.ibatis.reflection.MetaObject; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.common.handler + * @createTime 2022/11/26 - 21:50 + * @description + */ +@Slf4j +@Component +public class MyMetaObjectHandler implements MetaObjectHandler { + + @Override + public void insertFill(MetaObject metaObject) { + // 起始版本 3.3.3(推荐) + this.strictInsertFill(metaObject, "createTime", LocalDateTime::now, LocalDateTime.class); + // 起始版本 3.3.3(推荐) + this.strictInsertFill(metaObject, "updateTime", LocalDateTime::now, LocalDateTime.class); + this.strictInsertFill(metaObject, "creator", ()->"GSean", String.class); + this.strictInsertFill(metaObject, "updater", ()->"GSean", String.class); + } + + @Override + public void updateFill(MetaObject metaObject) { + // 起始版本 3.3.3(推荐) + this.strictUpdateFill(metaObject, "updateTime", LocalDateTime::now, LocalDateTime.class); + this.strictUpdateFill(metaObject, "updater", ()->"GSean", String.class); + } + +} diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/config/MybatisPlusConfig.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/config/MybatisPlusConfig.java new file mode 100644 index 0000000..494b4b5 --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/config/MybatisPlusConfig.java @@ -0,0 +1,28 @@ +package com.alibaba.demo.config; + +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @ClassName MybatisPlusConfig + * @Description TODO + * @Author Jincheng.Guo + * @Date 2024/2/29 22:11 + * @Version 1.0 + **/ +@Configuration +public class MybatisPlusConfig { + /** + * 添加分页插件 + */ + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));//如果配置多个插件,切记分页最后添加 + //interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); 如果有多数据源可以不配具体类型 否则都建议配上具体的DbType + return interceptor; + } +} diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/config/RedisConfig.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/config/RedisConfig.java new file mode 100644 index 0000000..cd80a35 --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/config/RedisConfig.java @@ -0,0 +1,107 @@ +package com.alibaba.demo.config; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; +import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.CachingConfigurerSupport; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializationContext; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +import java.time.Duration; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.common.config + * @createTime 2022/11/26 - 21:53 + * @description + */ +@Slf4j +@Configuration +@EnableCaching +public class RedisConfig extends CachingConfigurerSupport { + + // 这是缓存有效期 一天 + private Duration timeToLive = Duration.ofDays(1); + + /** + * 配置Jackson2JsonRedisSerializer序列化策略 + * */ + private Jackson2JsonRedisSerializer serializer() { + // 使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值 + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class); + ObjectMapper objectMapper = new ObjectMapper(); + + objectMapper.registerModule(new JavaTimeModule()); + objectMapper.registerModule(new Jdk8Module()); + + // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public + objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + + objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + + // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常 + objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL); + + // 反序列化忽略不存在的值,防止报错 + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false); + jackson2JsonRedisSerializer.setObjectMapper(objectMapper); + return jackson2JsonRedisSerializer; + } + + + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) { + RedisTemplate redisTemplate = new RedisTemplate<>(); + redisTemplate.setConnectionFactory(redisConnectionFactory); + // 用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值 + redisTemplate.setValueSerializer(serializer()); + + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // 使用StringRedisSerializer来序列化和反序列化redis的key值 + redisTemplate.setKeySerializer(stringRedisSerializer); + + // hash的key也采用String的序列化方式 + redisTemplate.setHashKeySerializer(stringRedisSerializer); + // hash的value序列化方式采用jackson + redisTemplate.setHashValueSerializer(serializer()); + redisTemplate.afterPropertiesSet(); + return redisTemplate; + } + + + + + @Bean + public CacheManager cacheManager(RedisConnectionFactory factory) { + RedisSerializer redisSerializer = new StringRedisSerializer(); + // 配置序列化(解决乱码的问题) + RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() + // 缓存有效期 + .entryTtl(timeToLive) + // 使用StringRedisSerializer来序列化和反序列化redis的key值 + .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer)) + // 使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值 + .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(serializer())) + // 禁用空值 + .disableCachingNullValues(); + + return RedisCacheManager.builder(factory) + .cacheDefaults(config) + .build(); + } +} diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/converter/AwardConvertor.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/converter/AwardConvertor.java new file mode 100644 index 0000000..e8bca62 --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/converter/AwardConvertor.java @@ -0,0 +1,21 @@ +package com.alibaba.demo.converter; + +import com.alibaba.demo.database.dataobject.AwardDO; +import com.alibaba.demo.domain.award.AwardEntity; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.luckyinfrastructure.convertor + * @createTime 2022/12/3 - 0:09 + * @description + */ +@Mapper(componentModel = "spring") +public interface AwardConvertor { + @Mapping(target = "number",source = "number.number") + AwardDO toAwardDO(AwardEntity entity); + + @Mapping(target = "number.number",source = "number") + AwardEntity toEntity(AwardDO awardDO); +} diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/converter/RecordConvertor.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/converter/RecordConvertor.java new file mode 100644 index 0000000..66c5203 --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/converter/RecordConvertor.java @@ -0,0 +1,26 @@ +package com.alibaba.demo.converter; + +import com.alibaba.demo.database.dataobject.RecordDO; +import com.alibaba.demo.domain.record.RecordEntity; +import com.alibaba.demo.domain.record.RecordStatus; +import org.mapstruct.Mapper; + +@Mapper(componentModel = "spring") +public interface RecordConvertor { + RecordDO toRecordDO(RecordEntity entity); + RecordEntity toEntity(RecordDO activityDO); + + + + default RecordStatus toStatus(Integer status){ + return new RecordStatus(status); + } + + + default Integer getStatus(RecordStatus recordStatus){ + return recordStatus.getState(); + } + + + +} diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/database/dataobject/ActivityDO.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/database/dataobject/ActivityDO.java index 17c4068..761ae26 100644 --- a/demo-web-infrastructure/src/main/java/com/alibaba/demo/database/dataobject/ActivityDO.java +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/database/dataobject/ActivityDO.java @@ -1,6 +1,7 @@ package com.alibaba.demo.database.dataobject; import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.databind.ser.Serializers; import lombok.Data; import java.io.Serializable; @@ -12,7 +13,7 @@ import java.time.LocalDateTime; */ @TableName(value ="activity") @Data -public class ActivityDO implements Serializable { +public class ActivityDO extends BaseDO { /** * */ @@ -40,28 +41,5 @@ public class ActivityDO implements Serializable { @TableField("`describe`") private String describe; - /** - * - */ - @TableField(fill = FieldFill.INSERT) - private LocalDateTime createTime; - - /** - * - */ - private String creator; - - /** - * - */ - @TableField(fill = FieldFill.INSERT_UPDATE) - private LocalDateTime updateTime; - - /** - * - */ - private String updater; - @TableField(exist = false) - private static final long serialVersionUID = 1L; } \ No newline at end of file diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/database/dataobject/AwardDO.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/database/dataobject/AwardDO.java new file mode 100644 index 0000000..87ac12b --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/database/dataobject/AwardDO.java @@ -0,0 +1,46 @@ +package com.alibaba.demo.database.dataobject; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * + * @TableName bld_award + */ +@TableName(value ="award") +@Data +public class AwardDO extends BaseDO { + /** + * + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 奖品名称 + */ + private Long prizeId; + @TableField(exist = false) + private String prizeName; + + private Long activityId; + + /** + * 数量 + */ + private Integer number; + + /** + * 奖项名称 + */ + private String awardName; + + /** + * 概率 + */ + private Double probability; + +} \ No newline at end of file diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/database/dataobject/BaseDO.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/database/dataobject/BaseDO.java new file mode 100644 index 0000000..8da70c2 --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/database/dataobject/BaseDO.java @@ -0,0 +1,43 @@ +package com.alibaba.demo.database.dataobject; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * @ClassName BaseDO + * @Description TODO + * @Author Jincheng.Guo + * @Date 2024/3/1 17:43 + * @Version 1.0 + **/ +@Data +public class BaseDO implements Serializable { + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 创建人 + */ + @TableField(fill = FieldFill.INSERT) + private String creator; + + /** + * 更新时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + /** + * 更新人 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updater; +} diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/database/dataobject/PrizeDO.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/database/dataobject/PrizeDO.java index 6e44e8b..38f09f0 100644 --- a/demo-web-infrastructure/src/main/java/com/alibaba/demo/database/dataobject/PrizeDO.java +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/database/dataobject/PrizeDO.java @@ -1,6 +1,7 @@ package com.alibaba.demo.database.dataobject; import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.databind.ser.Serializers; import lombok.Data; import java.io.Serializable; @@ -13,7 +14,7 @@ import java.time.LocalDateTime; */ @TableName(value ="prize") @Data -public class PrizeDO implements Serializable { +public class PrizeDO extends BaseDO { /** * */ @@ -40,28 +41,5 @@ public class PrizeDO implements Serializable { */ private Integer type; - /** - * - */ - @TableField(fill = FieldFill.INSERT) - private LocalDateTime createTime; - - /** - * - */ - private String creator; - - /** - * - */ - @TableField(fill = FieldFill.INSERT_UPDATE) - private LocalDateTime updateTime; - - /** - * - */ - private String updater; - @TableField(exist = false) - private static final long serialVersionUID = 1L; } \ No newline at end of file diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/database/dataobject/RecordDO.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/database/dataobject/RecordDO.java new file mode 100644 index 0000000..5f63fa8 --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/database/dataobject/RecordDO.java @@ -0,0 +1,60 @@ +package com.alibaba.demo.database.dataobject; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * + * @TableName bld_record + */ +@TableName(value ="record") +@Data +public class RecordDO extends BaseDO { + /** + * + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 用户id + */ + private Long userId; + + /** + * 活动id + */ + private Long activityId; + + private String activityName; + + /** + * 奖项id + */ + private Long awardId; + + @TableField(exist = false) + private String awardName; + + @TableField(exist = false) + private String prizeName; + + @TableField(exist = false) + private Integer prizeType; + + /** + * 是否中奖:0未中奖,1中奖 + */ + private Integer isWinning; + + /** + * 状态(0,1,2,3) + */ + private Integer state; + + + +} \ No newline at end of file diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/ActivityGatewayImpl.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/ActivityGatewayImpl.java index 6b947e2..83b7912 100644 --- a/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/ActivityGatewayImpl.java +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/ActivityGatewayImpl.java @@ -2,11 +2,18 @@ package com.alibaba.demo.gateway.impl; import com.alibaba.cola.demo.web.enums.LdExceptionEnum; import com.alibaba.cola.demo.web.util.AssertUtil; +import com.alibaba.cola.demo.web.vo.PageResultInfo; import com.alibaba.demo.converter.ActivityConvertor; import com.alibaba.demo.database.dataobject.ActivityDO; +import com.alibaba.demo.database.dataobject.AwardDO; import com.alibaba.demo.domain.activity.ActivityEntity; import com.alibaba.demo.domain.gateway.ActivityGateway; +import com.alibaba.demo.dto.query.ActivityListByParamQuery; import com.alibaba.demo.mapper.ActivityMapper; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -27,6 +34,18 @@ public class ActivityGatewayImpl implements ActivityGateway { private final ActivityMapper activityMapper; private final ActivityConvertor activityConvertor; + @Override + public PageResultInfo page(ActivityListByParamQuery query) { + LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery() + .like(Objects.nonNull(query.getActivityName()), ActivityDO::getActivityName, query.getActivityName()) + .eq(Objects.nonNull(query.getId()), ActivityDO::getId, query.getId()) + .lt(Objects.nonNull(query.getEndTime()),ActivityDO::getEndTime,query.getEndTime()) + .gt(Objects.nonNull(query.getStartTime()),ActivityDO::getStartTime,query.getStartTime()); + Page queryPage = Page.of(query.getPageIndex(), query.getPageSize()); + IPage page = activityMapper.selectPage(queryPage, queryWrapper); + return PageResultInfo.pageConvert(activityConvertor::toEntity,page.getRecords(),page.getTotal(),page.getCurrent(),page.getSize()); + } + @Override public ActivityEntity save(ActivityEntity entity) { if (Objects.isNull(entity.getId())) { diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/ActivityRedisCacheGatewayImpl.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/ActivityRedisCacheGatewayImpl.java new file mode 100644 index 0000000..2c73f46 --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/ActivityRedisCacheGatewayImpl.java @@ -0,0 +1,58 @@ +package com.alibaba.demo.gateway.impl; + +import cn.hutool.crypto.digest.DigestUtil; +import com.alibaba.cola.demo.web.vo.PageResultInfo; +import com.alibaba.demo.domain.activity.ActivityEntity; +import com.alibaba.demo.domain.gateway.ActivityCacheGateWay; +import com.alibaba.demo.domain.gateway.ActivityGateway; +import com.alibaba.demo.dto.data.ActivityConfigVO; +import com.alibaba.demo.dto.data.ActivityVO; +import com.alibaba.demo.dto.query.ActivityListByParamQuery; +import com.alibaba.fastjson.JSON; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; + +import java.time.Duration; +import java.util.Objects; + +/** + * @ClassName ActivityRedisCacheGatewayImpl + * @Description TODO + * @Author Jincheng.Guo + * @Date 2024/3/1 19:45 + * @Version 1.0 + **/ +@Slf4j +@Component +@AllArgsConstructor +public class ActivityRedisCacheGatewayImpl implements ActivityCacheGateWay { + private final ActivityGateway activityGateway; + private final RedisTemplate redisTemplate; + + + + @Override + public PageResultInfo page(String queryKey) { + log.info("开始查询缓存"); + return (PageResultInfo) redisTemplate.opsForValue().get(queryKey); + } + + @Override + public boolean setPage(PageResultInfo pageData, String cacheKey, Duration duration) { + redisTemplate.opsForValue().set(cacheKey,pageData,duration); + return true; + } + + @Override + public ActivityConfigVO one(String queryKey) { + return (ActivityConfigVO)redisTemplate.opsForValue().get(queryKey); + } + + @Override + public boolean setOne(ActivityConfigVO oneData, String cacheKey, Duration duration) { + redisTemplate.opsForValue().set(cacheKey,oneData,duration); + return true; + } +} diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/AwardGateWayImpl.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/AwardGateWayImpl.java index 1c3368a..db12729 100644 --- a/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/AwardGateWayImpl.java +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/AwardGateWayImpl.java @@ -1,11 +1,26 @@ package com.alibaba.demo.gateway.impl; +import com.alibaba.cola.demo.web.enums.LdExceptionEnum; +import com.alibaba.cola.demo.web.util.AssertUtil; +import com.alibaba.cola.demo.web.vo.PageResultInfo; +import com.alibaba.demo.converter.AwardConvertor; +import com.alibaba.demo.database.dataobject.AwardDO; +import com.alibaba.demo.database.dataobject.AwardDO; import com.alibaba.demo.domain.award.AwardEntity; import com.alibaba.demo.domain.gateway.AwardGateway; +import com.alibaba.demo.dto.query.AwardListByParamQuery; +import com.alibaba.demo.mapper.AwardMapper; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; +import java.util.Objects; +import java.util.Optional; + /** * @ClassName AwardGateWayImpl * @Description TODO @@ -17,13 +32,52 @@ import org.springframework.stereotype.Component; @Component @AllArgsConstructor public class AwardGateWayImpl implements AwardGateway { + private final AwardMapper awardMapper; + private final AwardConvertor awardConvertor; + + @Override public AwardEntity save(AwardEntity entity) { - return null; + if (Objects.isNull(entity.getId())) { + return addAward(entity); + } + return updateAward(entity); + } + + private AwardEntity addAward(AwardEntity entity) { + AwardDO awardDB = awardConvertor.toAwardDO(entity); + + AssertUtil.isTrue(awardMapper.insert(awardDB) <= 0, + LdExceptionEnum.ADD_ERROR.getDescription()); + + return awardConvertor.toEntity(awardDB); + } + + private AwardEntity updateAward(AwardEntity entity) { + AwardDO awardDB = awardConvertor.toAwardDO(entity); + + AssertUtil.isTrue(awardMapper.updateById(awardDB) <= 0, + LdExceptionEnum.UPDATE_ERROR.getDescription()); + + return awardConvertor.toEntity(awardDB); } + @Override + public PageResultInfo page(AwardListByParamQuery query) { + LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery() + .eq(Objects.nonNull(query.getAwardName()), AwardDO::getAwardName, query.getAwardName()) + .eq(Objects.nonNull(query.getActivityId()), AwardDO::getActivityId, query.getActivityId()) + .eq(Objects.nonNull(query.getActivityName()), AwardDO::getAwardName, query.getActivityName()) + .eq(Objects.nonNull(query.getId()), AwardDO::getId, query.getId()); + Page queryPage = Page.of(query.getPageIndex(), query.getPageSize()); + IPage page = awardMapper.selectPage(queryPage, queryWrapper); + return PageResultInfo.pageConvert(awardConvertor::toEntity,page.getRecords(),page.getTotal(),page.getCurrent(),page.getSize()); + } + + + @Override public int deductionAwardNumber(Long awardId, Integer number) { - return 0; + return awardMapper.deductionAwardNumber(awardId,number); } } diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/AwardRedisCacheGatewayImpl.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/AwardRedisCacheGatewayImpl.java new file mode 100644 index 0000000..4fceaa1 --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/AwardRedisCacheGatewayImpl.java @@ -0,0 +1,115 @@ +package com.alibaba.demo.gateway.impl; + +import cn.hutool.core.io.resource.ResourceUtil; +import com.alibaba.cola.demo.web.exception.LdException; +import com.alibaba.cola.demo.web.vo.PageResultInfo; +import com.alibaba.demo.domain.award.AwardEntity; +import com.alibaba.demo.domain.gateway.ActivityCacheGateWay; +import com.alibaba.demo.domain.gateway.ActivityGateway; +import com.alibaba.demo.domain.gateway.AwardCacheGateWay; +import com.alibaba.demo.domain.gateway.AwardGateway; +import com.alibaba.demo.dto.data.ActivityConfigVO; +import com.alibaba.demo.dto.data.ActivityVO; +import com.alibaba.demo.dto.data.AwardVO; +import com.alibaba.demo.dto.query.AwardListByParamQuery; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.script.DefaultRedisScript; +import org.springframework.data.redis.core.script.RedisScript; +import org.springframework.stereotype.Component; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * @ClassName AwardRedisCacheGatewayImpl + * @Description TODO + * @Author Jincheng.Guo + * @Date 2024/3/1 19:45 + * @Version 1.0 + **/ +@Slf4j +@Component +@AllArgsConstructor +public class AwardRedisCacheGatewayImpl implements AwardCacheGateWay { + private final RedisTemplate redisTemplate; + + + /** + * lucky-draw:activity:award:活动id:奖项id + */ + private static final String awardInventoryKey = "lucky-draw-award-inventory:activity:"; + private static final String awardInventoryHashKey = "award:"; + + + private static String stockDeductionLua; + private static String stockRollbackLua; + + static { + stockDeductionLua = ResourceUtil.readUtf8Str("lua/stock_deduction.lua"); + stockRollbackLua = ResourceUtil.readUtf8Str("lua/stock_rollback.lua"); + } + + + @Override + public boolean setAwardInventory(List awardVOS, Duration duration) { + boolean cacheTag=false; + try { + Optional> optionalAwardVOS = Optional.ofNullable(awardVOS); + Long activityId = optionalAwardVOS.orElseGet(ArrayList::new) + .stream() + .findFirst() + .map(AwardVO::getActivityId) + .orElseThrow(() -> new LdException("奖项活动信息不完整")); + // 生成hash + Map inventoryHash = optionalAwardVOS.orElseGet(ArrayList::new) + .stream() + .collect(Collectors.toMap(awardVO -> getHashKey(awardVO.getId()), awardVO -> awardVO.getNumber())); + redisTemplate.opsForHash().putAll(getKey(activityId),inventoryHash); + redisTemplate.expire(getKey(activityId),duration); + cacheTag=true; + } catch (LdException e) { + e.printStackTrace(); + } + return cacheTag; + } + + @Override + public boolean invokeStockDeductionLua(Long activityId, Long awardId) { + String key1 = getKey(activityId); + String key2 = getHashKey(awardId); + RedisScript redisScript = new DefaultRedisScript<>(stockDeductionLua, Long.class); + Long execute = redisTemplate.opsForValue().getOperations().execute( + redisScript, + List.of(key1,key2),-1); + return !execute.equals(-1L); + } + + @Override + public boolean invokeStockDeductionLuaRollback(Long activityId, Long awardId) { + String key1 = getKey(activityId); + String key2 = getHashKey(awardId); + RedisScript redisScript = new DefaultRedisScript<>(stockRollbackLua, Long.class); + Long execute = redisTemplate.opsForValue().getOperations().execute( + redisScript, + List.of(key1,key2),1); + return !execute.equals(-1L); + } + + + public static String getKey(Long activityId) { + + return awardInventoryKey + activityId; + } + + public static String getHashKey(Long awardId) { + + return awardInventoryHashKey + awardId; + } +} diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/PrizeGateWayImpl.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/PrizeGateWayImpl.java index 88b4dc8..739b05a 100644 --- a/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/PrizeGateWayImpl.java +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/PrizeGateWayImpl.java @@ -66,15 +66,13 @@ public class PrizeGateWayImpl implements PrizeGateway { private PrizeEntity addPrize(PrizeEntity entity) { PrizeDO prizeDB = prizeConvertor.toPrizeDO(entity); - AssertUtil.isTrue(prizeMapper.insert(prizeDB) <= 0, LdExceptionEnum.ADD_ERROR.getDescription()); - return prizeConvertor.toEntity(prizeDB); } @Override public int deductionInventory(Long prizeId, Integer number) { - return 0; + return prizeMapper.deductionInventory(prizeId,number); } } diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/RecordGatewayImpl.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/RecordGatewayImpl.java new file mode 100644 index 0000000..742bb8f --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/RecordGatewayImpl.java @@ -0,0 +1,49 @@ +package com.alibaba.demo.gateway.impl; + +import com.alibaba.cola.demo.web.enums.LdExceptionEnum; +import com.alibaba.cola.demo.web.util.AssertUtil; +import com.alibaba.cola.demo.web.vo.PageResultInfo; +import com.alibaba.demo.converter.RecordConvertor; +import com.alibaba.demo.database.dataobject.RecordDO; +import com.alibaba.demo.domain.gateway.RecordGateway; +import com.alibaba.demo.domain.record.RecordEntity; +import com.alibaba.demo.dto.query.RecordListByParamQuery; +import com.alibaba.demo.mapper.RecordMapper; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.math.BigDecimal; + +@Slf4j +@Component +@AllArgsConstructor +public class RecordGatewayImpl implements RecordGateway { + + private RecordMapper recordMapper; + private RecordConvertor recordConvertor; + + + @Override + public RecordEntity save(RecordEntity entity) { + RecordDO recordDB = recordConvertor.toRecordDO(entity); + AssertUtil.isTrue(recordMapper.insert(recordDB) != 1, LdExceptionEnum.ADD_ERROR.getDescription()); + + return recordConvertor.toEntity(recordDB); + } + + @Override + public PageResultInfo page(RecordListByParamQuery query) { + return null; + } + + @Override + public Boolean updateStatus(Long id, Integer status) { + return null; + } + + @Override + public BigDecimal getPrizeMoneyByRecordId(Long recordId) { + return null; + } +} diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/mapper/AwardMapper.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/mapper/AwardMapper.java new file mode 100644 index 0000000..13fe934 --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/mapper/AwardMapper.java @@ -0,0 +1,28 @@ +package com.alibaba.demo.mapper; + +import com.alibaba.demo.database.dataobject.AwardDO; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** +* @author Administrator +* @description 针对表【bld_award】的数据库操作Mapper +* @createDate 2022-11-26 23:02:09 +* @Entity cn.j3code.lduser.po.Award +*/ +@Mapper +public interface AwardMapper extends BaseMapper { + + + + int deductionAwardNumber(@Param("awardId") Long awardId, @Param("number") Integer number); + + + + +} + + + + diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/mapper/PrizeMapper.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/mapper/PrizeMapper.java index ed96eeb..cc75818 100644 --- a/demo-web-infrastructure/src/main/java/com/alibaba/demo/mapper/PrizeMapper.java +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/mapper/PrizeMapper.java @@ -3,6 +3,7 @@ package com.alibaba.demo.mapper; import com.alibaba.demo.database.dataobject.PrizeDO; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; /** * @description 针对表【bld_activity】的数据库操作Mapper @@ -12,6 +13,10 @@ public interface PrizeMapper extends BaseMapper { + int deductionInventory(@Param("prizeId") Long prizeId, @Param("number") Integer number); + + + } diff --git a/demo-web-infrastructure/src/main/java/com/alibaba/demo/mapper/RecordMapper.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/mapper/RecordMapper.java new file mode 100644 index 0000000..9d4eb9a --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/mapper/RecordMapper.java @@ -0,0 +1,27 @@ +package com.alibaba.demo.mapper; + +import com.alibaba.demo.database.dataobject.RecordDO; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.math.BigDecimal; + +/** +* @author Administrator +* @description 针对表【bld_record】的数据库操作Mapper +* @createDate 2022-11-26 23:01:54 +* @Entity cn.j3code.lduser.po.Record +*/ +@Mapper +public interface RecordMapper extends BaseMapper { + + + Integer updateStatus(@Param("id") Long id, @Param("status") Integer status); + + BigDecimal getPrizeMoneyByRecordId(@Param("recordId") Long recordId); +} + + + + diff --git a/demo-web-infrastructure/src/main/resources/mybatis/mybatis-config.xml b/demo-web-infrastructure/src/main/resources/mybatis-config.xml similarity index 100% rename from demo-web-infrastructure/src/main/resources/mybatis/mybatis-config.xml rename to demo-web-infrastructure/src/main/resources/mybatis-config.xml diff --git a/demo-web-infrastructure/src/main/resources/mybatis/AwardMapper.xml b/demo-web-infrastructure/src/main/resources/mybatis/AwardMapper.xml new file mode 100644 index 0000000..61a0fbf --- /dev/null +++ b/demo-web-infrastructure/src/main/resources/mybatis/AwardMapper.xml @@ -0,0 +1,11 @@ + + + + + + update award a + set a.number = a.number - #{number} + where a.id = #{awardId} + and (a.number - #{number}) >= 0 + + \ No newline at end of file diff --git a/demo-web-infrastructure/src/main/resources/mybatis/PrizeMapper.xml b/demo-web-infrastructure/src/main/resources/mybatis/PrizeMapper.xml new file mode 100644 index 0000000..7afd892 --- /dev/null +++ b/demo-web-infrastructure/src/main/resources/mybatis/PrizeMapper.xml @@ -0,0 +1,10 @@ + + + + + update prize + set inventory = inventory - #{number} + where id = #{prizeId} + and (inventory - #{number}) >= 0 + + \ No newline at end of file diff --git a/demo-web-infrastructure/src/test/java/com/alibaba/demo/gateway/impl/AwardRedisCacheGatewayImplTest.java b/demo-web-infrastructure/src/test/java/com/alibaba/demo/gateway/impl/AwardRedisCacheGatewayImplTest.java new file mode 100644 index 0000000..1f3a8c3 --- /dev/null +++ b/demo-web-infrastructure/src/test/java/com/alibaba/demo/gateway/impl/AwardRedisCacheGatewayImplTest.java @@ -0,0 +1,78 @@ +package com.alibaba.demo.gateway.impl; + +import cn.hutool.core.lang.Snowflake; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.RandomUtil; +import com.alibaba.demo.config.RedisConfig; +import com.alibaba.demo.dto.data.AwardVO; +import com.github.jsonzou.jmockdata.JMockData; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.slf4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import static org.mockito.Mockito.*; +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = {RedisAutoConfiguration.class, RedisConfig.class, AwardRedisCacheGatewayImplTest.CustomConfig.class}) +public class AwardRedisCacheGatewayImplTest { + + @Autowired + AwardRedisCacheGatewayImpl awardRedisCacheGatewayImpl; + + + static class CustomConfig{ + @Bean + public AwardRedisCacheGatewayImpl awardRedisCacheGateway(RedisTemplate redisTemplate){ + return new AwardRedisCacheGatewayImpl(redisTemplate); + } + } + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void testSetAwardInventory() throws Exception { + List inventoryNumbers = Arrays.asList(3, 2, 6, 7); + Snowflake snowflake = IdUtil.createSnowflake(1, 1); + List awardVOS = inventoryNumbers.stream() + .map(item -> { + AwardVO mock = new AwardVO(); + mock.setActivityId(1L); + mock.setId(snowflake.nextId()); + mock.setNumber(item); + return mock; + }).collect(Collectors.toList()); + boolean result = awardRedisCacheGatewayImpl.setAwardInventory(awardVOS,null); + Assert.assertEquals(true, result); + } + + @Test + public void testGetKey() throws Exception { + String result = AwardRedisCacheGatewayImpl.getKey(Long.valueOf(1)); + Assert.assertEquals("replaceMeWithExpectedResult", result); + } + + @Test + public void testGetHashKey() throws Exception { + String result = AwardRedisCacheGatewayImpl.getHashKey(Long.valueOf(1)); + Assert.assertEquals("replaceMeWithExpectedResult", result); + } +} + +//Generated with love by TestMe :) Please report issues and submit feature requests at: http://weirddev.com/forum#!/testme \ No newline at end of file diff --git a/demo-web-infrastructure/src/test/java/com/alibaba/demo/mapper/AwardMapperTest.java b/demo-web-infrastructure/src/test/java/com/alibaba/demo/mapper/AwardMapperTest.java new file mode 100644 index 0000000..10924f5 --- /dev/null +++ b/demo-web-infrastructure/src/test/java/com/alibaba/demo/mapper/AwardMapperTest.java @@ -0,0 +1,50 @@ +package com.alibaba.demo.mapper; + +import com.alibaba.demo.database.dataobject.AwardDO; +import com.baomidou.mybatisplus.core.MybatisSqlSessionFactoryBuilder; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import org.apache.ibatis.session.SqlSessionFactory; +import org.apache.ibatis.session.SqlSessionFactoryBuilder; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +public class AwardMapperTest { + + + private static AwardMapper mapper; + + + @BeforeClass + public static void init() { + SqlSessionFactory builder = new SqlSessionFactoryBuilder().build( + AwardMapperTest.class.getClassLoader().getResourceAsStream("mybatis-config.xml") + ); + mapper = builder.getConfiguration().getMapper(AwardMapper.class, builder.openSession(true)); + } + + @BeforeClass + public static void setUpMybatisDatabase() { + SqlSessionFactory builder = new MybatisSqlSessionFactoryBuilder().build(AwardMapperTest.class.getClassLoader().getResourceAsStream("mybatisTestConfiguration/AwardMapperTestConfiguration.xml")); + final MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); + interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); + builder.getConfiguration().addInterceptor(interceptor); + //you can use builder.openSession(false) to not commit to database + mapper = builder.getConfiguration().getMapper(AwardMapper.class, builder.openSession(true)); + + } + + + @Test + public void testA() { +// int i = mapper.deductionAwardNumber(1L, 1); +// System.out.println(i); + } + + +} + +//Generated with love by TestMe :) Please report issues and submit feature requests at: http://weirddev.com/forum#!/testme \ No newline at end of file diff --git a/demo-web-infrastructure/src/test/java/com/alibaba/demo/mapper/PrizeMapperTest.java b/demo-web-infrastructure/src/test/java/com/alibaba/demo/mapper/PrizeMapperTest.java new file mode 100644 index 0000000..f431e55 --- /dev/null +++ b/demo-web-infrastructure/src/test/java/com/alibaba/demo/mapper/PrizeMapperTest.java @@ -0,0 +1,33 @@ +package com.alibaba.demo.mapper; + +import org.apache.ibatis.session.SqlSessionFactory; +import org.apache.ibatis.session.SqlSessionFactoryBuilder; +import org.junit.BeforeClass; +import org.junit.Test; + +public class PrizeMapperTest { + + + + + private static PrizeMapper mapper; + + + + @BeforeClass + public static void init(){ + SqlSessionFactory builder=new SqlSessionFactoryBuilder().build( + PrizeMapperTest.class.getClassLoader().getResourceAsStream("mybatis-config.xml") + ); + mapper = builder.getConfiguration().getMapper(PrizeMapper.class, builder.openSession(true)); + } + + + @Test + public void testDeductionInventory(){ + int i = mapper.deductionInventory(1L, 1); + System.out.println(i); + } +} + +//Generated with love by TestMe :) Please report issues and submit feature requests at: http://weirddev.com/forum#!/testme \ No newline at end of file diff --git a/demo-web-infrastructure/src/test/java/com/alibaba/demo/mapper/RecordMapperTest.java b/demo-web-infrastructure/src/test/java/com/alibaba/demo/mapper/RecordMapperTest.java new file mode 100644 index 0000000..3af52b8 --- /dev/null +++ b/demo-web-infrastructure/src/test/java/com/alibaba/demo/mapper/RecordMapperTest.java @@ -0,0 +1,38 @@ +package com.alibaba.demo.mapper; + +import com.baomidou.mybatisplus.core.MybatisSqlSessionFactoryBuilder; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import org.apache.ibatis.session.SqlSessionFactory; +import org.junit.BeforeClass; +import org.junit.Test; + +/** + * @ClassName RecordMapperTest + * @Description TODO + * @Author Jincheng.Guo + * @Date 2024/3/5 21:01 + * @Version 1.0 + **/ +public class RecordMapperTest { + private static RecordMapper mapper; + + @BeforeClass + public static void setUpMybatisDatabase() { + SqlSessionFactory builder = new MybatisSqlSessionFactoryBuilder().build(RecordMapperTest.class.getClassLoader().getResourceAsStream("mybatisTestConfiguration/RecordMapperTestConfiguration.xml")); + final MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); + interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); + builder.getConfiguration().addInterceptor(interceptor); + //you can use builder.openSession(false) to not commit to database + mapper = builder.getConfiguration().getMapper(RecordMapper.class, builder.openSession(true)); + + } + + @Test + public void testUpdateStatus() { + +// mapper.updateStatus(); + } +} diff --git a/demo-web-infrastructure/src/test/java/com/alibaba/demo/repository/RedisCacheTest.java b/demo-web-infrastructure/src/test/java/com/alibaba/demo/repository/RedisCacheTest.java new file mode 100644 index 0000000..5baa115 --- /dev/null +++ b/demo-web-infrastructure/src/test/java/com/alibaba/demo/repository/RedisCacheTest.java @@ -0,0 +1,76 @@ +package com.alibaba.demo.repository; + +import cn.hutool.core.io.resource.ResourceUtil; +import com.alibaba.cola.demo.web.vo.PageResultInfo; +import com.alibaba.demo.config.RedisConfig; +import com.alibaba.demo.database.dataobject.ActivityDO; +import com.alibaba.demo.domain.activity.ActivityEntity; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.TypeReference; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.script.DefaultRedisScript; +import org.springframework.data.redis.core.script.RedisScript; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.util.Arrays; +import java.util.List; + +/** + * @ClassName RedisCacheTest + * @Description TODO + * @Author Jincheng.Guo + * @Date 2024/3/1 20:25 + * @Version 1.0 + **/ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = {RedisAutoConfiguration.class, RedisConfig.class}) +public class RedisCacheTest { + + + @Autowired + private RedisTemplate redisTemplate; + @Autowired + private RedisTemplate redisTemplate2; + + + @Test + public void testA(){ + String k1 = redisTemplate.opsForValue().get("k1"); + System.out.println(k1); + } + + + @Test + public void testB(){ + String value="{\"id\":6,\"activityName\":\"建看铁拉响\",\"startTime\":\"2024-01-05T04:03:06\",\"endTime\":\"2024-05-06T02:41:16\",\"describe\":\"laborum mollit adipisicing\",\"status\":1,\"createTime\":\"2024-03-01T17:42:05\",\"creator\":\"GSean\",\"updateTime\":\"2024-03-01T17:42:05\",\"updater\":\"GSean\"}"; + ActivityEntity act = JSON.parseObject(value, new TypeReference(){}); + PageResultInfo build = PageResultInfo.builder() + .pageIndex(1) + .pageSize(2) + .totalCount(10) + .data(Arrays.asList(act)) + .build(); + redisTemplate2.opsForValue().set("act",build); + PageResultInfo act1 = (PageResultInfo) redisTemplate2.opsForValue().get("act"); + System.out.println(act1); + + } + + + + @Test + public void testExeScript(){ + String stockDeductionLua = ResourceUtil.readUtf8Str("lua/stock_deduction.lua"); + RedisScript redisScript = new DefaultRedisScript<>(stockDeductionLua, Long.class); + + Long execute = redisTemplate2.opsForValue().getOperations().execute( + redisScript, + List.of("lucky-draw-award-inventory:activity:1","award:1765015499529392129"),-1); + System.out.println(execute); + } +} diff --git a/demo-web-infrastructure/src/test/resources/lua/stock_deduction.lua b/demo-web-infrastructure/src/test/resources/lua/stock_deduction.lua new file mode 100644 index 0000000..434ced5 --- /dev/null +++ b/demo-web-infrastructure/src/test/resources/lua/stock_deduction.lua @@ -0,0 +1,15 @@ +local isExists = redis.call('hexists',KEYS[1],KEYS[2]) +if isExists == 1 then + --- 拿库存 + local deduction=tonumber(redis.call('hget',KEYS[1],KEYS[2])) + if deduction ~= nil and deduction > 0 + then + --- 减库存 + return redis.call('hincrby',KEYS[1],KEYS[2],ARGV[1]) + else + return -1 + end +end +if isExists == 0 then + return -1 +end \ No newline at end of file diff --git a/demo-web-infrastructure/src/test/resources/lua/stock_rollback.lua b/demo-web-infrastructure/src/test/resources/lua/stock_rollback.lua new file mode 100644 index 0000000..4c40b87 --- /dev/null +++ b/demo-web-infrastructure/src/test/resources/lua/stock_rollback.lua @@ -0,0 +1,7 @@ +local key = KEYS[1] +local usedstore = tonumber(redis.call('get', key)) +if usedstore ~= nil and usedstore > -1 then + local current = tonumber(redis.call('incr', key)) + return current +end +return usedstore \ No newline at end of file diff --git a/demo-web-infrastructure/src/test/resources/mybatis-config.xml b/demo-web-infrastructure/src/test/resources/mybatis-config.xml new file mode 100644 index 0000000..a130b24 --- /dev/null +++ b/demo-web-infrastructure/src/test/resources/mybatis-config.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/demo-web-infrastructure/src/test/resources/mybatisTestConfiguration/AwardMapperTestConfiguration.xml b/demo-web-infrastructure/src/test/resources/mybatisTestConfiguration/AwardMapperTestConfiguration.xml new file mode 100644 index 0000000..b6eda34 --- /dev/null +++ b/demo-web-infrastructure/src/test/resources/mybatisTestConfiguration/AwardMapperTestConfiguration.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/demo-web-infrastructure/src/test/resources/mybatisTestConfiguration/RecordMapperTestConfiguration.xml b/demo-web-infrastructure/src/test/resources/mybatisTestConfiguration/RecordMapperTestConfiguration.xml new file mode 100644 index 0000000..321b204 --- /dev/null +++ b/demo-web-infrastructure/src/test/resources/mybatisTestConfiguration/RecordMapperTestConfiguration.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pom.xml b/pom.xml index 9ce8b66..19be8c3 100644 --- a/pom.xml +++ b/pom.xml @@ -29,6 +29,8 @@ 5.2.0 3.4.3.4 1.18.10 + 2.0.2 + 2.28.2 @@ -52,6 +54,36 @@ junit test + + org.mockito + mockito-core + ${mockito.version} + test + + + org.powermock + powermock-module-junit4 + ${powermock.version} + test + + + org.powermock + powermock-api-mockito2 + ${powermock.version} + test + + + com.github.jsonzou + jmockdata + 4.1.2 + test + + + org.assertj + assertj-core + test + 3.5.2 + diff --git a/start/src/main/java/com/alibaba/demo/HelloWorld.lua b/start/src/main/java/com/alibaba/demo/HelloWorld.lua new file mode 100644 index 0000000..e777c38 --- /dev/null +++ b/start/src/main/java/com/alibaba/demo/HelloWorld.lua @@ -0,0 +1,3 @@ + + +print("Hello World!") \ No newline at end of file diff --git a/start/src/main/resources/application.yml b/start/src/main/resources/application.yml index e667d70..41bd4f3 100644 --- a/start/src/main/resources/application.yml +++ b/start/src/main/resources/application.yml @@ -29,3 +29,7 @@ knife4j: api-rule: package api-rule-resources: - com.alibaba.demo.web + + +mybatis-plus: + mapper-locations: classpath*:/mybatis/*.xml diff --git a/start/src/main/resources/lua/HelloWorld.lua b/start/src/main/resources/lua/HelloWorld.lua new file mode 100644 index 0000000..5dee746 --- /dev/null +++ b/start/src/main/resources/lua/HelloWorld.lua @@ -0,0 +1,9 @@ +--- +--- Generated by EmmyLua(https://github.com/EmmyLua) +--- Created by guocheng. +--- DateTime: 2024/3/6 00:05 +--- + +print("Hello World!") +local key=KEYS[1] +print(key) \ No newline at end of file diff --git a/start/src/main/resources/lua/stock_deduction.lua b/start/src/main/resources/lua/stock_deduction.lua new file mode 100644 index 0000000..cf64c12 --- /dev/null +++ b/start/src/main/resources/lua/stock_deduction.lua @@ -0,0 +1,16 @@ +--- lua脚本扣减库存:扣减成功返回当前库存,否则返回-1 +local isExists = redis.call('hexists',KEYS[1],KEYS[2]) +if isExists == 1 then + --- 拿库存 + local deduction=tonumber(redis.call('hget',KEYS[1],KEYS[2])) + if deduction ~= nil and deduction > 0 + then + --- 减库存 + return redis.call('hincrby',KEYS[1],KEYS[2],ARGV[1]) + else + return -1 + end +end +if isExists == 0 then + return -1 +end \ No newline at end of file diff --git a/start/src/main/resources/lua/stock_rollback.lua b/start/src/main/resources/lua/stock_rollback.lua new file mode 100644 index 0000000..c147b1c --- /dev/null +++ b/start/src/main/resources/lua/stock_rollback.lua @@ -0,0 +1,9 @@ +--- lua脚本扣减库存:扣减成功返回当前库存,否则返回-1 +local isExists = redis.call('hexists',KEYS[1],KEYS[2]) +if isExists == 1 then + --- + return redis.call('hincrby',KEYS[1],KEYS[2],ARGV[1]) +end +if isExists == 0 then + return -1 +end \ No newline at end of file -- Gitee From a543fa05c069bdde5960c8d210e18238eb9e4cc2 Mon Sep 17 00:00:00 2001 From: ranyu1998 <2772602769@qq.com> Date: Thu, 7 Mar 2024 20:01:58 +0800 Subject: [PATCH 4/4] =?UTF-8?q?feat(init):=20=E5=AE=8C=E6=88=90=E5=A5=96?= =?UTF-8?q?=E5=93=81=E6=8A=BD=E5=A5=96=E7=AE=97=E6=B3=95=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../demo/activity/ActivityServiceImpl.java | 4 +- .../CacheDeductionAwardInventoryDrawExe.java | 3 +- .../activity/command/DefaultDrawCmdExe.java | 3 +- .../command/DefaultAwardAlgorithmCmdExe.java | 90 +++++++++++++++++++ .../DefaultAwardAlgorithmCmdExeTest.java | 49 ++++++++++ pom.xml | 3 +- 6 files changed, 148 insertions(+), 4 deletions(-) create mode 100644 demo-web-app/src/main/java/com/alibaba/demo/award/command/DefaultAwardAlgorithmCmdExe.java create mode 100644 demo-web-app/src/test/java/com/alibaba/demo/award/command/DefaultAwardAlgorithmCmdExeTest.java diff --git a/demo-web-app/src/main/java/com/alibaba/demo/activity/ActivityServiceImpl.java b/demo-web-app/src/main/java/com/alibaba/demo/activity/ActivityServiceImpl.java index 050d763..c3dbc82 100644 --- a/demo-web-app/src/main/java/com/alibaba/demo/activity/ActivityServiceImpl.java +++ b/demo-web-app/src/main/java/com/alibaba/demo/activity/ActivityServiceImpl.java @@ -25,6 +25,7 @@ import org.springframework.stereotype.Service; import org.springframework.web.bind.annotation.RestController; import java.time.Duration; +import java.time.LocalDateTime; import java.util.Objects; import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -93,7 +94,8 @@ public class ActivityServiceImpl extends ActivityDecoratorService { AssertUtil.isFalse(writeLockTag,"缓存数据失败"); try { activityConfigVO = super.one(id); - boolean cacheTag = activityCacheGateWay.setOne(activityConfigVO, cacheKey, Duration.ofMinutes(10)); + LocalDateTime endTime = activityConfigVO.getActivityVO().getEndTime(); + boolean cacheTag = activityCacheGateWay.setOne(activityConfigVO, cacheKey, Duration.between(LocalDateTime.now(),endTime)); AssertUtil.isFalse(cacheTag,"缓存数据失败"); return activityConfigVO; } finally { diff --git a/demo-web-app/src/main/java/com/alibaba/demo/activity/command/CacheDeductionAwardInventoryDrawExe.java b/demo-web-app/src/main/java/com/alibaba/demo/activity/command/CacheDeductionAwardInventoryDrawExe.java index 525e626..da6678f 100644 --- a/demo-web-app/src/main/java/com/alibaba/demo/activity/command/CacheDeductionAwardInventoryDrawExe.java +++ b/demo-web-app/src/main/java/com/alibaba/demo/activity/command/CacheDeductionAwardInventoryDrawExe.java @@ -5,6 +5,7 @@ import com.alibaba.cola.demo.web.util.AssertUtil; import com.alibaba.demo.assembler.AwardAssembler; import com.alibaba.demo.assembler.RecordAssembler; import com.alibaba.demo.award.command.AwardAlgorithmCmdExe; +import com.alibaba.demo.award.command.WeightRandomAwardAlgorithmCmdExe; import com.alibaba.demo.context.ActivityDrawContext; import com.alibaba.demo.domain.gateway.AwardCacheGateWay; import com.alibaba.demo.domain.gateway.AwardGateway; @@ -35,7 +36,7 @@ public class CacheDeductionAwardInventoryDrawExe extends DefaultDrawCmdExe{ - public CacheDeductionAwardInventoryDrawExe(AwardAlgorithmCmdExe awardAlgorithmCmdExe, TransactionTemplate transactionTemplate, AwardGateway awardGateway, RecordGateway recordGateway, RecordAssembler recordAssembler, AwardAssembler assembler, AwardCacheGateWay awardCacheGateWay) { + public CacheDeductionAwardInventoryDrawExe(WeightRandomAwardAlgorithmCmdExe awardAlgorithmCmdExe, TransactionTemplate transactionTemplate, AwardGateway awardGateway, RecordGateway recordGateway, RecordAssembler recordAssembler, AwardAssembler assembler, AwardCacheGateWay awardCacheGateWay) { super(awardAlgorithmCmdExe, transactionTemplate, awardGateway, recordGateway, recordAssembler, assembler); this.awardCacheGateWay = awardCacheGateWay; } diff --git a/demo-web-app/src/main/java/com/alibaba/demo/activity/command/DefaultDrawCmdExe.java b/demo-web-app/src/main/java/com/alibaba/demo/activity/command/DefaultDrawCmdExe.java index c464140..e2b435d 100644 --- a/demo-web-app/src/main/java/com/alibaba/demo/activity/command/DefaultDrawCmdExe.java +++ b/demo-web-app/src/main/java/com/alibaba/demo/activity/command/DefaultDrawCmdExe.java @@ -7,6 +7,7 @@ import com.alibaba.cola.demo.web.util.SecurityUtil; import com.alibaba.demo.assembler.AwardAssembler; import com.alibaba.demo.assembler.RecordAssembler; import com.alibaba.demo.award.command.AwardAlgorithmCmdExe; +import com.alibaba.demo.award.command.WeightRandomAwardAlgorithmCmdExe; import com.alibaba.demo.context.ActivityDrawContext; import com.alibaba.demo.domain.activity.ActivityEntity; import com.alibaba.demo.domain.activity.ActivityStatusEnum; @@ -42,7 +43,7 @@ import java.util.Optional; public class DefaultDrawCmdExe extends BaseDrawCmdExe{ - protected final AwardAlgorithmCmdExe awardAlgorithmCmdExe; + protected final WeightRandomAwardAlgorithmCmdExe awardAlgorithmCmdExe; protected final TransactionTemplate transactionTemplate; protected final AwardGateway awardGateway; protected final RecordGateway recordGateway; diff --git a/demo-web-app/src/main/java/com/alibaba/demo/award/command/DefaultAwardAlgorithmCmdExe.java b/demo-web-app/src/main/java/com/alibaba/demo/award/command/DefaultAwardAlgorithmCmdExe.java new file mode 100644 index 0000000..d0d3198 --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/award/command/DefaultAwardAlgorithmCmdExe.java @@ -0,0 +1,90 @@ +package com.alibaba.demo.award.command; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.lang.WeightRandom; +import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.RandomUtil; +import com.alibaba.cola.demo.web.exception.LdException; +import com.alibaba.demo.dto.data.AwardVO; +import com.alibaba.fastjson.JSON; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.math.BigDecimal; +import java.util.*; + +/** + * @ClassName WeightRandomAwardAlgorithmCmdExe + * @Description 权重随机获取奖品 + * @Author Jincheng.Guo + * @Date 2024/3/3 17:28 + * @Version 1.0 + **/ +@Slf4j +@Component +@AllArgsConstructor +public class DefaultAwardAlgorithmCmdExe implements AwardAlgorithmCmdExe{ + + + @Data + @Builder + static class AwardAlgorithmDTO{ + // 奖品ID + private Long awardId; + // 中奖概率 + private Double probability; + // 中奖机率范围开始 + private Double probabilityStart; + // 中奖机率范围结束 + private Double probabilityEnd; + + } + @Override + public AwardVO getAward(List awardVOList) { + List awardAlgorithmDTOS=new ArrayList<>(); + Stack stack=new Stack<>(); + awardVOList.stream() + .forEach(item->{ + AwardAlgorithmDTO awardAlgorithmDTO = AwardAlgorithmDTO.builder() + .awardId(item.getId()) + .probability(item.getProbability()) + .build(); + Double probabilityStart; + Double probabilityEnd; + if(CollectionUtil.isEmpty(stack)){ + probabilityStart = Double.valueOf(0); + probabilityEnd = NumberUtil.add(Double.valueOf(0),item.getProbability()); + }else{ + AwardAlgorithmDTO top = stack.peek(); + probabilityStart=top.getProbabilityEnd(); + probabilityEnd=NumberUtil.add(top.getProbabilityEnd(),item.getProbability()); + } + awardAlgorithmDTO.setProbabilityStart(probabilityStart); + awardAlgorithmDTO.setProbabilityEnd(probabilityEnd); + stack.push(awardAlgorithmDTO); + }); + awardAlgorithmDTOS.addAll(stack); + log.info("奖项概率列表:{}", JSON.toJSON(awardAlgorithmDTOS)); + Double randomDouble = RandomUtil.randomDouble(0, 1); + Long awardId = awardAlgorithmDTOS.stream() + .filter(item -> { + boolean greaterOrEqual = NumberUtil.isGreaterOrEqual(BigDecimal.valueOf(randomDouble), BigDecimal.valueOf(item.getProbabilityStart())); + boolean less = NumberUtil.isLess(BigDecimal.valueOf(randomDouble), BigDecimal.valueOf(item.getProbabilityEnd())); + return greaterOrEqual && less; + }).findFirst().map(AwardAlgorithmDTO::getAwardId).orElseThrow(()->new LdException("未匹配到任何奖品")); + return awardVOList.stream() + .filter(item-> item.getId().equals(awardId)) + .findFirst().get(); + + + + } + + + + + +} diff --git a/demo-web-app/src/test/java/com/alibaba/demo/award/command/DefaultAwardAlgorithmCmdExeTest.java b/demo-web-app/src/test/java/com/alibaba/demo/award/command/DefaultAwardAlgorithmCmdExeTest.java new file mode 100644 index 0000000..4f9a220 --- /dev/null +++ b/demo-web-app/src/test/java/com/alibaba/demo/award/command/DefaultAwardAlgorithmCmdExeTest.java @@ -0,0 +1,49 @@ +package com.alibaba.demo.award.command; + +import cn.hutool.core.thread.ThreadUtil; +import com.alibaba.demo.dto.data.AwardVO; +import com.github.jsonzou.jmockdata.JMockData; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.slf4j.Logger; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import static org.mockito.Mockito.*; + +public class DefaultAwardAlgorithmCmdExeTest { + @Mock + Logger log; + @InjectMocks + DefaultAwardAlgorithmCmdExe defaultAwardAlgorithmCmdExe; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void testGetAward() throws Exception { + List awardVOList = Arrays.asList(0.15, 0.11, 0.2, 1.6).stream() + .map(item -> { + AwardVO mock = JMockData.mock(AwardVO.class); + mock.setProbability(item); + return mock; + }).collect(Collectors.toList()); + + + ThreadUtil.concurrencyTest(10,()->{ + AwardVO result = defaultAwardAlgorithmCmdExe.getAward(awardVOList); + System.out.println(result); + }); +// Assert.assertEquals(new AwardVO(), result); + } +} + +//Generated with love by TestMe :) Please report issues and submit feature requests at: http://weirddev.com/forum#!/testme \ No newline at end of file diff --git a/pom.xml b/pom.xml index 19be8c3..82e82d3 100644 --- a/pom.xml +++ b/pom.xml @@ -31,6 +31,7 @@ 1.18.10 2.0.2 2.28.2 + 4.2.0 @@ -75,7 +76,7 @@ com.github.jsonzou jmockdata - 4.1.2 + ${jmockdata.version} test -- Gitee