From 656673bffffb147835f38a6f83f28cca5ee3924d Mon Sep 17 00:00:00 2001
From: peng <peng.com>
Date: 星期五, 26 九月 2025 17:16:45 +0800
Subject: [PATCH] 店铺优惠卷

---
 framework/src/main/java/cn/lili/modules/lmk/service/StoreCouponSingleService.java               |   65 ++++++++
 manager-api/src/main/java/cn/lili/controller/lmk/StoreCouponController.java                     |   42 +++++
 framework/src/main/java/cn/lili/modules/lmk/domain/form/StoreCouponForm.java                    |    2 
 framework/src/main/java/cn/lili/modules/lmk/service/impl/StoreCouponClaimRecordServiceImpl.java |   46 ++++-
 framework/src/main/java/cn/lili/modules/lmk/service/impl/StoreCouponServiceImpl.java            |  109 +++++++++++++
 framework/src/main/java/cn/lili/modules/lmk/service/impl/StoreCouponSingleServiceImpl.java      |  119 ++++++++++++++
 framework/src/main/java/cn/lili/modules/lmk/service/StoreCouponService.java                     |    5 
 framework/src/main/resources/mapper/lmk/StoreCouponSingleMapper.xml                             |   53 ++++++
 framework/src/main/java/cn/lili/modules/lmk/mapper/StoreCouponSingleMapper.java                 |   34 ++++
 9 files changed, 461 insertions(+), 14 deletions(-)

diff --git a/framework/src/main/java/cn/lili/modules/lmk/domain/form/StoreCouponForm.java b/framework/src/main/java/cn/lili/modules/lmk/domain/form/StoreCouponForm.java
index 811df29..84ed379 100644
--- a/framework/src/main/java/cn/lili/modules/lmk/domain/form/StoreCouponForm.java
+++ b/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 = "浼樻儬鍗穒d涓嶈兘涓虹┖", groups = {Add.class, Update.class})
     @ApiModelProperty("浼樻儬鍗穒d")
diff --git a/framework/src/main/java/cn/lili/modules/lmk/mapper/StoreCouponSingleMapper.java b/framework/src/main/java/cn/lili/modules/lmk/mapper/StoreCouponSingleMapper.java
new file mode 100644
index 0000000..d0c14eb
--- /dev/null
+++ b/framework/src/main/java/cn/lili/modules/lmk/mapper/StoreCouponSingleMapper.java
@@ -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);
+
+}
diff --git a/framework/src/main/java/cn/lili/modules/lmk/service/StoreCouponService.java b/framework/src/main/java/cn/lili/modules/lmk/service/StoreCouponService.java
index 44c4759..4764c76 100644
--- a/framework/src/main/java/cn/lili/modules/lmk/service/StoreCouponService.java
+++ b/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);
 }
diff --git a/framework/src/main/java/cn/lili/modules/lmk/service/StoreCouponSingleService.java b/framework/src/main/java/cn/lili/modules/lmk/service/StoreCouponSingleService.java
new file mode 100644
index 0000000..d1ac5f7
--- /dev/null
+++ b/framework/src/main/java/cn/lili/modules/lmk/service/StoreCouponSingleService.java
@@ -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();
+}
diff --git a/framework/src/main/java/cn/lili/modules/lmk/service/impl/StoreCouponClaimRecordServiceImpl.java b/framework/src/main/java/cn/lili/modules/lmk/service/impl/StoreCouponClaimRecordServiceImpl.java
index dc31f6c..3ba8743 100644
--- a/framework/src/main/java/cn/lili/modules/lmk/service/impl/StoreCouponClaimRecordServiceImpl.java
+++ b/framework/src/main/java/cn/lili/modules/lmk/service/impl/StoreCouponClaimRecordServiceImpl.java
@@ -4,8 +4,11 @@
 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.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;
@@ -50,6 +53,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 +151,53 @@
         String userId = currentUser.getId();
         String nickName = currentUser.getNickName();
 
-        //閿佷綇搴楅摵鏌愪竴涓紭鎯犲嵎
+        //閿佷綇绀煎搧鐮乮d
         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);
