zjy 5 hónapja
szülő
commit
fd7264ad35

+ 12 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/LifeGroupBuyThaliVo.java

@@ -259,4 +259,16 @@ public class LifeGroupBuyThaliVo {
     @ApiModelProperty(value = "已售数量")
     private Integer saleNum;
 
+    @ApiModelProperty(value = "审核状态")
+    private String reviewType;
+
+    @ApiModelProperty(value = "成本价")
+    private BigDecimal costPrice;
+
+    @ApiModelProperty(value = "利润")
+    private BigDecimal profit;
+
+    @ApiModelProperty(value = "状态(0草稿/1待审核/2未开始/3审核拒绝/4已售罄/5进行中/6已下架/7已结束)")
+    private String statusName;
+
 }

+ 38 - 0
alien-entity/src/main/java/shop/alien/entity/storePlantform/LifeGroupBuyMainPlantform.java

@@ -0,0 +1,38 @@
+package shop.alien.entity.storePlantform;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import shop.alien.entity.store.LifeGroupBuyMain;
+
+import java.util.List;
+
+/**
+ * 团购主表
+ * @TableName life_group_buy_main
+ */
+@JsonInclude
+@Data
+public class LifeGroupBuyMainPlantform extends LifeGroupBuyMain {
+
+    /**
+     * 有效期类型
+     */
+    @ApiModelProperty(value = "有效期时间")
+    private List<String> expirationDate;
+
+    /**
+     * 有效期时间数组
+     */
+    @ApiModelProperty(value = "有效期时间数组")
+    private List<String> expirationDateList;
+
+    /**
+     * 不可用日期类型
+     */
+    @ApiModelProperty(value = "不可用日期二维数组")
+    private List<List<String>> disableDateList;
+
+
+}

+ 21 - 0
alien-entity/src/main/java/shop/alien/entity/storePlantform/vo/LifeGroupBuyPlantformDto.java

@@ -0,0 +1,21 @@
+package shop.alien.entity.storePlantform.vo;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.Data;
+import shop.alien.entity.store.LifeGroupBuyMain;
+import shop.alien.entity.store.LifeGroupBuyThali;
+import shop.alien.entity.storePlantform.LifeGroupBuyMainPlantform;
+
+import java.util.List;
+
+/**
+ * 团购
+ */
+@Data
+@JsonInclude
+public class LifeGroupBuyPlantformDto {
+
+    private LifeGroupBuyMainPlantform lifeGroupBuyMain;
+
+    private List<LifeGroupBuyThali> lifeGroupBuyThalis;
+}

+ 33 - 0
alien-entity/src/main/java/shop/alien/mapper/storePlantform/LifeGroupBuyMainPlantformMapper.java

@@ -0,0 +1,33 @@
+package shop.alien.mapper.storePlantform;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Constants;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
+import shop.alien.entity.store.LifeGroupBuyMain;
+import shop.alien.entity.store.vo.LifeGroupBuyThaliVo;
+
+import java.math.BigDecimal;
+
+/**
+* @author youch
+* @description 针对表【life_group_buy_main(团购主表)】的数据库操作Mapper
+* @createDate 2025-07-28 14:31:30
+* @Entity shop.alien.entity.store.LifeGroupBuyMain
+*/
+@Mapper
+public interface LifeGroupBuyMainPlantformMapper extends BaseMapper<LifeGroupBuyMain> {
+
+    @Select("select SUM(cost_price) from life_group_buy_thali lgbt inner join store_menu sm on lgbt.detail_id = sm.id where parent_id = #{id} and lgbt.delete_flag = 0 and sm.delete_flag = 0 ")
+    BigDecimal selectSumCostPrice(@Param("id") Integer id);
+
+
+}
+
+
+
+

+ 8 - 1
alien-gateway/src/main/java/shop/alien/gateway/service/LifeUserService.java

@@ -9,6 +9,7 @@ import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
 import shop.alien.entity.second.LifeUserLog;
 import shop.alien.entity.second.SecondRiskControlRecord;
