framework/src/main/java/cn/lili/modules/lmk/domain/form/StoreCouponForm.java
@@ -30,7 +30,7 @@ @NotNull(message = "店铺名称不能为空", groups = {Add.class, Update.class}) @ApiModelProperty("店铺名称") private Long storeName; private String storeName; @NotNull(message = "优惠卷id不能为空", groups = {Add.class, Update.class}) @ApiModelProperty("优惠卷id") framework/src/main/java/cn/lili/modules/lmk/domain/query/StoreCouponQuery.java
@@ -2,6 +2,9 @@ import cn.lili.base.AbsQuery; import java.util.List; import cn.lili.modules.lmk.enums.general.GenerateCouponStausEnum; import cn.lili.modules.lmk.enums.general.StoreCouponStausEnum; import org.springframework.lang.NonNull; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; @@ -18,5 +21,16 @@ @Data @ApiModel(value = "StoreCoupon查询参数", description = "店铺优惠卷对应关系查询参数") public class StoreCouponQuery extends AbsQuery { /** 店铺id */ private Long storeId; /** 店铺优惠卷状态 * @see StoreCouponStausEnum * */ private String status; /** 生成优惠卷状态 * @see GenerateCouponStausEnum * */ private String generateStatus; } framework/src/main/java/cn/lili/modules/lmk/mapper/StoreCouponSingleMapper.java
New file @@ -0,0 +1,34 @@ package cn.lili.modules.lmk.mapper; import cn.lili.modules.lmk.domain.entity.StoreCouponSingle; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import cn.lili.modules.lmk.domain.vo.StoreCouponSingleVO; import cn.lili.modules.lmk.domain.form.StoreCouponSingleForm; import cn.lili.modules.lmk.domain.query.StoreCouponSingleQuery; import java.util.List; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; /** * 店铺优惠卷单品 Mapper 接口 * * @author peng * @since 2025-09-26 */ @Mapper public interface StoreCouponSingleMapper extends BaseMapper<StoreCouponSingle> { /** * id查找店铺优惠卷单品 * @param id * @return */ StoreCouponSingleVO getById(String id); /** * 分页 */ IPage getPage(IPage page, @Param("query") StoreCouponSingleQuery query); } framework/src/main/java/cn/lili/modules/lmk/service/StoreCouponService.java
@@ -6,6 +6,7 @@ import cn.lili.modules.lmk.domain.form.StoreCouponForm; import cn.lili.modules.lmk.domain.query.StoreCouponQuery; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import java.util.List; @@ -66,4 +67,8 @@ Result all(); Result getCoupon(String id); Result addStoreCoupon(StoreCouponForm storeCoupon); Result generateStoreCoupon( String id); } framework/src/main/java/cn/lili/modules/lmk/service/StoreCouponSingleService.java
New file @@ -0,0 +1,65 @@ package cn.lili.modules.lmk.service; import cn.lili.modules.lmk.domain.entity.StoreCouponSingle; import com.baomidou.mybatisplus.extension.service.IService; import cn.lili.base.Result; import cn.lili.modules.lmk.domain.form.StoreCouponSingleForm; import cn.lili.modules.lmk.domain.query.StoreCouponSingleQuery; import java.util.List; /** * 店铺优惠卷单品 服务类 * * @author peng * @since 2025-09-26 */ public interface StoreCouponSingleService extends IService<StoreCouponSingle> { /** * 添加 * @param form * @return */ Result add(StoreCouponSingleForm form); /** * 修改 * @param form * @return */ Result update(StoreCouponSingleForm form); /** * 批量删除 * @param ids * @return */ Result remove(List<String> ids); /** * id删除 * @param id * @return */ Result removeById(String id); /** * 分页查询 * @param query * @return */ Result page(StoreCouponSingleQuery query); /** * 根据id查找 * @param id * @return */ Result detail(String id); /** * 列表 * @return */ Result all(); } framework/src/main/java/cn/lili/modules/lmk/service/impl/StoreCouponClaimRecordServiceImpl.java
@@ -4,13 +4,18 @@ import cn.lili.common.security.AuthUser; import cn.lili.common.security.context.UserContext; import cn.lili.modules.lmk.domain.entity.StoreCoupon; import cn.lili.modules.lmk.domain.entity.StoreCouponSingle; import cn.lili.modules.lmk.enums.general.PrizeStatusEnum; import cn.lili.modules.lmk.enums.general.StoreCouponStausEnum; import cn.lili.modules.lmk.service.StoreCouponService; import cn.lili.modules.lmk.service.StoreCouponSingleService; import cn.lili.modules.order.order.entity.enums.ClaimStatusEnum; import cn.lili.modules.promotion.entity.dos.MemberCoupon; import cn.lili.modules.promotion.service.MemberCouponService; import cn.lili.rocketmq.RocketmqSendCallbackBuilder; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import cn.lili.modules.lmk.domain.entity.StoreCouponClaimRecord; import cn.lili.modules.lmk.mapper.StoreCouponClaimRecordMapper; @@ -50,6 +55,7 @@ private static final String STORE_COUPON_CLAIM = "store_coupon_claim:"; private final MemberCouponService memberCouponService; private final StoreCouponService storeCouponService; private final StoreCouponSingleService storeCouponSingleService; /** * 添加 * @param form @@ -147,33 +153,63 @@ String userId = currentUser.getId(); String nickName = currentUser.getNickName(); //锁住店铺某一个优惠卷 //锁住礼品码id RLock redissonLock = redissonClient.getLock(STORE_COUPON_CLAIM + id); try { redissonLock.lock(); StoreCoupon storeCoupon = storeCouponService.getById(id); if (storeCoupon == null) { throw new ServiceException("当前店铺不存在优惠卷"); LambdaQueryWrapper<StoreCouponSingle> forUpdate = Wrappers.<StoreCouponSingle>lambdaQuery() .eq(StoreCouponSingle::getId, id).last("FOR UPDATE"); StoreCouponSingle storeCouponSingle = storeCouponSingleService.getOne(forUpdate); if (storeCouponSingle == null) { throw new ServiceException("当前礼品码不存在"); } if (!ClaimStatusEnum.NOT_CLAIM.name().equals(storeCouponSingle.getClaimStatus())) { throw new ServiceException("当前礼品码状态异常"); } LambdaQueryWrapper<StoreCouponSingle> claimListQuery = Wrappers.<StoreCouponSingle>lambdaQuery() .eq(StoreCouponSingle::getClaimUserId, userId) .eq(StoreCouponSingle::getStoreCoupRef, storeCouponSingle.getStoreCoupRef()) .eq(StoreCouponSingle::getClaimStatus, ClaimStatusEnum.CLAIM.name()); List<StoreCouponSingle> claimList = storeCouponSingleService.list(claimListQuery); if (!claimList.isEmpty()) { throw new ServiceException("已经领取过该类型的礼品码无法领取"); } //处理幂等问题限制一个用户只能该店铺领取一种优惠卷 LambdaQueryWrapper<StoreCouponClaimRecord> memCoupon = Wrappers.<StoreCouponClaimRecord>lambdaQuery() .eq(StoreCouponClaimRecord::getUserId, userId) .eq(StoreCouponClaimRecord::getCouponId, storeCoupon.getCouponId()); .eq(StoreCouponClaimRecord::getCouponId, storeCouponSingle.getCouponId()); List<StoreCouponClaimRecord> list = this.list(memCoupon); if (!list.isEmpty()){ throw new ServiceException("当前用户已经领取过了无法再次领取"); } //更新单品被领取的记录 storeCouponSingle.setClaimStatus(ClaimStatusEnum.CLAIM.name()); storeCouponSingle.setClaimUserId(userId); storeCouponSingle.setClaimUserName(nickName); storeCouponSingleService.updateById(storeCouponSingle); //校验是否在单品卷类领取过 LambdaQueryWrapper<StoreCoupon> storeCoupQuery = Wrappers.<StoreCoupon>lambdaQuery() .eq(StoreCoupon::getId, storeCouponSingle.getStoreCoupRef()).last("FOR UPDATE"); StoreCoupon storeCoupon = storeCouponService.getOne(storeCoupQuery); if (storeCoupon == null) { throw new ServiceException("当前店铺优惠卷不存在"); } if (!StoreCouponStausEnum.ENABLE.name().equals(storeCoupon.getStatus())) { throw new ServiceException("当前店铺优惠卷状态异常"); } //领取对应的优惠卷写入记录 memberCouponService.receiveCoupon(storeCoupon.getCouponId(),userId , nickName); StoreCouponClaimRecord storeCouponClaimRecord = new StoreCouponClaimRecord(); storeCouponClaimRecord.setCouponId(storeCoupon.getCouponId()); storeCouponClaimRecord.setCouponName(storeCoupon.getCouponName()); storeCouponClaimRecord.setStoreId(storeCoupon.getStoreId()); storeCouponClaimRecord.setStoreName(storeCoupon.getStoreName()); storeCouponClaimRecord.setUserId(userId); memberCouponService.receiveCoupon(storeCouponSingle.getCouponId(),userId , nickName); StoreCouponClaimRecord storeCouponClaimRecord = getStoreCouponClaimRecord(storeCouponSingle, userId); this.save(storeCouponClaimRecord); LambdaUpdateWrapper<StoreCoupon> updateStoreCoupon = Wrappers.<StoreCoupon>lambdaUpdate().eq(StoreCoupon::getId, storeCoupon.getId()) .set(StoreCoupon::getCouponClaimNum, storeCoupon.getCouponClaimNum() + 1) .gt(StoreCoupon::getCouponClaimNum, storeCoupon.getCouponClaimNum() + 1); boolean update = storeCouponService.update(updateStoreCoupon); if (!update) { throw new ServiceException("更新失败"); } //领取成功返回优惠卷id用于跳转购物使用 return Result.ok().data(storeCoupon.getCouponId()); return Result.ok().data(storeCouponSingle.getCouponId()); } finally { TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { @@ -183,8 +219,28 @@ redissonLock.unlock(); } } @Override public void afterCompletion(int status) { // 确保即使在事务回滚的情况下也能释放锁 if (redissonLock.isHeldByCurrentThread()) { redissonLock.unlock(); } } }); } } private static StoreCouponClaimRecord getStoreCouponClaimRecord(StoreCouponSingle storeCouponSingle, String userId) { StoreCouponClaimRecord storeCouponClaimRecord = new StoreCouponClaimRecord(); storeCouponClaimRecord.setCouponId(storeCouponSingle.getCouponId()); storeCouponClaimRecord.setCouponName(storeCouponSingle.getCouponName()); storeCouponClaimRecord.setStoreId(storeCouponSingle.getStoreId()); storeCouponClaimRecord.setStoreName(storeCouponSingle.getStoreName()); storeCouponClaimRecord.setUserId(userId); storeCouponClaimRecord.setStoreCouponId(storeCouponSingle.getStoreCoupRef()); return storeCouponClaimRecord; } } framework/src/main/java/cn/lili/modules/lmk/service/impl/StoreCouponServiceImpl.java
@@ -1,21 +1,40 @@ package cn.lili.modules.lmk.service.impl; import cn.lili.common.exception.ServiceException; import cn.lili.modules.lmk.domain.entity.CouponVirtual; import cn.lili.modules.lmk.domain.entity.StoreCouponSingle; import cn.lili.modules.lmk.enums.general.GenerateCouponStausEnum; import cn.lili.modules.lmk.enums.general.StoreCouponStausEnum; import cn.lili.modules.lmk.service.StoreCouponSingleService; import cn.lili.modules.order.order.entity.enums.ClaimStatusEnum; import cn.lili.modules.promotion.entity.dos.Coupon; import cn.lili.modules.promotion.service.CouponService; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import cn.lili.modules.lmk.domain.entity.StoreCoupon; import cn.lili.modules.lmk.mapper.StoreCouponMapper; import cn.lili.modules.lmk.service.StoreCouponService; import cn.lili.base.Result; import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import cn.lili.modules.lmk.domain.form.StoreCouponForm; import cn.lili.modules.lmk.domain.vo.StoreCouponVO; import cn.lili.modules.lmk.domain.query.StoreCouponQuery; import org.redisson.api.RLock; import org.redisson.api.RedissonClient; import org.springframework.stereotype.Service; import lombok.RequiredArgsConstructor; import cn.lili.utils.PageUtil; import org.springframework.beans.BeanUtils; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.support.TransactionSynchronization; import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.util.Assert; import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; /** @@ -29,6 +48,10 @@ public class StoreCouponServiceImpl extends ServiceImpl<StoreCouponMapper, StoreCoupon> implements StoreCouponService { private final StoreCouponMapper storeCouponMapper; private final RedissonClient redissonClient; private static final String STORE_COUPON_GENERATE = "store_coupon_generate:"; private final CouponService couponService; private final StoreCouponSingleService storeCouponSingleService; /** * 添加 @@ -87,8 +110,12 @@ */ @Override public Result page(StoreCouponQuery query) { IPage<StoreCouponVO> page = PageUtil.getPage(query, StoreCouponVO.class); baseMapper.getPage(page, query); IPage<StoreCoupon> page = PageUtil.getPage(query, StoreCoupon.class); LambdaQueryWrapper<StoreCoupon> wrapper = Wrappers.lambdaQuery(); wrapper.eq(Objects.nonNull(query.getStoreId()), StoreCoupon::getStoreId, query.getStoreId()); wrapper.eq(StringUtils.isNotBlank(query.getStatus()), StoreCoupon::getStatus, query.getStatus()); wrapper.eq(StringUtils.isNotBlank(query.getGenerateStatus()), StoreCoupon::getGenerateStatus, query.getGenerateStatus()); this.page(page, wrapper); return Result.ok().data(page.getRecords()).total(page.getTotal()); } @@ -119,7 +146,98 @@ @Override public Result getCoupon(String id) { StoreCoupon storeCoupon = this.getById(id); return Result.ok().data(storeCoupon); StoreCouponSingle storeCouponSingle = storeCouponSingleService.getById(id); StoreCoupon storeCoupon = this.getById(storeCouponSingle.getStoreCoupRef()); if (storeCoupon == null) { throw new ServiceException("店铺礼品卡包不存在"); } if (!StoreCouponStausEnum.ENABLE.name().equals(storeCoupon.getStatus())) { throw new ServiceException("店铺礼品卡包没有启用无法领取"); } if (ClaimStatusEnum.CLAIM.name().equals(storeCouponSingle.getClaimStatus())) { throw new ServiceException("当前礼品卡包已被领取"); } return Result.ok().data(storeCouponSingle); } @Override @Transactional(rollbackFor = Exception.class) public Result addStoreCoupon(StoreCouponForm storeCoupon) { StoreCoupon entity = StoreCouponForm.getEntityByForm(storeCoupon, null); entity.setStatus(StoreCouponStausEnum.ENABLE.name()); entity.setCouponClaimNum(0); entity.setGenerateStatus(GenerateCouponStausEnum.NOT_GENERATE.name()); Coupon coupon = couponService.getById(entity.getCouponId()); Integer publishNum = coupon.getPublishNum(); //表示不限制领取数量 if (!Integer.valueOf(0).equals(publishNum)) { if (publishNum < storeCoupon.getCouponNum()) { throw new ServiceException("优惠卷发行数量小于生成二维码数量"); } } this.save(entity); return Result.ok(); } @Override @Transactional(rollbackFor = Exception.class) public Result generateStoreCoupon(String id) { RLock redissonLock = redissonClient.getLock(STORE_COUPON_GENERATE + id); try { redissonLock.lock(); LambdaQueryWrapper<StoreCoupon> forUpdate = Wrappers.<StoreCoupon>lambdaQuery().eq(StoreCoupon::getId, id).last("FOR UPDATE"); StoreCoupon storeCoupon = this.getOne(forUpdate); if (storeCoupon == null) { throw new ServiceException("当前店铺优惠卷不存在无法生成"); } if (!GenerateCouponStausEnum.NOT_GENERATE.name().equals( storeCoupon.getGenerateStatus())) { throw new ServiceException("当前店铺优惠卷状态异常无法生成"); } //生成优惠卷 Integer couponNum = storeCoupon.getCouponNum(); if (couponNum == null) { throw new ServiceException("发行数量为空不能生成"); } List<StoreCouponSingle> storeCouponSingles = new ArrayList<>(); for (int i = 1; i <= couponNum; i++) { StoreCouponSingle storeCouponSingle = getStoreCouponSingle(storeCoupon, i); storeCouponSingles.add(storeCouponSingle); } if (!storeCouponSingles.isEmpty()) { storeCouponSingleService.saveBatch(storeCouponSingles); } //更新状态生成状态 storeCoupon.setGenerateStatus(GenerateCouponStausEnum.GENERATE.name()); this.updateById(storeCoupon); return Result.ok(); }finally { TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { @Override public void afterCommit() { if (redissonLock.isHeldByCurrentThread()) { redissonLock.unlock(); } } @Override public void afterCompletion(int status) { // 确保即使在事务回滚的情况下也能释放锁 if (redissonLock.isHeldByCurrentThread()) { redissonLock.unlock(); } } }); } } private static StoreCouponSingle getStoreCouponSingle(StoreCoupon storeCoupon, int i) { StoreCouponSingle storeCouponSingle = new StoreCouponSingle(); storeCouponSingle.setStoreCoupRef(storeCoupon.getId()); storeCouponSingle.setStoreId(storeCoupon.getStoreId()); storeCouponSingle.setStoreName(storeCoupon.getStoreName()); storeCouponSingle.setCouponName(storeCoupon.getCouponName()); storeCouponSingle.setCouponId(storeCoupon.getCouponId()); storeCouponSingle.setClaimStatus(ClaimStatusEnum.NOT_CLAIM.name()); storeCouponSingle.setCouponNo(String.format("%08d", i)); return storeCouponSingle; } } framework/src/main/java/cn/lili/modules/lmk/service/impl/StoreCouponSingleServiceImpl.java
New file @@ -0,0 +1,119 @@ package cn.lili.modules.lmk.service.impl; import com.baomidou.mybatisplus.core.metadata.IPage; import cn.lili.modules.lmk.domain.entity.StoreCouponSingle; import cn.lili.modules.lmk.mapper.StoreCouponSingleMapper; import cn.lili.modules.lmk.service.StoreCouponSingleService; import cn.lili.base.Result; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import cn.lili.modules.lmk.domain.form.StoreCouponSingleForm; import cn.lili.modules.lmk.domain.vo.StoreCouponSingleVO; import cn.lili.modules.lmk.domain.query.StoreCouponSingleQuery; import org.springframework.stereotype.Service; import lombok.RequiredArgsConstructor; import cn.lili.utils.PageUtil; import org.springframework.beans.BeanUtils; import org.springframework.util.Assert; import java.util.List; import java.util.stream.Collectors; /** * 店铺优惠卷单品 服务实现类 * * @author peng * @since 2025-09-26 */ @Service @RequiredArgsConstructor public class StoreCouponSingleServiceImpl extends ServiceImpl<StoreCouponSingleMapper, StoreCouponSingle> implements StoreCouponSingleService { private final StoreCouponSingleMapper storeCouponSingleMapper; /** * 添加 * @param form * @return */ @Override public Result add(StoreCouponSingleForm form) { StoreCouponSingle entity = StoreCouponSingleForm.getEntityByForm(form, null); baseMapper.insert(entity); return Result.ok("添加成功"); } /** * 修改 * @param form * @return */ @Override public Result update(StoreCouponSingleForm form) { StoreCouponSingle entity = baseMapper.selectById(form.getId()); // 为空抛IllegalArgumentException,做全局异常处理 Assert.notNull(entity, "记录不存在"); BeanUtils.copyProperties(form, entity); baseMapper.updateById(entity); return Result.ok("修改成功"); } /** * 批量删除 * @param ids * @return */ @Override public Result remove(List<String> ids) { baseMapper.deleteBatchIds(ids); return Result.ok("删除成功"); } /** * id删除 * @param id * @return */ @Override public Result removeById(String id) { baseMapper.deleteById(id); return Result.ok("删除成功"); } /** * 分页查询 * @param query * @return */ @Override public Result page(StoreCouponSingleQuery query) { IPage<StoreCouponSingleVO> page = PageUtil.getPage(query, StoreCouponSingleVO.class); baseMapper.getPage(page, query); return Result.ok().data(page.getRecords()).total(page.getTotal()); } /** * 根据id查找 * @param id * @return */ @Override public Result detail(String id) { StoreCouponSingleVO vo = baseMapper.getById(id); Assert.notNull(vo, "记录不存在"); return Result.ok().data(vo); } /** * 列表 * @return */ @Override public Result all() { List<StoreCouponSingle> entities = baseMapper.selectList(null); List<StoreCouponSingleVO> vos = entities.stream() .map(entity -> StoreCouponSingleVO.getVoByEntity(entity, null)) .collect(Collectors.toList()); return Result.ok().data(vos); } } framework/src/main/resources/mapper/lmk/StoreCouponSingleMapper.xml
New file @@ -0,0 +1,53 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="cn.lili.modules.lmk.mapper.StoreCouponSingleMapper"> <!-- 通用查询映射结果 --> <resultMap id="BaseResultMap" type="cn.lili.modules.lmk.domain.vo.StoreCouponSingleVO"> <id column="id" property="id"/> <result column="store_coup_ref" property="storeCoupRef" /> <result column="store_id" property="storeId" /> <result column="coupon_id" property="couponId" /> <result column="coupon_name" property="couponName" /> <result column="coupon_no" property="couponNo" /> <result column="claim_status" property="claimStatus" /> </resultMap> <select id="getById" resultMap="BaseResultMap"> SELECT LSCS.store_coup_ref, LSCS.store_id, LSCS.coupon_id, LSCS.coupon_name, LSCS.coupon_no, LSCS.claim_status, LSCS.id FROM lmk_store_coupon_single LSCS WHERE LSCS.id = #{id} AND LSCS.delete_flag = 0 </select> <select id="getPage" resultMap="BaseResultMap"> SELECT LSCS.store_coup_ref, LSCS.store_id, LSCS.coupon_id, LSCS.coupon_name, LSCS.coupon_no, LSCS.claim_status, LSCS.id FROM lmk_store_coupon_single LSCS WHERE LSCS.delete_flag = 0 </select> </mapper> manager-api/src/main/java/cn/lili/controller/lmk/StoreCouponController.java
New file @@ -0,0 +1,53 @@ package cn.lili.controller.lmk; import cn.lili.base.Result; import cn.lili.modules.lmk.domain.form.StoreCouponForm; import cn.lili.modules.lmk.domain.query.StoreCouponQuery; import cn.lili.modules.lmk.service.StoreCouponService; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.AllArgsConstructor; import org.springframework.web.bind.annotation.*; /** * 商家端生成店铺优惠卷信息 * * @author : peng * @date : 2025-09-16 16:36 **/ @RestController @AllArgsConstructor @RequestMapping("/manager/lmk/storeCoupon") public class StoreCouponController { private final StoreCouponService storeCouponService; /** * 创建店铺与优惠卷关联关系 * @param storeCoupon * @return */ @PostMapping public Result addStoreCoupon(@RequestBody StoreCouponForm storeCoupon){ return storeCouponService.addStoreCoupon(storeCoupon); } /** * 根据店铺关联关系生成单品 * @param id * @return */ @PostMapping("/generateStoreCoupon/{id}") public Result generateStoreCoupon(@PathVariable String id){ return storeCouponService.generateStoreCoupon(id); } /** * 获取店铺列表 * @param query * @return */ @GetMapping public Result getPage(StoreCouponQuery query){ return storeCouponService.page(query); } }