diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..be723753d09db712fa975c34a8faaffba1763405 --- /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 0000000000000000000000000000000000000000..59697458e6c9bd560659bac7c16ba5a9400e2025 --- /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 0000000000000000000000000000000000000000..50ab17a72fce22e4ff8e941b128237446ae188c7 --- /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 0000000000000000000000000000000000000000..5ede9137cd04a119a3c5a1ca739905c6baf58db1 --- /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/ActivityController.java b/demo-web-adapter/src/main/java/com/alibaba/demo/web/ActivityController.java new file mode 100644 index 0000000000000000000000000000000000000000..222dfb79778ecdb795de6a629fb6980a8dd3766b --- /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/CustomerController.java b/demo-web-adapter/src/main/java/com/alibaba/demo/web/CustomerController.java new file mode 100644 index 0000000000000000000000000000000000000000..bb012fdcab7e309c838ebb9596cea946e5e26dfc --- /dev/null +++ b/demo-web-adapter/src/main/java/com/alibaba/demo/web/CustomerController.java @@ -0,0 +1,36 @@ +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-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 0000000000000000000000000000000000000000..5370e1ec4a25010bf3d6e21ebbcccda772bd61b5 --- /dev/null +++ b/demo-web-adapter/src/main/java/com/alibaba/demo/web/admin/AdminActivityConfigController.java @@ -0,0 +1,66 @@ +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.*; + +/** + * 活动配置接口 + * @ClassName AdminActivityConfigController + * @Description 活动配置接口 + * @Author guocheng + * @Date 2024/2/28 16:58 + * @Version 1.0 + **/ +@Slf4j +@AllArgsConstructor +@RestController +@RequestMapping("/admin/v1/activityConfig") +public class AdminActivityConfigController { + + @Qualifier("activityConfigService") + @Autowired + private IActivityConfigService activityConfigService; + + /** + * 添加活动配置 + **/ + @PostMapping("/add") + public ActivityConfigVO add(@Validated(value = {AddGroup.class}) @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); +// } + + + /** + * 刷新活动奖项库存 + **/ + @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 0000000000000000000000000000000000000000..cc729a72aa3d73ad6e33d25eaa8e4ce7da5900e2 --- /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 new file mode 100644 index 0000000000000000000000000000000000000000..cfac27bdc4c32668b3ce2c8fa68376838423d13e --- /dev/null +++ b/demo-web-adapter/src/main/java/com/alibaba/demo/web/admin/AdminPrizeController.java @@ -0,0 +1,61 @@ +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; +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(value = {AddGroup.class}) @RequestBody PrizeAddCmd cmd) { + return prizeService.add(cmd); + } + + /** + * 修改奖品 + **/ + @PostMapping("/update") + public PrizeVO update(@Validated(value = {UpdateGroup.class}) @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 new file mode 100644 index 0000000000000000000000000000000000000000..2104a7917dc975b34a9b6f3adaddf01704b6a55c --- /dev/null +++ b/demo-web-app/pom.xml @@ -0,0 +1,52 @@ + + + 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 + + + + + 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 0000000000000000000000000000000000000000..4afe529be305448c2962ad42b26c7e60674db3fb --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/activity/ActivityConfigServiceImpl.java @@ -0,0 +1,171 @@ +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; +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; + +/** + * @ClassName ActivityConfigServiceImpl + * @Description TODO + * @Author Jincheng.Guo + * @Date 2024/2/28 17:35 + * @Version 1.0 + **/ +@Slf4j +@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) + @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); + // 发布活动创建事件 + + // 发送活动创建事件 + applicationEventMulticaster.multicastEvent(new ActivityCreatedEvent("", activityConfigVO)); + + return activityConfigVO; + } + + @Override + public ActivityConfigVO update(ActivityConfigUpdateCmd cmd) { + return null; + } + + @Override + public ActivityConfigVO one(Long id) { + // 查询活动信息 + 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; + } + + +// 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), "奖项不为空!"); + checkTotalProbabilityEqualOne(awardAddCmdList); + List result = new ArrayList<>(); + for (AwardAddCmd awardAddCmd : awardAddCmdList) { + awardAddCmd.setActivityId(activityVO.getId()); + result.add(awardAddCmdExe.execute(awardAddCmd)); + } + + 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 0000000000000000000000000000000000000000..c3dbc8275d768dff621a57bb4154cac5337fae04 --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/activity/ActivityServiceImpl.java @@ -0,0 +1,115 @@ +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.time.LocalDateTime; +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); + LocalDateTime endTime = activityConfigVO.getActivityVO().getEndTime(); + boolean cacheTag = activityCacheGateWay.setOne(activityConfigVO, cacheKey, Duration.between(LocalDateTime.now(),endTime)); + 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 new file mode 100644 index 0000000000000000000000000000000000000000..60f1af259725d92464e18c5126759cc6817c19dd --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/activity/command/ActivityAddCmdExe.java @@ -0,0 +1,30 @@ +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; + private final ActivityAssembler activityAssembler; + + 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/activity/command/BaseDrawCmdExe.java b/demo-web-app/src/main/java/com/alibaba/demo/activity/command/BaseDrawCmdExe.java new file mode 100644 index 0000000000000000000000000000000000000000..0e4d93bd627e75d40a1375a92ca40829051a2ec1 --- /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 0000000000000000000000000000000000000000..da6678ffb21237812efda48d73202c02ab78a82b --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/activity/command/CacheDeductionAwardInventoryDrawExe.java @@ -0,0 +1,74 @@ +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.award.command.WeightRandomAwardAlgorithmCmdExe; +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(WeightRandomAwardAlgorithmCmdExe 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 0000000000000000000000000000000000000000..e2b435d77a7d062bd24301b912807e6d683730f3 --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/activity/command/DefaultDrawCmdExe.java @@ -0,0 +1,159 @@ +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.award.command.WeightRandomAwardAlgorithmCmdExe; +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 WeightRandomAwardAlgorithmCmdExe 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 0000000000000000000000000000000000000000..c720200484881d6f5852f69dd407637d800c1c46 --- /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 new file mode 100644 index 0000000000000000000000000000000000000000..3376eb751b8afcec02a30f0136eb3174878ed261 --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/assembler/ActivityAssembler.java @@ -0,0 +1,42 @@ +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 org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Named; + +import java.time.LocalDateTime; + +/** + * @author J3(about:https://j3code.cn) + * @package cn.j3code.luckyapp.assembler + * @createTime 2022/12/3 - 0:03 + * @description + */ +@Mapper(componentModel = "spring") +public interface ActivityAssembler { + @Mapping(target = "activityTime.startTime",source = "startTime") + @Mapping(target = "activityTime.endTime",source = "endTime") + ActivityEntity toAddEntity(ActivityAddCmd cmd); + + + @Mapping(target = "startTime",source = "activityTime.startTime") + @Mapping(target = "endTime",source = "activityTime.endTime") + @Mapping(target = "status",source = "activityTime",qualifiedByName = {"status"}) + ActivityVO toActivityVO(ActivityEntity entity); + + ActivityEntity toUpdateEntity(ActivityAddCmd cmd); + + ActivityAddCmd toActivityAddCmd(ActivityVO activityVO); + + + + @Named("status") + default Integer toStatus(ActivityTime activityTime){ + return activityTime.getStatus().getValue(); + } +} 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 0000000000000000000000000000000000000000..5af1ba59f8522935d1629e440a8885692b351b1a --- /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 0000000000000000000000000000000000000000..e325016c06f47405bebfeb3d0fa81e355ee8a02e --- /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/assembler/RecordAssembler.java b/demo-web-app/src/main/java/com/alibaba/demo/assembler/RecordAssembler.java new file mode 100644 index 0000000000000000000000000000000000000000..7118e1256e6ffa7daa7cfbe692a11bafa8c9ef24 --- /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 0000000000000000000000000000000000000000..a1fe796bbb8c356001f1ca1a8be28d129735ec45 --- /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 new file mode 100644 index 0000000000000000000000000000000000000000..565e890bd6ddc52fad0b66094bed26192bbf559d --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/award/command/AwardAddCmdExe.java @@ -0,0 +1,80 @@ +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) + * @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不为空!"); + checkTotalProbabilityEqualOne(cmd); + // 保存奖项 + 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); + } + + + /** + * @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 0000000000000000000000000000000000000000..fe0abf709262994c17c8ac2d8118802cf0ffa71f --- /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/AwardUpdateCmdExe.java b/demo-web-app/src/main/java/com/alibaba/demo/award/command/AwardUpdateCmdExe.java new file mode 100644 index 0000000000000000000000000000000000000000..a751ab364047a5fccf1b81ed5cdf94b3d6c2ed40 --- /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/award/command/DefaultAwardAlgorithmCmdExe.java b/demo-web-app/src/main/java/com/alibaba/demo/award/command/DefaultAwardAlgorithmCmdExe.java new file mode 100644 index 0000000000000000000000000000000000000000..d0d31981f8da38386026d0d3d77ee1dd4a5e8203 --- /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/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 0000000000000000000000000000000000000000..6b34c534265ea31f39b3df1b0681667ed1dad4c9 --- /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 0000000000000000000000000000000000000000..a275b093f241d83ea2fe0e6f4dd8f09f4637ed98 --- /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 0000000000000000000000000000000000000000..eb2d02f8a4292685ff00ec01942a2a87cd8cc2bc --- /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/customer/CustomerServiceImpl.java b/demo-web-app/src/main/java/com/alibaba/demo/customer/CustomerServiceImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..b64cab0b1d53d8d6bc4372d5e8be6ed1967c9773 --- /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 0000000000000000000000000000000000000000..14e52ccebd3813dc0d9dbb9126e706364364cc1f --- /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 0000000000000000000000000000000000000000..4fc00ffd8a9d3d8fcdce82aec7b4664a2c7c7b5a --- /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/listener/AwardInventory2CacheListener.java b/demo-web-app/src/main/java/com/alibaba/demo/listener/AwardInventory2CacheListener.java new file mode 100644 index 0000000000000000000000000000000000000000..c8d2db0578118488f8177cc756fe9349919df3eb --- /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 0000000000000000000000000000000000000000..cf017287551085e3645284998145bab34c626864 --- /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 0000000000000000000000000000000000000000..36f043400fada9277e0ea29e0193d07f34e82608 --- /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/order/OrderServiceImpl.java b/demo-web-app/src/main/java/com/alibaba/demo/order/OrderServiceImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..c25fa3a170e3452794b144e7f7acb6b2e34b41e4 --- /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/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 0000000000000000000000000000000000000000..6f7b4818f3fe5deb5d45033e61277d76c458c221 --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/prize/PrizeServiceImpl.java @@ -0,0 +1,63 @@ +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; +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; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +/** + * @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) { + 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 new file mode 100644 index 0000000000000000000000000000000000000000..f76a8d810f311a3c1ae4eb547c3a39f53a508fcb --- /dev/null +++ b/demo-web-app/src/main/java/com/alibaba/demo/prize/command/PrizeAddCmdExe.java @@ -0,0 +1,31 @@ +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 0000000000000000000000000000000000000000..4a2ccc68c5dba5fdeedc614e9d7f74e4575e96b3 --- /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 0000000000000000000000000000000000000000..1a0ea4d0f3bfbf9641a12e2c6011956ee454bc8d --- /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-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 0000000000000000000000000000000000000000..3de23a2e0ef2b025ebb21aebb555d653548cfc7e --- /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 0000000000000000000000000000000000000000..633c0d7dfeb329f77341557bf809e6fe7a89dd82 --- /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-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 0000000000000000000000000000000000000000..612f3a3c233a5387debdaeab75f1abd564de245e --- /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 0000000000000000000000000000000000000000..a2fec49c1f8615138620ba239fa0b4df1ed20ecd --- /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-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 0000000000000000000000000000000000000000..4f9a220d575bdb297f3c8466716038bf36cbd7e8 --- /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/demo-web-base/pom.xml b/demo-web-base/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..802aff85f751ff446c3c93306d03e4a9510a7bf7 --- /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 0000000000000000000000000000000000000000..e7eb406eadb693d56b0f00cf78c26ca67c6ba255 --- /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 0000000000000000000000000000000000000000..fec761d50e5016f844b08b663eca3f0c690a80aa --- /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 0000000000000000000000000000000000000000..ae6636163d54be9b797f36cca92f633ce99b9e97 --- /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 0000000000000000000000000000000000000000..e4e839de3da0c5725bb8146a3e9c88128ffcd2ac --- /dev/null +++ b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/enums/RecordStatusEnum.java @@ -0,0 +1,43 @@ +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 + * @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; + } + + 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/exception/LdCodeException.java b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/exception/LdCodeException.java new file mode 100644 index 0000000000000000000000000000000000000000..fbfe70bd747e0cbba25c303ed42e7777f570c035 --- /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 0000000000000000000000000000000000000000..306d3b9bc92c5447438e4916debf9922c07ca56b --- /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 0000000000000000000000000000000000000000..63ec9b8d030d50ad37101bc1c71bb15d0ba943ab --- /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/ResponseResultHandler.java b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/handler/ResponseResultHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..19bebc606e854d2efcba66d25fd3bb66c8a09fe1 --- /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/handler/SysExceptionHandler.java b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/handler/SysExceptionHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..c9218ee6377b76453425e52995762d07c6505a1e --- /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 0000000000000000000000000000000000000000..aa715129381bab142e85cb92628afe542dbc4b6b --- /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 0000000000000000000000000000000000000000..b7d012fc2ef79eb42d461edc2616283c3894eb6d --- /dev/null +++ b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/util/SecurityUtil.java @@ -0,0 +1,50 @@ +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() { + return 1L; +// 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 0000000000000000000000000000000000000000..eced7fb030b7c6d27ff4a70e50817025e6d042ed --- /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 0000000000000000000000000000000000000000..54a2ccfd46ff2dcaee4fbcf96f1b360535e968d1 --- /dev/null +++ b/demo-web-base/src/main/java/com/alibaba/cola/demo/web/vo/PageResultInfo.java @@ -0,0 +1,70 @@ +package com.alibaba.cola.demo.web.vo; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.*; + +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 +@Data +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() { + super(true, DEFAULT_CODE, DEFAULT_MESSAGE); + } + + 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 0000000000000000000000000000000000000000..4f6be63284b54e74dffe23f677f54b402ff47865 --- /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 0000000000000000000000000000000000000000..3da9c9ddf3d41314b5b72bc9b2b5da9e9a7217e8 --- /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 new file mode 100644 index 0000000000000000000000000000000000000000..f55350e951ec0ae455dbbb4e9e187376238d4068 --- /dev/null +++ b/demo-web-client/pom.xml @@ -0,0 +1,29 @@ + + + 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 + + + com.alibaba.cola.demo.web + demo-web-base + + + 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 0000000000000000000000000000000000000000..217c2779919064191a0d1a4566163b36e1a6cd86 --- /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/CustomerServiceI.java b/demo-web-client/src/main/java/com/alibaba/demo/api/CustomerServiceI.java new file mode 100644 index 0000000000000000000000000000000000000000..72c18bede661191c45ed5d7bef4f508c6689f47b --- /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/api/IActivityConfigService.java b/demo-web-client/src/main/java/com/alibaba/demo/api/IActivityConfigService.java new file mode 100644 index 0000000000000000000000000000000000000000..1ba4f04bc4642aa615c927804e36ae1315b8641f --- /dev/null +++ b/demo-web-client/src/main/java/com/alibaba/demo/api/IActivityConfigService.java @@ -0,0 +1,27 @@ +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) + * @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); + + 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 0000000000000000000000000000000000000000..4f16b3b68c22d57233798b4e66cfaabdca04b093 --- /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 0000000000000000000000000000000000000000..632c5a549f89ac01f16e551270ceaf1cebcaf849 --- /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/api/IPrizeService.java b/demo-web-client/src/main/java/com/alibaba/demo/api/IPrizeService.java new file mode 100644 index 0000000000000000000000000000000000000000..cf9e24820d5e775f85b288dddfc0fffa32c0f7cd --- /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 0000000000000000000000000000000000000000..d53579c0af9a72b11cf008603d47dead7dfa6e15 --- /dev/null +++ b/demo-web-client/src/main/java/com/alibaba/demo/dto/ActivityAddCmd.java @@ -0,0 +1,55 @@ +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; + +/** + * @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}) + @Null(message = "id需为空",groups = {AddGroup.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 0000000000000000000000000000000000000000..2deb8a07d3fcfe2e5eab055f05730cc318500ce5 --- /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 0000000000000000000000000000000000000000..556e541b48bc0f0b853336e24f1b86400dfc7847 --- /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/ActivityDrawCmd.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/ActivityDrawCmd.java new file mode 100644 index 0000000000000000000000000000000000000000..fc40ed8c091374131f70a0c850ed3bb64d30be7c --- /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 new file mode 100644 index 0000000000000000000000000000000000000000..6a1582a2c93a54efaa23e833860cae2ce4beba50 --- /dev/null +++ b/demo-web-client/src/main/java/com/alibaba/demo/dto/AwardAddCmd.java @@ -0,0 +1,45 @@ +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 + * @Description 奖项添加命令 + * @Author guocheng + * @Date 2024/2/28 16:34 + * @Version 1.0 + **/ +@Data +public class AwardAddCmd extends Command { + + @NotNull(message = "id不为空",groups = {UpdateGroup.class}) + @Null(message = "id需为空",groups = {AddGroup.class}) + private Long id; + /** + * 奖品ID + */ + private Long prizeId; + /** + * 活动ID + */ + @NotNull(message = "活动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/CustomerAddCmd.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/CustomerAddCmd.java new file mode 100644 index 0000000000000000000000000000000000000000..b04842951f55022da4d1f6d8f2bde932e2b2c1f5 --- /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 0000000000000000000000000000000000000000..0e0b2cbb73341e773019b448ab0955c8bd7bb805 --- /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/PrizeAddCmd.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/PrizeAddCmd.java new file mode 100644 index 0000000000000000000000000000000000000000..7e08a2bb00cc7b53f6ea0c173885d9adcdafc09f --- /dev/null +++ b/demo-web-client/src/main/java/com/alibaba/demo/dto/PrizeAddCmd.java @@ -0,0 +1,50 @@ +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; + +/** + * @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}) + @Null(message = "id需为空",groups = {AddGroup.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/RecordAddCmd.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/RecordAddCmd.java new file mode 100644 index 0000000000000000000000000000000000000000..20115040c3328337a6de235c7d868b3c88095ac4 --- /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/ActivityConfigVO.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/data/ActivityConfigVO.java new file mode 100644 index 0000000000000000000000000000000000000000..b231fd06a9977d81201c1b405c8eca818aeb4af2 --- /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 0000000000000000000000000000000000000000..cf7a5f5e2ebb57d62e2067fa982668b4d0c70803 --- /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 0000000000000000000000000000000000000000..df2e5bf27ad5309a5c9a88501ad1e390d2646dfc --- /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/CustomerDTO.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/data/CustomerDTO.java new file mode 100644 index 0000000000000000000000000000000000000000..53c41756e432bcb34373cc1ff340eef4e3e516f8 --- /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/DrawResultVO.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/data/DrawResultVO.java new file mode 100644 index 0000000000000000000000000000000000000000..8def1382e2047653f45a6bf5de77b2da35da3ecd --- /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/ErrorCode.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/data/ErrorCode.java new file mode 100644 index 0000000000000000000000000000000000000000..caa46e0aa03e38289c0e6da2f031a364234fbf5a --- /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/data/PrizeVO.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/data/PrizeVO.java new file mode 100644 index 0000000000000000000000000000000000000000..b08305942c1eb8d0b0deae4d6ad4a30c0a84dfc1 --- /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/RecordVO.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/data/RecordVO.java new file mode 100644 index 0000000000000000000000000000000000000000..ed0715e6370809ecc9956e14e421ab01cfb009ab --- /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/data/RuleVO.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/data/RuleVO.java new file mode 100644 index 0000000000000000000000000000000000000000..0724106c7b1e915178531a9ab6c1bfb8e5781714 --- /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/event/CustomerCreatedEvent.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/event/CustomerCreatedEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..acd359a948a37b4e895c4fd46c5765d3933e65d8 --- /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 0000000000000000000000000000000000000000..569ec5b60cd487078e1dc274179e073026be93a0 --- /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-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 0000000000000000000000000000000000000000..92cd5507f6a116c9ad7647ec8bd79188b445908d --- /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 0000000000000000000000000000000000000000..1196ab8d7b7d2017b229cbf59c27a0a68411b53f --- /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/PrizeListByParamQuery.java b/demo-web-client/src/main/java/com/alibaba/demo/dto/query/PrizeListByParamQuery.java new file mode 100644 index 0000000000000000000000000000000000000000..9328552e71de1c802b21946044e2b3a039cb84e3 --- /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-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 0000000000000000000000000000000000000000..f7d2377cc63670e29303f5376684d53b40fa1f9f --- /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/pom.xml b/demo-web-domain/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..a1740c988b233605350995a4dee611a924e435c6 --- /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/acceptprize/AcceptPrizeEntity.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/acceptprize/AcceptPrizeEntity.java new file mode 100644 index 0000000000000000000000000000000000000000..07ac25214dbc6c9b8209e238e48536bccfdc82d0 --- /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 0000000000000000000000000000000000000000..ed527d72ccd4d9d6e715088dd22759d252930ced --- /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 0000000000000000000000000000000000000000..d5e1fd2b75530df8c87836657fe8331250a05c42 --- /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 0000000000000000000000000000000000000000..3e6cb48eefec6e1fb90310df578c73de944b406c --- /dev/null +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/activity/ActivityTime.java @@ -0,0 +1,63 @@ +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; + +/** + * @ClassName ActivityTimeEntity + * @Description TODO + * @Author guocheng + * @Date 2024/2/28 15:27 + * @Version 1.0 + **/ +@Data +@NoArgsConstructor +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 0000000000000000000000000000000000000000..debecd57c14b8515ecc1e222b1fd78223515ab92 --- /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 0000000000000000000000000000000000000000..d4f94b8ee9cf28705675699957d12bcfd3bb9572 --- /dev/null +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/award/AwardEntity.java @@ -0,0 +1,78 @@ +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; + +/** + * @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; + + + /** + * 判断该奖项是否是一个奖品,也即该奖项是否中奖:谢谢惠顾的奖项ID为0 + * + * @return + */ + public Boolean isPrize() { + return !PrizeEntity.THINKS_PRIZE_ID.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 0000000000000000000000000000000000000000..4ed374112233e39f7c78107c11ec6f91d000342d --- /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/customer/CompanyType.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/customer/CompanyType.java new file mode 100644 index 0000000000000000000000000000000000000000..239fe2ca536077abc04ef53efe4c074f742a638c --- /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 0000000000000000000000000000000000000000..a32190a3f2628f339f69d44c3cf78d923caefa67 --- /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 0000000000000000000000000000000000000000..b52c145a2d9a66e85b2104745e33362aee1b290a --- /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 0000000000000000000000000000000000000000..0739dbd815936086c8eedf7120a61832609634ea --- /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 0000000000000000000000000000000000000000..825e5f4d8872e14be7bae8397de1094168e8027d --- /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 0000000000000000000000000000000000000000..8c6469791330567a14c09a3ee80f6aca6c51ca6f --- /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 0000000000000000000000000000000000000000..c9cfc79bf8ea0fe77f36a0cc08f252be36e20b41 --- /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 0000000000000000000000000000000000000000..5abf2c57f9958630d4d0a0c3962ff8cd95b056ff --- /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/gateway/ActivityCacheGateWay.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/gateway/ActivityCacheGateWay.java new file mode 100644 index 0000000000000000000000000000000000000000..89b56ee6a0f102c0a6a071c8f1ec4939fa86d536 --- /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 new file mode 100644 index 0000000000000000000000000000000000000000..4225efb20d661e888810a2798e3c5e2a6fde2712 --- /dev/null +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/gateway/ActivityGateway.java @@ -0,0 +1,21 @@ +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) + * @package cn.j3code.luckydomain.gateway + * @createTime 2022/12/3 - 0:01 + * @description + */ +public interface ActivityGateway { + + ActivityEntity save(ActivityEntity entity); + + + 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 0000000000000000000000000000000000000000..36612f468db8447c5cedcd41d48f92074882cf9b --- /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 new file mode 100644 index 0000000000000000000000000000000000000000..05480b5a8cccd1ee43d0eea538a00111a7e6d852 --- /dev/null +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/gateway/AwardGateway.java @@ -0,0 +1,21 @@ +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) + * @package cn.j3code.luckydomain.gateway + * @createTime 2022/12/2 - 22:55 + * @description + */ +public interface AwardGateway { + + AwardEntity save(AwardEntity entity); + + PageResultInfo 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 0000000000000000000000000000000000000000..b31ad122ea6bd64e4819294493f9637b126078ec --- /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/gateway/RecordGateway.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/gateway/RecordGateway.java new file mode 100644 index 0000000000000000000000000000000000000000..6798c25c53640ae0023e49395515c83f3e03afd4 --- /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/order/Order.java b/demo-web-domain/src/main/java/com/alibaba/demo/domain/order/Order.java new file mode 100644 index 0000000000000000000000000000000000000000..f3d7832925310567804128aaafd2e02b7e7d17b8 --- /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 0000000000000000000000000000000000000000..08180c98179fdba0d5d084e65970cdb55152b3da --- /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/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 0000000000000000000000000000000000000000..47b3f13844b1ceaea49a16d8668a237fb096b26e --- /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 0000000000000000000000000000000000000000..fc976170a49635ccdc246195cf4a3158d1aa6014 --- /dev/null +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/prize/PrizeEntity.java @@ -0,0 +1,70 @@ +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 { + /** + * 谢谢惠顾奖品ID + **/ + public final static String THINKS_PRIZE_ID="0"; + + /** + * + */ + 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 0000000000000000000000000000000000000000..d337722658920311729867c567426d4e31716f21 --- /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 0000000000000000000000000000000000000000..75cfc3637150910c9931c6ee5081e877a5afcdd7 --- /dev/null +++ b/demo-web-domain/src/main/java/com/alibaba/demo/domain/record/RecordStatus.java @@ -0,0 +1,62 @@ +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) + * @package cn.j3code.luckydomain.record + * @createTime 2022/12/9 - 23:06 + * @description + */ +@Getter +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-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 0000000000000000000000000000000000000000..862acfe9aa0945ab416b860b71c6888f121b9d7a --- /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 0000000000000000000000000000000000000000..538d2166c22ed9129c64c405076f4f3e3304424d --- /dev/null +++ b/demo-web-infrastructure/pom.xml @@ -0,0 +1,65 @@ + + + 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 + + + com.baomidou + mybatis-plus-boot-starter + + + org.mapstruct + mapstruct + + + org.springframework.boot + spring-boot-starter-data-redis + + + cn.hutool + hutool-all + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + 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 0000000000000000000000000000000000000000..0020c1f2170c58056319470c38cbd43a6a0703f8 --- /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/config/MyMetaObjectHandler.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/config/MyMetaObjectHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..558d819d770aa2fef487d47efd0463ba95a4f9a5 --- /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 0000000000000000000000000000000000000000..494b4b5ca9197050e41b81bec4e949d7e141f73a --- /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 0000000000000000000000000000000000000000..cd80a3526b748c0867723e54f4b9c1e02e4afa2e --- /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/ActivityConvertor.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/converter/ActivityConvertor.java new file mode 100644 index 0000000000000000000000000000000000000000..61c11ec7e788753faf8126e7175402b6d302fb61 --- /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/AwardConvertor.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/converter/AwardConvertor.java new file mode 100644 index 0000000000000000000000000000000000000000..e8bca62c19d86d35076ee98e9381d19d176f183a --- /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/PrizeConvertor.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/converter/PrizeConvertor.java new file mode 100644 index 0000000000000000000000000000000000000000..49288e6183b25171cbd866543df76c4e3f258807 --- /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/converter/RecordConvertor.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/converter/RecordConvertor.java new file mode 100644 index 0000000000000000000000000000000000000000..66c5203abc10f518e5788680108317c9f77e1c38 --- /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 new file mode 100644 index 0000000000000000000000000000000000000000..761ae26495a8289ddea0797ccd1c7716c901e627 --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/database/dataobject/ActivityDO.java @@ -0,0 +1,45 @@ +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; +import java.time.LocalDateTime; + +/** + * + * @TableName bld_activity + */ +@TableName(value ="activity") +@Data +public class ActivityDO extends BaseDO { + /** + * + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 活动名称 + */ + private String activityName; + + /** + * 开始时间 + */ + private LocalDateTime startTime; + + /** + * 结束时间 + */ + private LocalDateTime endTime; + + /** + * 描述 + */ + @TableField("`describe`") + private String describe; + + +} \ 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 0000000000000000000000000000000000000000..87ac12b208ceaee94020546fa0e1d45c9af64a88 --- /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 0000000000000000000000000000000000000000..8da70c25fcfe8af314fce66300465b1de91e562a --- /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/CustomerDO.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/database/dataobject/CustomerDO.java new file mode 100644 index 0000000000000000000000000000000000000000..da9d446d854b9e2cae5615a66c4ec020c4998a17 --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/database/dataobject/CustomerDO.java @@ -0,0 +1,12 @@ +package com.alibaba.demo.database.dataobject; + +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/database/dataobject/PrizeDO.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/database/dataobject/PrizeDO.java new file mode 100644 index 0000000000000000000000000000000000000000..38f09f08009ba926e6803694cc6daa8a05177722 --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/database/dataobject/PrizeDO.java @@ -0,0 +1,45 @@ +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; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * + * @TableName bld_prize + */ +@TableName(value ="prize") +@Data +public class PrizeDO extends BaseDO { + /** + * + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 奖品名称 + */ + private String prizeName; + + /** + * 库存 + */ + private Integer inventory; + + /** + * 金额 + */ + private BigDecimal money; + + /** + * 类型(1:商品,2:金钱) + */ + private Integer type; + + +} \ 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 0000000000000000000000000000000000000000..5f63fa8deeb3516d597949093e53ba859ce2f63f --- /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 new file mode 100644 index 0000000000000000000000000000000000000000..83b791232536a7af21f327500270ea56f1fa82de --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/ActivityGatewayImpl.java @@ -0,0 +1,73 @@ +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; + +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 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())) { + 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/ActivityRedisCacheGatewayImpl.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/ActivityRedisCacheGatewayImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..2c73f466881329ee19a3a0f94d2cb720437035cf --- /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 new file mode 100644 index 0000000000000000000000000000000000000000..db12729488f79df25da5ea720daf56bb6d503461 --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/AwardGateWayImpl.java @@ -0,0 +1,83 @@ +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 + * @Author Jincheng.Guo + * @Date 2024/2/28 22:43 + * @Version 1.0 + **/ +@Slf4j +@Component +@AllArgsConstructor +public class AwardGateWayImpl implements AwardGateway { + private final AwardMapper awardMapper; + private final AwardConvertor awardConvertor; + + + @Override + public AwardEntity save(AwardEntity entity) { + 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 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 0000000000000000000000000000000000000000..4fceaa1cb9d4e4e7f3ca213d066ae8d8afa675e7 --- /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/CreditGatewayImpl.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/CreditGatewayImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..8d40a44dc65231000ed2643a4be01b9317ce2105 --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/CreditGatewayImpl.java @@ -0,0 +1,10 @@ +package com.alibaba.demo.gateway.impl; + +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/gateway/impl/CustomerGatewayImpl.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/CustomerGatewayImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..ea7cdf1095e51e38036090ef5116f714393d02c0 --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/CustomerGatewayImpl.java @@ -0,0 +1,21 @@ +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; + +@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/gateway/impl/OrderGatewayImpl.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/OrderGatewayImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..73de19d7d7aadaa5ffdd9bc6d210c6f5308e0ffc --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/OrderGatewayImpl.java @@ -0,0 +1,5 @@ +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 0000000000000000000000000000000000000000..739b05a3f837bf67b9b8503b2d951ff0760c8ca0 --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/gateway/impl/PrizeGateWayImpl.java @@ -0,0 +1,78 @@ +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 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 0000000000000000000000000000000000000000..742bb8f84116bbc4ab2f6426080f6c98214dd16a --- /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/ActivityMapper.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/mapper/ActivityMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..9607ac0848975770ef6486a8dd870217e1f186e6 --- /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/mapper/AwardMapper.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/mapper/AwardMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..13fe9349ef99392e2fa7ed1cb7fe9d0dcf18fa2d --- /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/CustomerMapper.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/mapper/CustomerMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..ed40826bcfba911719f97bdb7eaf117cef1d293c --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/mapper/CustomerMapper.java @@ -0,0 +1,10 @@ +package com.alibaba.demo.mapper; + +import com.alibaba.demo.database.dataobject.CustomerDO; +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/mapper/PrizeMapper.java b/demo-web-infrastructure/src/main/java/com/alibaba/demo/mapper/PrizeMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..cc75818576c29c5cafa47c73cdccca1cd329ccb9 --- /dev/null +++ b/demo-web-infrastructure/src/main/java/com/alibaba/demo/mapper/PrizeMapper.java @@ -0,0 +1,25 @@ +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 +*/ +@Mapper +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 0000000000000000000000000000000000000000..9d4eb9a952e4bc3315c6a45d9415bca787b9f8f4 --- /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/logback-spring.xml b/demo-web-infrastructure/src/main/resources/logback-spring.xml new file mode 100644 index 0000000000000000000000000000000000000000..38a1553c1f477b11af57a4ffb8845cf4a84a281e --- /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-config.xml b/demo-web-infrastructure/src/main/resources/mybatis-config.xml new file mode 100644 index 0000000000000000000000000000000000000000..f7c8d886f7a025c437356f9b647a62417b955d60 --- /dev/null +++ b/demo-web-infrastructure/src/main/resources/mybatis-config.xml @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file 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 0000000000000000000000000000000000000000..61a0fbf51c25e2708c14e93fc8d00767a4d9e149 --- /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 0000000000000000000000000000000000000000..7afd892e4b207800a7e710f3269eb891e44dfacd --- /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/main/resources/mybatis/customer-mapper.xml b/demo-web-infrastructure/src/main/resources/mybatis/customer-mapper.xml new file mode 100644 index 0000000000000000000000000000000000000000..46d7b8d9eb693951863624d2873ee1824a5c3d29 --- /dev/null +++ b/demo-web-infrastructure/src/main/resources/mybatis/customer-mapper.xml @@ -0,0 +1,14 @@ + + + + + + + + + + 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 0000000000000000000000000000000000000000..1f3a8c3676b34fd17ca50245e7b838501686d243 --- /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 0000000000000000000000000000000000000000..10924f5302f91e20ef52c9d1a59217b9e6ad8f0e --- /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 0000000000000000000000000000000000000000..f431e5554db133f99867665ceb1e4974fca43725 --- /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 0000000000000000000000000000000000000000..3af52b87a78b88877c57924751981e66f01ac385 --- /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/CustomerMapperTest.java b/demo-web-infrastructure/src/test/java/com/alibaba/demo/repository/CustomerMapperTest.java new file mode 100644 index 0000000000000000000000000000000000000000..8f03c29f965a88ff5884f0c1e262c725a7a4bc53 --- /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/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 0000000000000000000000000000000000000000..5baa1150c9f3b287230fa31150754712e80a31fd --- /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 0000000000000000000000000000000000000000..434ced53ef5710780011b691c446a442d9171503 --- /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 0000000000000000000000000000000000000000..4c40b87f20d628015571d4308afc07904a719fee --- /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 0000000000000000000000000000000000000000..a130b24e43a0c68cecebd7e3611a8f16285a9b55 --- /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 0000000000000000000000000000000000000000..b6eda347e828d94d63fbeaac8fe74b523d09a65a --- /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 0000000000000000000000000000000000000000..321b204a60fcc827bcf4a04c35778cdd7ca6b32d --- /dev/null +++ b/demo-web-infrastructure/src/test/resources/mybatisTestConfiguration/RecordMapperTestConfiguration.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..82e82d3594dbb8018e650e5e4ac6afb1e1d724e3 --- /dev/null +++ b/pom.xml @@ -0,0 +1,252 @@ + + + 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 + + + 11 + ${maven.compiler.source} + UTF-8 + UTF-8 + true + + 4.3.2 + + 2.7.2 + 2.2.2 + + 1.4.2.Final + 5.2.0 + 3.4.3.4 + 1.18.10 + 2.0.2 + 2.28.2 + 4.2.0 + + + + demo-web-client + demo-web-adapter + demo-web-app + demo-web-domain + demo-web-infrastructure + start + demo-web-base + + + + + org.projectlombok + lombok + provided + + + junit + 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 + ${jmockdata.version} + test + + + org.assertj + assertj-core + test + 3.5.2 + + + + + + + + + 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.demo.web + demo-web-base + ${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} + + + + + com.baomidou + mybatis-plus-boot-starter + ${mybatis-plus.version} + + + + + cn.hutool + hutool-all + ${hutool.version} + + + + + org.mapstruct + mapstruct + ${org.mapstruct.version} + + + + + + javax.el + javax.el-api + 3.0.0 + + + + + + com.alibaba + fastjson + 1.2.83 + + + + + + org.projectlombok + lombok + ${lombok.version} + + + + + + + + maven-compiler-plugin + + + + + + maven-resources-plugin + 3.3.0 + + + maven-compiler-plugin + 3.10.1 + + 11 + 11 + + + org.projectlombok + lombok + ${lombok.version} + + + org.mapstruct + mapstruct-processor + ${org.mapstruct.version} + + + + + + + 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 0000000000000000000000000000000000000000..40714571a818ca32da12ff65ef6ed94ee3969285 --- /dev/null +++ b/start/pom.xml @@ -0,0 +1,44 @@ + + + 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 + + + com.github.xiaoymin + knife4j-openapi2-spring-boot-starter + 4.4.0 + + + 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 0000000000000000000000000000000000000000..d74c6f50fa57cf9e7f753bf6b02e404747f533fb --- /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/java/com/alibaba/demo/HelloWorld.lua b/start/src/main/java/com/alibaba/demo/HelloWorld.lua new file mode 100644 index 0000000000000000000000000000000000000000..e777c388dd53d82673ddc27d8119d68c4b47e25a --- /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 new file mode 100644 index 0000000000000000000000000000000000000000..41bd4f3d4567cb6db2754d592e1c3e6e9d14fd3a --- /dev/null +++ b/start/src/main/resources/application.yml @@ -0,0 +1,35 @@ +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 + + +mybatis-plus: + mapper-locations: classpath*:/mybatis/*.xml diff --git a/start/src/main/resources/logback-spring.xml b/start/src/main/resources/logback-spring.xml new file mode 100644 index 0000000000000000000000000000000000000000..b4d90e2f642fa3d1343c4baa11d1f7a734d40a7e --- /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/main/resources/lua/HelloWorld.lua b/start/src/main/resources/lua/HelloWorld.lua new file mode 100644 index 0000000000000000000000000000000000000000..5dee746fcf3e5d0eb9f3e13342682b225565137c --- /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 0000000000000000000000000000000000000000..cf64c123b468119f079ace607a830f36c4f2f109 --- /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 0000000000000000000000000000000000000000..c147b1c227caddb2dcca02b28e208f2a36e818be --- /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 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 0000000000000000000000000000000000000000..0bf4fcb5bfc633fa3fe0dddec2c293ad076b70c5 --- /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 0000000000000000000000000000000000000000..90164728050a80a7755d76714949529680e900dc --- /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 0000000000000000000000000000000000000000..b4d90e2f642fa3d1343c4baa11d1f7a734d40a7e --- /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 0000000000000000000000000000000000000000..e81b2a396c6f9e9241bdea6cdefdc3018d4ad5f0 --- /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