@@ -157,7 +158,8 @@ public class LifeUserService extends ServiceImpl<LifeUserGatewayMapper, LifeUser
             if (count > 0) {
                 String startDate = LocalDateTime.now().minusHours(24L).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                 String endDate = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
-                List<LifeUserLog> lsit = lifeUserLogMapper.getLifeUserLogByDate(startDate, endDate, macIp);
+                // 使用一个新的事务来查询,确保能看到刚才插入的数据
+                List<LifeUserLog> lsit = getLifeUserLogByDateInNewTransaction(startDate, endDate, macIp);
 
                 if (lsit.size() > riskControlProperties.getAccountAbnormal().getRegCount24h() && !isViolation(startDate, endDate, macIp, user.getId())) {
                     String detailInfo = lsit.stream()
@@ -174,6 +176,11 @@ public class LifeUserService extends ServiceImpl<LifeUserGatewayMapper, LifeUser
 
     }
 
+    @Transactional(propagation = Propagation.REQUIRES_NEW)
+    public List<LifeUserLog> getLifeUserLogByDateInNewTransaction(String startDate, String endDate, String macIp) {
+        return lifeUserLogMapper.getLifeUserLogByDate(startDate, endDate, macIp);
+    }
+
     public boolean isViolation(String startDate, String endDate, String macIp, Integer userId) {
         List<SecondRiskControlRecord> list = secondRiskControlRecordMapper.selectByBusinessId(startDate, endDate, macIp);
         for (SecondRiskControlRecord record : list) {

+ 174 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/controller/LifeGroupBuyController.java

@@ -0,0 +1,174 @@
+package shop.alien.storeplatform.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+import shop.alien.entity.result.R;
+import shop.alien.entity.store.LifeGroupBuyThali;
+import shop.alien.entity.store.dto.LifeGroupBuyDto;
+import shop.alien.entity.store.vo.LifeGroupBuyThaliVo;
+import shop.alien.entity.storePlantform.vo.LifeGroupBuyPlantformDto;
+import shop.alien.storeplatform.service.LifeGroupBuyService;
+
+/**
+ * 团购
+ * @date 2025-11-11
+ */
+@Api(tags = {"商家端-团购"})
+@Slf4j
+@CrossOrigin
+@RestController
+@RequestMapping("/PcGroupBuy")
+@RequiredArgsConstructor
+public class LifeGroupBuyController {
+
+    /**
+     * 团购服务层
+     */
+    private final LifeGroupBuyService lifeGroupBuyService;
+
+    /**
+     * 保存套餐团购草稿
+     *
+     * @param lifeGroupBuyDto 套餐团购数据
+     * @return 操作结果
+     * @date 2025-11-11
+     */
+    @ApiOperation("保存套餐团购草稿")
+    @PostMapping("/saveDraft")
+    public R saveDraft(@RequestBody LifeGroupBuyPlantformDto lifeGroupBuyDto) {
+        log.info("LifeGroupBuyController.saveThali?lifeGroupBuyDto={}", lifeGroupBuyDto.toString());
+        if (lifeGroupBuyService.saveDraft(lifeGroupBuyDto)) {
+            return R.success("成功");
+        }
+        return R.fail("失败");
+    }
+
+    /**
+     * 保存套餐团购并返回套餐信息
+     *
+     * @param lifeGroupBuyDto 套餐团购数据
+     * @return 保存后的套餐详情
+     * @date 2025-11-11
+     */
+    @ApiOperation("保存套餐团购(返回保存套餐)")
+    @PostMapping("/saveThali")
+    public R<LifeGroupBuyThali> saveThali(@RequestBody LifeGroupBuyDto lifeGroupBuyDto) {
+        log.info("LifeGroupBuyController.saveThaliNew?lifeGroupBuyDto={}", lifeGroupBuyDto.toString());
+        LifeGroupBuyThali lifeGroupBuyThali = lifeGroupBuyService.saveThali(lifeGroupBuyDto);
+        return R.data(lifeGroupBuyThali);
+    }
+
+    /**
+     * 分页查询套餐团购列表
+     *
+     * @param pageNum      页码
+     * @param pageSize      每页数量
+     * @param storeId   门店编号
+     * @param status    状态
+     * @param groupName 团购名称
+     * @param groupType 团购类型
+     * @return 套餐团购分页信息
+     * @date 2025-11-11
+     */
+    @ApiOperation("套餐团购列表")
+    @ApiImplicitParams({@ApiImplicitParam(name = "pageNum", value = "页数", dataType = "Integer", paramType = "query", required = true),
+            @ApiImplicitParam(name = "pageSize", value = "页容", dataType = "Integer", paramType = "query", required = true),
+            @ApiImplicitParam(name = "storeId", value = "门店id", dataType = "String", paramType = "query", required = true),
+            @ApiImplicitParam(name = "status", value = "状态(0草稿/1待审核/2未开始/3审核拒绝/4已售罄/5进行中/6已下架/7已结束/8=2+手动下架)", dataType = "String", paramType = "query", required = false),
+            @ApiImplicitParam(name = "groupName", value = "名称", dataType = "String", paramType = "query", required = false),
+            @ApiImplicitParam(name = "groupType", value = "团购类型", dataType = "String", paramType = "query", required = false),
+            @ApiImplicitParam(name = "reviewType", value = "审核状态", dataType = "String", paramType = "query", required = false)
+    })
+    @GetMapping("/getThaliList")
+    private R<IPage<LifeGroupBuyThaliVo>> getThaliList(@RequestParam(value = "pageNum", defaultValue = "1") int pageNum,
+                                                       @RequestParam(value = "pageSize", defaultValue = "10") int pageSize,
+                                                       @RequestParam(value = "storeId") String storeId,
+                                                       @RequestParam(value = "status", required = false) String status,
+                                                       @RequestParam(value = "groupName", required = false) String groupName,
+                                                       @RequestParam(value = "groupType", required = false) String groupType,
+                                                       @RequestParam(value = "groupNo", required = false) String groupNo,
+                                                       @RequestParam(value = "reviewType", required = false) String reviewType) {
+        log.info("LifeGroupBuyController.getThaliList?page={},size={},storeId={},status={},groupName={},groupType={},reviewType={},groupNo={}", pageNum, pageSize, storeId, status, groupName, groupType, reviewType, groupNo);
+        return R.data(lifeGroupBuyService.getThaliList(pageNum, pageSize, storeId, status, groupName, groupType, reviewType, groupNo));
+    }
+
+    /**
+     * 根据编号查询套餐团购详情
+     *
+     * @param id     团购编号
+     * @param userId 用户编号
+     * @return 团购详情
+     * @date 2025-11-11
+     */
+    @ApiOperation("id查询套餐团购")
+    @GetMapping("/getThaliById")
+    private R getThaliById(@RequestParam("id") String id, String userId) {
+        log.info("LifeGroupBuyController.getThaliById?id={}&userId={}", id, userId);
+        return R.data(lifeGroupBuyService.getThaliById(id, userId));
+    }
+
+    /**
+     * 更新团购状态
+     *
+     * @param id                团购编号
+     * @param status            状态值
+     * @param approvalComments  审核意见
+     * @return 操作结果
+     * @date 2025-11-11
+     */
+    @ApiOperation("修改团购状态")
+    @GetMapping("/updateStatus")
+    private R updateStatus(@RequestParam("id") String id, @RequestParam("status") String status, @RequestParam("approvalComments") String approvalComments) {
+        log.info("LifeGroupBuyController.updateStatus?id={},status={},approvalComments={}", id, status, approvalComments);
+        if (lifeGroupBuyService.updateStatus(id, status, approvalComments)) {
+            return R.success("成功");
+        }
+        return R.fail("失败");
+    }
+
+    /**
+     * 修改团购库存
+     *
+     * @param id  团购编号
+     * @param num 库存数量
+     * @return 操作结果
+     * @date 2025-11-11
+     */
+    @ApiOperation("修改团购库存")
+    @GetMapping("/updateNum")
+    private R updateNum(@RequestParam("id") String id, @RequestParam("num") String num) {
+        log.info("LifeGroupBuyController.updateNum?id={},num={}", id, num);
+        if (lifeGroupBuyService.updateNum(id, num)) {
+            return R.success("成功");
+        }
+        return R.fail("失败");
+    }
+
+    /**
+     * 删除套餐团购
+     *
+     * @param id        团购编号
+     * @param groupType 团购类型
+     * @return 操作结果
+     * @date 2025-11-11
+     */
+    @ApiOperation("删除套餐团购")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "id", dataType = "String", paramType = "query", required = true),
+            @ApiImplicitParam(name = "groupType", value = "团购类型(1美食)", dataType = "String", paramType = "query", required = true)
+    })
+    @GetMapping("/delThaliById")
+    private R delThaliById(@RequestParam("id") String id, @RequestParam("groupType") String groupType) {
+        log.info("LifeGroupBuyController.delThaliById?id={},groupType={}", id, groupType);
+        if (lifeGroupBuyService.delThaliById(id, groupType)) {
+            return R.success("成功");
+        }
+        return R.fail("失败");
+    }
+}