+            //鏍¢獙鏄惁鍦ㄥ崟鍝佸嵎绫婚鍙栬繃
+
             //棰嗗彇瀵瑰簲鐨勪紭鎯犲嵎鍐欏叆璁板綍
-            memberCouponService.receiveCoupon(storeCoupon.getCouponId(),userId , nickName);
+            memberCouponService.receiveCoupon(storeCouponSingle.getCouponId(),userId , nickName);
             StoreCouponClaimRecord storeCouponClaimRecord = new StoreCouponClaimRecord();
-            storeCouponClaimRecord.setCouponId(storeCoupon.getCouponId());
-            storeCouponClaimRecord.setCouponName(storeCoupon.getCouponName());
-            storeCouponClaimRecord.setStoreId(storeCoupon.getStoreId());
-            storeCouponClaimRecord.setStoreName(storeCoupon.getStoreName());
+            storeCouponClaimRecord.setCouponId(storeCouponSingle.getCouponId());
+            storeCouponClaimRecord.setCouponName(storeCouponSingle.getCouponName());
+            storeCouponClaimRecord.setStoreId(storeCouponSingle.getStoreId());
+            storeCouponClaimRecord.setStoreName(storeCouponSingle.getStoreName());
             storeCouponClaimRecord.setUserId(userId);
             this.save(storeCouponClaimRecord);
             //棰嗗彇鎴愬姛杩斿洖浼樻儬鍗穒d鐢ㄤ簬璺宠浆璐墿浣跨敤
-            return Result.ok().data(storeCoupon.getCouponId());
+            return Result.ok().data(storeCouponSingle.getCouponId());
 
         } finally {
             TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
diff --git a/framework/src/main/java/cn/lili/modules/lmk/service/impl/StoreCouponServiceImpl.java b/framework/src/main/java/cn/lili/modules/lmk/service/impl/StoreCouponServiceImpl.java
index c640c03..cf3782d 100644
--- a/framework/src/main/java/cn/lili/modules/lmk/service/impl/StoreCouponServiceImpl.java
+++ b/framework/src/main/java/cn/lili/modules/lmk/service/impl/StoreCouponServiceImpl.java
@@ -1,20 +1,37 @@
 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.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.stream.Collectors;
 
@@ -29,6 +46,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;
 
     /**
      * 娣诲姞
@@ -119,7 +140,91 @@
 
     @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(storeCoupon.getCouponNum());
+        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();
+                    }
+                }
+            });
+        }
+    }
+
+    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;
     }
 }
diff --git a/framework/src/main/java/cn/lili/modules/lmk/service/impl/StoreCouponSingleServiceImpl.java b/framework/src/main/java/cn/lili/modules/lmk/service/impl/StoreCouponSingleServiceImpl.java
new file mode 100644
index 0000000..5708653
--- /dev/null
+++ b/framework/src/main/java/cn/lili/modules/lmk/service/impl/StoreCouponSingleServiceImpl.java
@@ -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());
+
+        // 涓虹┖鎶汭llegalArgumentException锛屽仛鍏ㄥ眬寮傚父澶勭悊
+        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);
+    }
+}
diff --git a/framework/src/main/resources/mapper/lmk/StoreCouponSingleMapper.xml b/framework/src/main/resources/mapper/lmk/StoreCouponSingleMapper.xml
new file mode 100644
index 0000000..e9085ef
--- /dev/null
+++ b/framework/src/main/resources/mapper/lmk/StoreCouponSingleMapper.xml
@@ -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>
diff --git a/manager-api/src/main/java/cn/lili/controller/lmk/StoreCouponController.java b/manager-api/src/main/java/cn/lili/controller/lmk/StoreCouponController.java
new file mode 100644
index 0000000..b324bb6
--- /dev/null
+++ b/manager-api/src/main/java/cn/lili/controller/lmk/StoreCouponController.java
@@ -0,0 +1,42 @@
+package cn.lili.controller.lmk;
+
+import cn.lili.base.Result;
+import cn.lili.modules.lmk.domain.form.StoreCouponForm;
+import cn.lili.modules.lmk.service.StoreCouponService;
+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);
+    }
+
+}

--
Gitblit v1.8.0