+ 91 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/service/LifeGroupBuyService.java

@@ -0,0 +1,91 @@
+package shop.alien.storeplatform.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.springframework.transaction.annotation.Transactional;
+import shop.alien.entity.store.LifeGroupBuyMain;
+import shop.alien.entity.store.LifeGroupBuyThali;
+import shop.alien.entity.store.dto.LifeGroupBuyDto;
+import shop.alien.entity.store.vo.LifeGroupBuyThaliVo;
+import shop.alien.entity.storePlantform.vo.LifeGroupBuyPlantformDto;
+
+/**
+ * 团购服务接口
+ * @date 2025-11-11
+ */
+public interface LifeGroupBuyService extends IService<LifeGroupBuyMain> {
+
+    /**
+     * 保存团购草稿
+     *
+     * @param lifeGroupBuyDto 团购数据
+     * @return 是否保存成功
+     * @date 2025-11-11
+     */
+    @Transactional(rollbackFor = Exception.class)
+    boolean saveDraft(LifeGroupBuyPlantformDto lifeGroupBuyDto);
+
+    /**
+     * 保存团购并返回套餐信息
+     *
+     * @param lifeGroupBuyDto 团购数据
+     * @return 最新套餐记录
+     * @date 2025-11-11
+     */
+    LifeGroupBuyThali saveThali(LifeGroupBuyDto lifeGroupBuyDto);
+
+    /**
+     * 查询团购套餐列表
+     *
+     * @param page      页码
+     * @param size      每页数量
+     * @param storeId   门店编号
+     * @param status    状态
+     * @param groupName 团购名称
+     * @param groupType 团购类型
+     * @return 分页数据
+     * @date 2025-11-11
+     */
+    IPage<LifeGroupBuyThaliVo> getThaliList(int page, int size, String storeId, String status, String groupName, String groupType, String reviewType, String groupNo);
+
+    /**
+     * 根据编号查询团购详情
+     *
+     * @param id     团购编号
+     * @param userId 用户编号
+     * @return 团购详情
+     * @date 2025-11-11
+     */
+    LifeGroupBuyThaliVo getThaliById(String id, String userId);
+
+    /**
+     * 更新团购状态
+     *
+     * @param id               团购编号
+     * @param status           状态值
+     * @param approvalComments 审核意见
+     * @return 是否更新成功
+     * @date 2025-11-11
+     */
+    boolean updateStatus(String id,String status, String approvalComments);
+
+    /**
+     * 删除团购
+     *
+     * @param id        团购编号
+     * @param groupType 团购类型
+     * @return 是否删除成功
+     * @date 2025-11-11
+     */
+    boolean delThaliById(String id,String groupType);
+
+    /**
+     * 更新团购库存
+     *
+     * @param id  团购编号
+     * @param num 库存数量
+     * @return 是否更新成功
+     * @date 2025-11-11
+     */
+    boolean updateNum(String id, String num);
+}

+ 497 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/LifeGroupBuyServiceImpl.java

@@ -0,0 +1,497 @@
+package shop.alien.storeplatform.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.RequiredArgsConstructor;
+import org.apache.http.client.utils.DateUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+import shop.alien.entity.store.*;
+import shop.alien.entity.store.dto.LifeGroupBuyDto;
+import shop.alien.entity.store.vo.LifeGroupBuyNameThaliVo;
+import shop.alien.entity.store.vo.LifeGroupBuyThaliVo;
+import shop.alien.entity.store.vo.StoreMenuVo;
+import shop.alien.entity.storePlantform.LifeGroupBuyMainPlantform;
+import shop.alien.entity.storePlantform.vo.LifeGroupBuyPlantformDto;
+import shop.alien.mapper.*;
+import shop.alien.mapper.storePlantform.LifeGroupBuyMainPlantformMapper;
+import shop.alien.storeplatform.service.LifeGroupBuyService;
+import shop.alien.util.common.JwtUtil;
+
+import java.math.BigDecimal;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 团购服务实现
+ * @date 2025-11-11
+ */
+@Service
+@RequiredArgsConstructor
+public class LifeGroupBuyServiceImpl extends ServiceImpl<LifeGroupBuyMainMapper, LifeGroupBuyMain> implements LifeGroupBuyService {
+
+    /**
+     * 团购主表 Mapper
+     */
+    private final LifeGroupBuyMainMapper lifeGroupBuyMainMapper;
+
+    /**
+     * 团购套餐 Mapper
+     */
+    private final LifeGroupBuyThaliMapper lifeGroupBuyThaliMapper;
+
+    /**
+     * 门店图片 Mapper
+     */
+    private final StoreImgMapper storeImgMapper;
+
+    /**
+     * 节假日对照 Mapper
+     */
+    private final EssentialHolidayComparisonMapper essentialHolidayComparisonMapper;
+
+    /**
+     * 门店菜品 Mapper
+     */
+    private final StoreMenuMapper storeMenuMapper;
+
+    /**
+     * 收藏 Mapper
+     */
+    private final LifeCollectMapper lifeCollectMapper;
+
+    /**
+     * 审核记录 Mapper
+     */
+    private final WebAuditMapper webAuditMapper;
+
+    /**
+     * 订单 Mapper
+     */
+    private final LifeUserOrderMapper lifeUserOrderMapper;
+
+    /**
+     * 团购主表 Mapper
+     */
+    private final LifeGroupBuyMainPlantformMapper lifeGroupBuyMainPlantformMapper;
+
+
+    /**
+     * 保存团购草稿
+     *
+     * @param lifeGroupBuyDto 团购数据
+     * @return 是否保存成功
+     * @date 2025-11-11
+     */
+    @Override
+    public boolean saveDraft(LifeGroupBuyPlantformDto lifeGroupBuyDto) {
+        LifeGroupBuyMainPlantform lifeGroupBuyMain = lifeGroupBuyDto.getLifeGroupBuyMain();
+        List<LifeGroupBuyThali> lifeGroupBuyThalis = lifeGroupBuyDto.getLifeGroupBuyThalis();
+
+
+        if (lifeGroupBuyMain.getEffectiveDateType() != null && lifeGroupBuyMain.getEffectiveDateType() == 1) {
+            List<String> expirationDate = lifeGroupBuyMain.getExpirationDate();
+            if (ObjectUtils.isNotEmpty(expirationDate)) {
+                lifeGroupBuyMain.setEffectiveDateValue(String.join(",", expirationDate));
+            } else {
+                lifeGroupBuyMain.setEffectiveDateValue("");
+            }
+        }
+
+        if (lifeGroupBuyMain.getDisableDateType() != null && lifeGroupBuyMain.getDisableDateType() == 2) {
+            lifeGroupBuyMain.getDisableDateList()
+            if (ObjectUtils.isNotEmpty()) {
+                lifeGroupBuyMain.setEffectiveDateValue(String.join(",", disableDateList));
+            } else {
+                lifeGroupBuyMain.setEffectiveDateValue("");
+            }
+        }
+
+
+
+
+
+
+
+
+
+
+
+
+        JSONObject currentUserInfo = JwtUtil.getCurrentUserInfo();
+        Integer userId = null;
+        if (!ObjectUtils.isEmpty(currentUserInfo)) {
+            userId = currentUserInfo.getInteger("userId");
+        }
+        if (ObjectUtils.isEmpty(lifeGroupBuyMain.getId())) {
+            Integer count = lifeGroupBuyMainMapper.selectCount(new LambdaQueryWrapper<LifeGroupBuyMain>().like(LifeGroupBuyMain::getCreatedTime, DateUtils.formatDate(new Date(), "yyyy-MM-dd")).eq(LifeGroupBuyMain::getStoreId, lifeGroupBuyMain.getStoreId()));
+            lifeGroupBuyMain.setGroupNo("G" + DateUtils.formatDate(new Date(), "yyyyMMdd") + lifeGroupBuyMain.getStoreId() + org.apache.commons.lang3.StringUtils.leftPad(String.valueOf(count + 1), 5, "0"));
+            lifeGroupBuyMain.setCreatedUserId(userId);
+            lifeGroupBuyMainMapper.insert(lifeGroupBuyMain);
+            if (ObjectUtils.isNotEmpty(lifeGroupBuyThalis)) {
+                for (int i = 0; i < lifeGroupBuyThalis.size(); i++) {
+                    LifeGroupBuyThali lifeGroupBuyThali = lifeGroupBuyThalis.get(i);
+                    lifeGroupBuyThali.setParentId(lifeGroupBuyMain.getId().toString());
+                    lifeGroupBuyThali.setDetailSort(i + 1);
+                    lifeGroupBuyThali.setCreatedUserId(userId);
+                    lifeGroupBuyThaliMapper.insert(lifeGroupBuyThali);
+                }
+            }
+            return true;
+        } else {
+            lifeGroupBuyMain.setUpdatedUserId(userId);
+            lifeGroupBuyMainMapper.updateById(lifeGroupBuyMain);
+            lifeGroupBuyThaliMapper.update(null, new LambdaUpdateWrapper<LifeGroupBuyThali>().eq(LifeGroupBuyThali::getParentId, lifeGroupBuyMain.getId()).set(LifeGroupBuyThali::getDeleteFlag, 1));
+            if (ObjectUtils.isNotEmpty(lifeGroupBuyThalis)) {
+                for (int i = 0; i < lifeGroupBuyThalis.size(); i++) {
+                    LifeGroupBuyThali lifeGroupBuyThali = lifeGroupBuyThalis.get(i);
+                    lifeGroupBuyThali.setParentId(lifeGroupBuyMain.getId().toString());
+                    lifeGroupBuyThali.setDetailSort(i + 1);
+                    lifeGroupBuyThali.setCreatedUserId(userId);
+                    lifeGroupBuyThaliMapper.insert(lifeGroupBuyThali);
+                }
+            }
+            return true;
+        }
+    }
+
+    /**
+     * 保存团购并返回套餐信息
+     *
+     * @param lifeGroupBuyDto 团购数据
+     * @return 最新套餐记录
+     * @date 2025-11-11
+     */
+    @Override
+    public LifeGroupBuyThali saveThali(LifeGroupBuyDto lifeGroupBuyDto) {
+        JSONObject currentUserInfo = JwtUtil.getCurrentUserInfo();
+        Integer userId = null;
+        if (!ObjectUtils.isEmpty(currentUserInfo)) {
+            userId = currentUserInfo.getInteger("userId");
+        }
+        LifeGroupBuyMain lifeGroupBuyMain = lifeGroupBuyDto.getLifeGroupBuyMain();
+        List<LifeGroupBuyThali> lifeGroupBuyThalis = lifeGroupBuyDto.getLifeGroupBuyThalis();
+        LifeGroupBuyThali lifeGroupBuyThali = null;
+        if (ObjectUtils.isEmpty(lifeGroupBuyMain.getId())) {
+            Integer count = lifeGroupBuyMainMapper.selectCount(new LambdaQueryWrapper<LifeGroupBuyMain>().like(LifeGroupBuyMain::getCreatedTime, DateUtils.formatDate(new Date(), "yyyy-MM-dd")).eq(LifeGroupBuyMain::getStoreId, lifeGroupBuyMain.getStoreId()));
+            lifeGroupBuyMain.setGroupNo("G" + DateUtils.formatDate(new Date(), "yyyyMMdd") + lifeGroupBuyMain.getStoreId() + org.apache.commons.lang3.StringUtils.leftPad(String.valueOf(count + 1), 5, "0"));
+            lifeGroupBuyMain.setCreatedUserId(userId);
+            lifeGroupBuyMain.setCreatedTime(new Date());
+            lifeGroupBuyMainMapper.insert(lifeGroupBuyMain);
+            if (ObjectUtils.isNotEmpty(lifeGroupBuyThalis)) {
+                for (int i = 0; i < lifeGroupBuyThalis.size(); i++) {
+                    lifeGroupBuyThali = lifeGroupBuyThalis.get(i);
+                    lifeGroupBuyThali.setParentId(lifeGroupBuyMain.getId().toString());
+                    lifeGroupBuyThali.setDetailSort(i + 1);
+                    lifeGroupBuyThali.setCreatedUserId(userId);
+                    lifeGroupBuyThali.setCreatedTime(new Date());
+                    lifeGroupBuyThaliMapper.insert(lifeGroupBuyThali);
+                }
+            }
+            return lifeGroupBuyThali;
+        } else {
+            lifeGroupBuyMain.setUpdatedUserId(userId);
+            lifeGroupBuyMain.setCreatedTime(new Date());
+            lifeGroupBuyMainMapper.updateById(lifeGroupBuyMain);
+            lifeGroupBuyThaliMapper.update(null, new LambdaUpdateWrapper<LifeGroupBuyThali>().eq(LifeGroupBuyThali::getParentId, lifeGroupBuyMain.getId()).set(LifeGroupBuyThali::getDeleteFlag, 1).set(LifeGroupBuyThali::getCreatedTime, new Date()));
+            if (ObjectUtils.isNotEmpty(lifeGroupBuyThalis)) {
+                for (int i = 0; i < lifeGroupBuyThalis.size(); i++) {
+                    lifeGroupBuyThali = lifeGroupBuyThalis.get(i);
+                    lifeGroupBuyThali.setParentId(lifeGroupBuyMain.getId().toString());
+                    lifeGroupBuyThali.setDetailSort(i + 1);
+                    lifeGroupBuyThali.setCreatedUserId(userId);
+                    lifeGroupBuyThaliMapper.insert(lifeGroupBuyThali);
+                }
+            }
+            return lifeGroupBuyThali;
+        }
+    }
+
+    /**
+     * 查询团购套餐列表
+     *
+     * @param page      页码
+     * @param size      每页数量
+     * @param storeId   门店编号
+     * @param status    状态
+     * @param groupName 团购名称
+     * @param groupType 团购类型
+     * @return 套餐分页数据
+     * @date 2025-11-11
+     */
+    @Override
+    public IPage<LifeGroupBuyThaliVo> getThaliList(int page, int size, String storeId, String status, String groupName, String groupType, String reviewType, String groupNo) {
+        QueryWrapper<LifeGroupBuyThaliVo> queryWrapper = new QueryWrapper<>();
+        queryWrapper.eq(StringUtils.isNotEmpty(storeId), "store_id", storeId);
+        if (StringUtils.isNotEmpty(reviewType)) {
+            switch (reviewType) {
+                case "0":
+                    queryWrapper.eq("status", "1");
+                    break;
+                case "1":
+                    queryWrapper.in("status", Arrays.asList("2", "4", "5", "6", "7", "8"));
+                    break;
+                case "2":
+                    queryWrapper.eq("status", "3");
+                    break;
+                default:
+                    queryWrapper.eq(StringUtils.isNotEmpty(status), "status", status);
+                    break;
+            }
+        } else {
+            if ("8".equals(status)) {
+                queryWrapper.in(StringUtils.isNotEmpty(status), "status", Arrays.asList("2", "6"));
+            } else {
+                queryWrapper.eq(StringUtils.isNotEmpty(status), "status", status);
+            }
+        }
+        queryWrapper.eq(StringUtils.isNotEmpty(groupType), "group_type", groupType);
+        queryWrapper.like(StringUtils.isNotEmpty(groupName), "group_name", groupName);
+        queryWrapper.like(StringUtils.isNotEmpty(groupNo), "group_no", groupNo);
+        queryWrapper.eq("delete_flag", 0);
+        queryWrapper.orderByDesc("created_time");
+        IPage<LifeGroupBuyThaliVo> lifeGroupBuyThaliVoIPage = new Page<>(page, size);
+        IPage<LifeGroupBuyThaliVo> voIPage = lifeGroupBuyMainMapper.selectPageByThaliVo(lifeGroupBuyThaliVoIPage, queryWrapper);
+        voIPage.getRecords().forEach(this::getMainImgAndDisableDate);
+        return voIPage;
+    }
+
+    /**
+     * 根据编号查询团购详情
+     *
+     * @param id     团购编号
+     * @param userId 用户编号
+     * @return 团购详情
+     * @date 2025-11-11
+     */
+    @Override
+    public LifeGroupBuyThaliVo getThaliById(String id, String userId) {
+        LifeGroupBuyMain lifeGroupBuyMain = lifeGroupBuyMainMapper.selectById(id);
+        LifeGroupBuyThaliVo lifeGroupBuyThaliVo = new LifeGroupBuyThaliVo();
+        BeanUtils.copyProperties(lifeGroupBuyMain, lifeGroupBuyThaliVo);
+        List<LifeGroupBuyThali> lifeGroupBuyThalis = lifeGroupBuyThaliMapper.selectList(new LambdaQueryWrapper<LifeGroupBuyThali>().eq(LifeGroupBuyThali::getParentId, id).eq(LifeGroupBuyThali::getDeleteFlag, 0));
+
+        // 是否收藏了该团购
+        LifeCollect lifeCollect = lifeCollectMapper.selectOne(new QueryWrapper<LifeCollect>().eq("user_id", userId).eq("coupon_id", id));
+        lifeGroupBuyThaliVo.setIsCollect("0");
+        if (!Objects.isNull(lifeCollect)) {
+            lifeGroupBuyThaliVo.setIsCollect("1");
+        }
+        //美食
+        if (lifeGroupBuyMain.getGroupType() == 1) {
+            for (LifeGroupBuyThali lifeGroupBuyThali : lifeGroupBuyThalis) {
+                if (StringUtils.isNotEmpty(lifeGroupBuyThali.getDetailId())) {
+                    StoreMenuVo menuInfo = storeMenuMapper.getMenuInfo(Integer.parseInt(lifeGroupBuyThali.getDetailId()));
+                    if (ObjectUtils.isNotEmpty(menuInfo)) {
+                        lifeGroupBuyThali.setDishName(menuInfo.getDishName());
+                        lifeGroupBuyThali.setDishImg(menuInfo.getImgUrl());
+                        lifeGroupBuyThali.setDishPrice(menuInfo.getDishPrice().toString());
+                        lifeGroupBuyThali.setDishesUnit(menuInfo.getDishesUnit());
+                    }
+                }
+            }
+        }
+
+        Map<String, List<LifeGroupBuyThali>> collect = lifeGroupBuyThalis.stream().collect(Collectors.groupingBy(LifeGroupBuyThali::getGroupName));
+        List<LifeGroupBuyNameThaliVo> resultMap = new ArrayList<>();
+        List<String> keys = collect.entrySet().stream().sorted(Comparator.comparingInt(i -> i.getValue().get(0).getDetailSort())).map(Map.Entry::getKey).collect(Collectors.toList());
+        for (String key : keys) {
+            LifeGroupBuyNameThaliVo lifeGroupBuyNameThaliVo = new LifeGroupBuyNameThaliVo();
+            lifeGroupBuyNameThaliVo.setGroupName(key);
+            lifeGroupBuyNameThaliVo.setDetails(collect.get(key).stream().sorted(Comparator.comparingInt(LifeGroupBuyThali::getDetailSort)).collect(Collectors.toList()));
+            resultMap.add(lifeGroupBuyNameThaliVo);
+        }
+        lifeGroupBuyThaliVo.setDetails(resultMap);
+        getMainImgAndDisableDate(lifeGroupBuyThaliVo);
+
+        //已售数量
+        lifeGroupBuyThaliVo.setSaleNum(lifeUserOrderMapper.countBuyGroup(id));
+
+        return lifeGroupBuyThaliVo;
+    }
+
+    /**
+     * 更新团购状态
+     *
+     * @param id               团购编号
+     * @param status           状态值
+     * @param approvalComments 审核意见
+     * @return 是否更新成功
+     * @date 2025-11-11
+     */
+    @Override
+    public boolean updateStatus(String id, String status, String approvalComments) {
+        LambdaUpdateWrapper<LifeGroupBuyMain> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
+        lambdaUpdateWrapper.eq(LifeGroupBuyMain::getId, id);
+        lambdaUpdateWrapper.set(LifeGroupBuyMain::getStatus, status);
+        lambdaUpdateWrapper.set(LifeGroupBuyMain::getApprovalComments, approvalComments);
+        if(status.equals("5")){
+            LifeGroupBuyMain lifeGroupBuyMain = lifeGroupBuyMainMapper.selectById(id);
+            if(lifeGroupBuyMain !=null && lifeGroupBuyMain.getStatus()==2){
+                lambdaUpdateWrapper.set(LifeGroupBuyMain::getStartTimeValue, new Date());
+            }
+        }
+            lifeGroupBuyMainMapper.update(null,lambdaUpdateWrapper);
+        //处理中台审核记录
+        if (StringUtils.isNotEmpty(id) && StringUtils.isNotEmpty(status) && (status.equals("2") || status.equals("3"))) {
+            LambdaUpdateWrapper<WebAudit> wrapper = new LambdaUpdateWrapper<>();
+            wrapper.eq(WebAudit::getLifeGroupPackageId, id);
+            wrapper.set(WebAudit::getStatus, "1");
+            webAuditMapper.update(null, wrapper);
+        }
+        return true;
+    }
+
+    /**
+     * 删除团购
+     *
+     * @param id        团购编号
+     * @param groupType 团购类型
+     * @return 是否删除成功
+     * @date 2025-11-11
+     */
+    @Override
+    public boolean delThaliById(String id, String groupType) {
+        if ("1".equals(groupType)) {
+            lifeGroupBuyThaliMapper.update(null, new LambdaUpdateWrapper<LifeGroupBuyThali>().eq(LifeGroupBuyThali::getParentId, id).set(LifeGroupBuyThali::getDeleteFlag, 1));
+        }
+        lifeGroupBuyMainMapper.update(null, new LambdaUpdateWrapper<LifeGroupBuyMain>().eq(LifeGroupBuyMain::getId, id).set(LifeGroupBuyMain::getDeleteFlag, 1));
+        return true;
+    }
+
+    /**
+     * 更新团购库存
+     *
+     * @param id  团购编号
+     * @param num 库存数量
+     * @return 是否更新成功
+     * @date 2025-11-11
+     */
+    @Override
+    public boolean updateNum(String id, String num) {
+        //判断库存数为0 增加库存数修改状态为进行中
+        LambdaQueryWrapper<LifeGroupBuyMain> lambdaQueryWrapper = new LambdaQueryWrapper<>();
+        lambdaQueryWrapper.eq(LifeGroupBuyMain :: getId, id);
+        LifeGroupBuyMain lifeGroupBuyMain = lifeGroupBuyMainMapper.selectOne(lambdaQueryWrapper);
+
+        if(lifeGroupBuyMain.getInventoryNum() == 0){
+            LambdaUpdateWrapper<LifeGroupBuyMain> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
+            lambdaUpdateWrapper.eq(LifeGroupBuyMain :: getId, id);
+            lambdaUpdateWrapper.set(LifeGroupBuyMain :: getStatus, 5);
+            lambdaUpdateWrapper.set(LifeGroupBuyMain :: getInventoryNum, num);
+            lifeGroupBuyMainMapper.update(null, lambdaUpdateWrapper);
+        }
+        else {
+            LambdaUpdateWrapper<LifeGroupBuyMain> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
+            lambdaUpdateWrapper.eq(LifeGroupBuyMain::getId, id);
+            lambdaUpdateWrapper.set(LifeGroupBuyMain::getInventoryNum, num);
+            lifeGroupBuyMainMapper.update(null, lambdaUpdateWrapper);
+        }
+
+        return true;
+    }
+
+    /**
+     * 填充主图与不可用日期信息
+     *
+     * @param record 团购套餐数据
+     * @date 2025-11-11
+     */
+    private void getMainImgAndDisableDate(LifeGroupBuyThaliVo record) {
+        //图片
+        if (StringUtils.isNotEmpty(record.getImageId())) {
+            List<String> imgIds = Arrays.asList(record.getImageId().split(","));
+            List<StoreImg> storeImgs = storeImgMapper.selectList(new LambdaQueryWrapper<StoreImg>().in(StoreImg::getId, imgIds));
+            if (ObjectUtils.isNotEmpty(storeImgs)) {
+                /*String imgs = storeImgs.stream()
+                        .map(StoreImg::getImgUrl)
+                        .collect(Collectors.joining("*"));
+                record.setImageValueStr(imgs);*/
+                record.setImageValueStr(storeImgs.stream().map(StoreImg::getImgUrl).collect(Collectors.toList()));
+            }
+        }
+        //不可用日期
+        if (ObjectUtils.isNotEmpty(record.getDisableDateType())) {
+            if (record.getDisableDateType() == 1) {
+                List<String> valueList = Arrays.asList(record.getDisableDateValue().split(";"));
+                String holiday = "";
+                if (valueList.size() > 1) {
+                    List<String> list = Arrays.asList(valueList.get(1).split(","));
+                    List<EssentialHolidayComparison> essentialHolidayComparisons = essentialHolidayComparisonMapper.selectList(new LambdaQueryWrapper<EssentialHolidayComparison>().in(EssentialHolidayComparison::getId, list));
+                    holiday = essentialHolidayComparisons.stream().map(EssentialHolidayComparison::getFestivalName).collect(Collectors.joining(","));
+                }
+                if (StringUtils.isNotEmpty(valueList.get(0)) && StringUtils.isNotEmpty(holiday)) {
+                    record.setDisableDateValueStr(valueList.get(0) + ";" + holiday);
+                }
+                if (StringUtils.isEmpty(valueList.get(0))) {
+                    record.setDisableDateValueStr(holiday);
+                }
+                if (StringUtils.isEmpty(holiday)) {
+                    record.setDisableDateValueStr(valueList.get(0));
+                }
+            }
+        }
+
+        //已售数量
+        record.setSaleNum(lifeUserOrderMapper.countBuyGroup(record.getId().toString()));
+
+        BigDecimal costPrice = lifeGroupBuyMainPlantformMapper.selectSumCostPrice(record.getId());
+        if (ObjectUtils.isEmpty(costPrice)) {
+            costPrice = BigDecimal.ZERO;;
+        }
+        record.setCostPrice(costPrice);
+
+        if (ObjectUtils.isNotEmpty(record.getPreferentialPrice())) {
+            record.setProfit(record.getPreferentialPrice().subtract(costPrice));
+        }
+
+        if (record.getStatus() == 1) {
+            record.setReviewType("待审核");
+        } else if (record.getStatus() == 2 || record.getStatus() == 4 || record.getStatus() == 5 || record.getStatus() == 6 || record.getStatus() == 7 ) {
+            record.setReviewType("审核通过");
+        } else if (record.getStatus() == 3) {
+            record.setReviewType("审核拒绝");
+
+            if (Objects.nonNull(record.getStatus())) {
+                switch (record.getStatus()) {
+                    case 0:
+                        record.setStatusName("草稿");
+                        break;
+                    case 1:
+                        record.setStatusName("待审核");
+                        break;
+                    case 2:
+                        record.setStatusName("未开始");
+                        break;
+                    case 3:
+                        record.setStatusName("审核拒绝");
+                        break;
+                    case 4:
+                        record.setStatusName("已售罄");
+                        break;
+                    case 5:
+                        record.setStatusName("进行中");
+                        break;
+                    case 6:
+                        record.setStatusName("已下架");
+                        break;
+                    case 7:
+                        record.setStatusName("已结束");
+                        break;
+                    default:
+                        record.setStatusName("未知状态");
+                        break;
+                }
+            }
+        }
+
+    }
+
+}

+ 10 - 1
alien-store/src/main/java/shop/alien/store/service/LifeUserService.java

@@ -14,6 +14,8 @@ import org.apache.commons.lang3.tuple.Triple;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
 import shop.alien.config.properties.RiskControlProperties;
 import shop.alien.entity.second.LifeUserLog;
@@ -244,6 +246,7 @@ public class LifeUserService extends ServiceImpl<LifeUserMapper, LifeUser> {
         }
     }
 
+    @Transactional
     public void addLifeUserLogInfo(LifeUser user, String macIp) {
         try {
             LifeUserLog lifeUserLog = new LifeUserLog();
@@ -255,7 +258,8 @@ public class LifeUserService extends ServiceImpl<LifeUserMapper, LifeUser> {
             if (count > 0) {
                 String startDate = LocalDateTime.now().minusHours(24L).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                 String endDate = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
-                List<LifeUserLog> lsit = lifeUserLogMapper.getLifeUserLogByDate(startDate, endDate, macIp);
+                // 使用一个新的事务来查询,确保能看到刚才插入的数据
+                List<LifeUserLog> lsit = getLifeUserLogByDateInNewTransaction(startDate, endDate, macIp);
 
                 if (lsit.size() > riskControlProperties.getAccountAbnormal().getRegCount24h() && !isViolation(startDate, endDate, macIp, user.getId())) {
                     String detailInfo = lsit.stream()
@@ -271,6 +275,11 @@ public class LifeUserService extends ServiceImpl<LifeUserMapper, LifeUser> {
         }
     }
 
+    @Transactional(propagation = Propagation.REQUIRES_NEW)
+    public List<LifeUserLog> getLifeUserLogByDateInNewTransaction(String startDate, String endDate, String macIp) {
+        return lifeUserLogMapper.getLifeUserLogByDate(startDate, endDate, macIp);
+    }
+
     public boolean isViolation(String startDate, String endDate, String macIp, Integer userId) {
         List<SecondRiskControlRecord> list = secondRiskControlRecordMapper.selectByBusinessId(startDate, endDate, macIp);
         for (SecondRiskControlRecord record : list) {