Merge branch 'master' of https://gitea.zianxin.com/zax/biz-api-cloud-zax
This commit is contained in:
commit
e2d28b5d53
13 files changed
+450
-64
No files matched your search
+48
@@ -0,0 +1,48 @@
|
||||
package com.bsd.pjcloud.canteen.entity;
|
||||
|
||||
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 com.baomidou.mybatisplus.extension.activerecord.Model;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@TableName("canteen_online_combo_item")
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Schema(description = "线上点餐套餐组成明细")
|
||||
public class CanteenOnlineComboItemEntity extends Model<CanteenOnlineComboItemEntity> {
|
||||
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "套餐 SPU id")
|
||||
private Long comboSpuId;
|
||||
|
||||
@Schema(description = "组成菜品 SPU id")
|
||||
private Long childSpuId;
|
||||
|
||||
@Schema(description = "份数")
|
||||
private Integer quantity;
|
||||
|
||||
@Schema(description = "排序")
|
||||
private Integer sortOrder;
|
||||
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@TableField(exist = false)
|
||||
@Schema(description = "组成菜品名称")
|
||||
private String childSpuName;
|
||||
|
||||
@TableField(exist = false)
|
||||
@Schema(description = "组成菜品封面图")
|
||||
private String childSpuPicUrl;
|
||||
|
||||
@TableField(exist = false)
|
||||
@Schema(description = "组成菜品价格(分)")
|
||||
private Integer childSpuPrice;
|
||||
}
|
||||
+16
-1
@@ -10,7 +10,9 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import com.bsd.pjcloud.common.core.util.TenantTable;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 在线点餐spu
|
||||
@@ -80,9 +82,15 @@ public class CanteenOnlineSpuEntity extends Model<CanteenOnlineSpuEntity> {
|
||||
/**
|
||||
* 商品状态: 0 上架(默认/开启) 1 下架(禁用) -1 回收
|
||||
*/
|
||||
@Schema(description="商品状态: 0 上架(默认/开启) 1 下架(禁用) -1 回收")
|
||||
@Schema(description="商品状态: 0 上架(默认/开启) 1 下架(禁用) -1 回收")
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 商品类型:1单品 2套餐
|
||||
*/
|
||||
@Schema(description = "商品类型:1单品 2套餐")
|
||||
private Integer spuType;
|
||||
|
||||
/**
|
||||
* 是否必选:0 否 1 是(前端下单需包含该品,如米饭)
|
||||
*/
|
||||
@@ -212,4 +220,11 @@ public class CanteenOnlineSpuEntity extends Model<CanteenOnlineSpuEntity> {
|
||||
@Schema(description="菜品类型名称")
|
||||
@TableField(exist = false)
|
||||
private String dishTypeName;
|
||||
|
||||
/**
|
||||
* 套餐组成(仅 spuType=2 时使用)
|
||||
*/
|
||||
@Schema(description = "套餐组成明细")
|
||||
@TableField(exist = false)
|
||||
private List<CanteenOnlineComboItemEntity> comboItems;
|
||||
}
|
||||
+8
-8
@@ -1,16 +1,12 @@
|
||||
package com.bsd.pjcloud.canteen.vo;
|
||||
|
||||
import com.bsd.pjcloud.canteen.vo.app.OnlineSpuChoiceGroupRuleVO;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import com.bsd.pjcloud.common.core.util.MoneyDeserializer;
|
||||
import com.bsd.pjcloud.common.core.util.MoneySerializer;
|
||||
import com.bsd.pjcloud.common.core.util.TenantTable;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.bsd.pjcloud.canteen.vo.app.OnlineSpuComboItemVO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 在线点餐spu
|
||||
@@ -19,7 +15,6 @@ import java.time.LocalDateTime;
|
||||
* @date 2024-12-16 23:42:19
|
||||
*/
|
||||
@Data
|
||||
@TenantTable
|
||||
@Schema(description = "在线点餐vo")
|
||||
public class APPOnlineSpuVO {
|
||||
|
||||
@@ -109,6 +104,12 @@ public class APPOnlineSpuVO {
|
||||
@Schema(description = "商品状态: 0 上架 1 下架")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "商品类型:1单品 2套餐")
|
||||
private Integer spuType;
|
||||
|
||||
@Schema(description = "套餐组成(spuType=2 时返回)")
|
||||
private List<OnlineSpuComboItemVO> comboItems;
|
||||
|
||||
/**
|
||||
* 是否必选:0 否 1 是
|
||||
*/
|
||||
@@ -150,7 +151,6 @@ public class APPOnlineSpuVO {
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
@Schema(description="创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package com.bsd.pjcloud.canteen.vo.app;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@Schema(description = "套餐组成项(App)")
|
||||
public class OnlineSpuComboItemVO {
|
||||
|
||||
@Schema(description = "组成菜品 SPU id")
|
||||
private Long childSpuId;
|
||||
|
||||
@Schema(description = "组成菜品名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "组成菜品封面")
|
||||
private String picUrl;
|
||||
|
||||
@Schema(description = "份数")
|
||||
private Integer quantity;
|
||||
|
||||
@Schema(description = "排序")
|
||||
private Integer sortOrder;
|
||||
|
||||
@Schema(description = "组成菜品单价(分,仅展示)")
|
||||
private Integer price;
|
||||
}
|
||||
+5
-2
@@ -10,12 +10,15 @@ public class CanteenOnlineSpuSimpleVO {
|
||||
@Schema(description = "id")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "菜品名称")
|
||||
@Schema(description = "商品名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "菜品封面图")
|
||||
@Schema(description = "商品封面图")
|
||||
private String picUrl;
|
||||
|
||||
@Schema(description = "商品价格,单位:分")
|
||||
private Integer price;
|
||||
|
||||
@Schema(description = "关联线下菜品id")
|
||||
private Long linkSpuId;
|
||||
|
||||
|
||||
+47
-19
@@ -95,6 +95,7 @@ public class CanteenOnlineSpuController {
|
||||
LambdaQueryWrapper<CanteenOnlineSpuEntity> wrapper = Wrappers.lambdaQuery();
|
||||
wrapper.like(StrUtil.isNotBlank(canteenOnlineSpu.getName()), CanteenOnlineSpuEntity::getName, canteenOnlineSpu.getName());
|
||||
wrapper.eq(Objects.nonNull(canteenOnlineSpu.getCategoryId()), CanteenOnlineSpuEntity::getCategoryId, canteenOnlineSpu.getCategoryId());
|
||||
wrapper.eq(Objects.nonNull(canteenOnlineSpu.getSpuType()), CanteenOnlineSpuEntity::getSpuType, canteenOnlineSpu.getSpuType());
|
||||
|
||||
// 根据菜品类型筛选
|
||||
if (Objects.nonNull(dishType)) {
|
||||
@@ -106,7 +107,11 @@ public class CanteenOnlineSpuController {
|
||||
wrapper.isNotNull(CanteenOnlineSpuEntity::getLinkSpuId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
page.orders().clear();
|
||||
wrapper.orderByDesc(CanteenOnlineSpuEntity::getCreateTime)
|
||||
.orderByDesc(CanteenOnlineSpuEntity::getId);
|
||||
|
||||
return R.ok(canteenOnlineSpuService.pageScope(page, wrapper));
|
||||
}
|
||||
|
||||
@@ -117,11 +122,11 @@ public class CanteenOnlineSpuController {
|
||||
* @param id id
|
||||
* @return R
|
||||
*/
|
||||
@Operation(summary = "通过id查询", description = "通过id查询")
|
||||
@Operation(summary = "通过id查询", description = "通过id查询(含套餐组成)")
|
||||
@GetMapping("/{id}")
|
||||
@PreAuthorize("@pms.hasPermission('canteen_canteenOnlineSpu_view')")
|
||||
public R getById(@PathVariable("id") Long id) {
|
||||
return R.ok(canteenOnlineSpuService.getById(id));
|
||||
return R.ok(canteenOnlineSpuService.getDetail(id));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -130,20 +135,26 @@ public class CanteenOnlineSpuController {
|
||||
* @param canteenOnlineSpu 在线点餐spu
|
||||
* @return R
|
||||
*/
|
||||
@Operation(summary = "新增在线点餐spu", description = "新增在线点餐spu")
|
||||
@Operation(summary = "新增在线点餐spu", description = "新增在线点餐spu;套餐时传 spuType=2 与 comboItems")
|
||||
@SysLog("新增在线点餐spu")
|
||||
@ApiCryptoAes
|
||||
@PostMapping
|
||||
@PreAuthorize("@pms.hasPermission('canteen_canteenOnlineSpu_add')")
|
||||
public R save(@RequestBody CanteenOnlineSpuEntity canteenOnlineSpu) {
|
||||
if (canteenOnlineSpu.getChoiceGroupId() != null) {
|
||||
if (canteenOnlineSpu.getChoiceGroupId() != null
|
||||
&& !Objects.equals(canteenOnlineSpu.getSpuType(), 2)) {
|
||||
CanteenOnlineSpuChoiceGroupEntity g = canteenOnlineSpuChoiceGroupService.getById(canteenOnlineSpu.getChoiceGroupId());
|
||||
if (g == null) {
|
||||
return R.failed("择一分组不存在(可能是前端 long 精度丢失导致 id 被圆整),请重新选择分组");
|
||||
}
|
||||
}
|
||||
canteenOnlineSpu.setDeptId(SecurityUtils.getUser().getDeptId());
|
||||
return R.ok(canteenOnlineSpuService.save(canteenOnlineSpu));
|
||||
try {
|
||||
return R.ok(canteenOnlineSpuService.saveDeep(canteenOnlineSpu));
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
return R.failed(ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "批量新增关联每日菜谱", description = "批量新增关联每日菜谱")
|
||||
@@ -161,19 +172,25 @@ public class CanteenOnlineSpuController {
|
||||
* @param canteenOnlineSpu 在线点餐spu
|
||||
* @return R
|
||||
*/
|
||||
@Operation(summary = "修改在线点餐spu", description = "修改在线点餐spu")
|
||||
@Operation(summary = "修改在线点餐spu", description = "修改在线点餐spu;套餐时传 spuType=2 与 comboItems")
|
||||
@SysLog("修改在线点餐spu")
|
||||
@ApiCryptoAes
|
||||
@PutMapping
|
||||
@PreAuthorize("@pms.hasPermission('canteen_canteenOnlineSpu_edit')")
|
||||
public R updateById(@RequestBody CanteenOnlineSpuEntity canteenOnlineSpu) {
|
||||
if (canteenOnlineSpu.getChoiceGroupId() != null) {
|
||||
if (canteenOnlineSpu.getChoiceGroupId() != null
|
||||
&& !Objects.equals(canteenOnlineSpu.getSpuType(), 2)) {
|
||||
CanteenOnlineSpuChoiceGroupEntity g = canteenOnlineSpuChoiceGroupService.getById(canteenOnlineSpu.getChoiceGroupId());
|
||||
if (g == null) {
|
||||
return R.failed("择一分组不存在(可能是前端 long 精度丢失导致 id 被圆整),请重新选择分组");
|
||||
}
|
||||
}
|
||||
return R.ok(canteenOnlineSpuService.updateById(canteenOnlineSpu));
|
||||
try {
|
||||
return R.ok(canteenOnlineSpuService.updateDeep(canteenOnlineSpu));
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
return R.failed(ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -186,8 +203,14 @@ public class CanteenOnlineSpuController {
|
||||
@SysLog("通过id删除在线点餐spu")
|
||||
@DeleteMapping
|
||||
@PreAuthorize("@pms.hasPermission('canteen_canteenOnlineSpu_del')")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public R removeById(@RequestBody Long[] ids) {
|
||||
return R.ok(canteenOnlineSpuService.removeBatchByIds(CollUtil.toList(ids)));
|
||||
List<Long> idList = CollUtil.toList(ids);
|
||||
boolean ok = canteenOnlineSpuService.removeBatchByIds(idList);
|
||||
if (ok && CollUtil.isNotEmpty(idList)) {
|
||||
canteenOnlineSpuService.removeComboItemsByComboIds(idList);
|
||||
}
|
||||
return R.ok(ok);
|
||||
}
|
||||
|
||||
|
||||
@@ -244,7 +267,7 @@ public class CanteenOnlineSpuController {
|
||||
*/
|
||||
@ApiCryptoAes
|
||||
@GetMapping("/app/getCanteenSpuList")
|
||||
@Operation(summary = "获取在线点餐的菜品列表", description = "商户 id 必传;返回含 status、requiredChoice、choiceGroupId+choiceGroup(择一/组合规则)、soldOut")
|
||||
@Operation(summary = "获取在线点餐的菜品列表", description = "商户 id 必传;返回含 status、spuType、comboItems(套餐组成)、requiredChoice、choiceGroup、soldOut")
|
||||
public R<List<APPOnlineSpuVO>> getCanteenSpuList(
|
||||
@RequestParam(value = "categoryId", required = false) @Parameter(description = "分类 id,可选") String categoryId,
|
||||
@RequestParam(value = "merchantId") @Parameter(description = "商户 id,必填") String merchantId,
|
||||
@@ -262,16 +285,21 @@ public class CanteenOnlineSpuController {
|
||||
|
||||
@ApiCryptoAes
|
||||
@GetMapping("/app/getCanteenSpuDetails")
|
||||
@Operation(summary = "获取详情接口", description = "通过spu的id")
|
||||
@Operation(summary = "获取详情接口", description = "通过spu的id;套餐含 comboItems 组成")
|
||||
public R<APPOnlineSpuVO> getCanteenSpuDetails(@RequestParam(value = "id") Long id) {
|
||||
CanteenOnlineSpuEntity canteenOnlineSpuEntity = canteenOnlineSpuService.getById(id);
|
||||
// 走 getDetail,保证套餐组成从明细表装载
|
||||
CanteenOnlineSpuEntity canteenOnlineSpuEntity = canteenOnlineSpuService.getDetail(id);
|
||||
if (canteenOnlineSpuEntity == null) {
|
||||
return R.ok(null);
|
||||
}
|
||||
APPOnlineSpuVO bean = BeanUtils.toBean(canteenOnlineSpuEntity, APPOnlineSpuVO.class);
|
||||
if (bean != null && canteenOnlineSpuEntity != null) {
|
||||
Integer st = canteenOnlineSpuEntity.getStock();
|
||||
bean.setSoldOut(st == null || st <= 0);
|
||||
canteenOnlineSpuService.fillAppOnlineSpuChoiceGroups(Collections.singletonList(bean),
|
||||
Collections.singletonList(canteenOnlineSpuEntity));
|
||||
}
|
||||
Integer st = canteenOnlineSpuEntity.getStock();
|
||||
bean.setSoldOut(st == null || st <= 0);
|
||||
canteenOnlineSpuService.fillAppOnlineSpuChoiceGroups(Collections.singletonList(bean),
|
||||
Collections.singletonList(canteenOnlineSpuEntity));
|
||||
// BeanUtils 无法正确把 Entity 明细转到 App VO,统一用 fill 覆盖
|
||||
canteenOnlineSpuService.fillAppComboItems(Collections.singletonList(bean),
|
||||
Collections.singletonList(canteenOnlineSpuEntity));
|
||||
return R.ok(bean);
|
||||
}
|
||||
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package com.bsd.pjcloud.canteen.mapper;
|
||||
|
||||
import com.bsd.pjcloud.canteen.entity.CanteenOnlineComboItemEntity;
|
||||
import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface CanteenOnlineComboItemMapper extends PjcloudBaseMapper<CanteenOnlineComboItemEntity> {
|
||||
}
|
||||
+23
@@ -17,6 +17,29 @@ import java.util.List;
|
||||
|
||||
public interface CanteenOnlineSpuService extends IService<CanteenOnlineSpuEntity> {
|
||||
|
||||
/**
|
||||
* 详情(含套餐组成)
|
||||
*/
|
||||
CanteenOnlineSpuEntity getDetail(Long id);
|
||||
|
||||
/**
|
||||
* 新增(套餐时同步组成)
|
||||
*/
|
||||
Boolean saveDeep(CanteenOnlineSpuEntity entity);
|
||||
|
||||
/**
|
||||
* 修改(套餐时同步组成)
|
||||
*/
|
||||
Boolean updateDeep(CanteenOnlineSpuEntity entity);
|
||||
|
||||
/**
|
||||
* 为 App VO 批量填充套餐组成
|
||||
*/
|
||||
void fillAppComboItems(List<APPOnlineSpuVO> vos, List<CanteenOnlineSpuEntity> entities);
|
||||
|
||||
/** 删除套餐组成明细 */
|
||||
void removeComboItemsByComboIds(List<Long> comboIds);
|
||||
|
||||
/**
|
||||
* 模板选择线上菜品分页(简化数据,用于选择弹窗)
|
||||
*/
|
||||
|
||||
+238
-1
@@ -3,6 +3,7 @@ package com.bsd.pjcloud.canteen.service.impl;
|
||||
import com.baomidou.lock.annotation.Lock4j;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.bsd.pjcloud.canteen.dto.CanteenOnlineSpuShelfReqDTO;
|
||||
@@ -13,17 +14,20 @@ import com.bsd.pjcloud.canteen.dto.canteenonline.CanteenOnlineSpuSaveItemDto;
|
||||
import com.bsd.pjcloud.canteen.entity.CanteenCategoryEntity;
|
||||
import com.bsd.pjcloud.canteen.entity.CanteenDailyMenuEntity;
|
||||
import com.bsd.pjcloud.canteen.entity.CanteenOnlineCategoryEntity;
|
||||
import com.bsd.pjcloud.canteen.entity.CanteenOnlineComboItemEntity;
|
||||
import com.bsd.pjcloud.canteen.entity.CanteenOnlineSpuChoiceGroupEntity;
|
||||
import com.bsd.pjcloud.canteen.entity.CanteenOnlineSpuEntity;
|
||||
import com.bsd.pjcloud.canteen.mapper.CanteenCategoryMapper;
|
||||
import com.bsd.pjcloud.canteen.mapper.CanteenDailyMenuMapper;
|
||||
import com.bsd.pjcloud.canteen.mapper.CanteenOnlineCategoryMapper;
|
||||
import com.bsd.pjcloud.canteen.mapper.CanteenOnlineComboItemMapper;
|
||||
import com.bsd.pjcloud.canteen.mapper.CanteenOnlineSpuMapper;
|
||||
import com.bsd.pjcloud.canteen.service.CanteenOnlineSpuChoiceGroupService;
|
||||
import com.bsd.pjcloud.canteen.service.CanteenOnlineSpuService;
|
||||
import com.bsd.pjcloud.canteen.util.MealSegmentCategoryUtils;
|
||||
import com.bsd.pjcloud.canteen.vo.app.CanteenOnlineSpuAppVO;
|
||||
import com.bsd.pjcloud.canteen.vo.app.OnlineSpuChoiceGroupRuleVO;
|
||||
import com.bsd.pjcloud.canteen.vo.app.OnlineSpuComboItemVO;
|
||||
import com.bsd.pjcloud.canteen.vo.APPOnlineSpuVO;
|
||||
import com.bsd.pjcloud.canteen.vo.erp.CanteenOnlineSpuSimpleVO;
|
||||
import com.bsd.pjcloud.common.core.util.BeanUtils;
|
||||
@@ -37,8 +41,12 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
@@ -70,6 +78,214 @@ public class CanteenOnlineSpuServiceImpl extends ServiceImpl<CanteenOnlineSpuMap
|
||||
private final CanteenOnlineSpuMapper baseMapper;
|
||||
|
||||
private final CanteenOnlineSpuChoiceGroupService canteenOnlineSpuChoiceGroupService;
|
||||
|
||||
private final CanteenOnlineComboItemMapper comboItemMapper;
|
||||
|
||||
@Override
|
||||
public CanteenOnlineSpuEntity getDetail(Long id) {
|
||||
CanteenOnlineSpuEntity entity = baseMapper.selectById(id);
|
||||
if (entity == null) {
|
||||
return null;
|
||||
}
|
||||
if (entity.getSpuType() == null) {
|
||||
entity.setSpuType(1);
|
||||
}
|
||||
if (Objects.equals(entity.getSpuType(), 2)) {
|
||||
entity.setComboItems(loadComboItems(Collections.singletonList(id)).getOrDefault(id, Collections.emptyList()));
|
||||
}
|
||||
else {
|
||||
entity.setComboItems(Collections.emptyList());
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean saveDeep(CanteenOnlineSpuEntity entity) {
|
||||
normalizeSpuType(entity);
|
||||
validateCombo(entity, null);
|
||||
baseMapper.insert(entity);
|
||||
saveComboItems(entity.getId(), entity.getSpuType(), entity.getComboItems());
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean updateDeep(CanteenOnlineSpuEntity entity) {
|
||||
normalizeSpuType(entity);
|
||||
validateCombo(entity, entity.getId());
|
||||
baseMapper.updateById(entity);
|
||||
comboItemMapper.delete(Wrappers.<CanteenOnlineComboItemEntity>lambdaQuery()
|
||||
.eq(CanteenOnlineComboItemEntity::getComboSpuId, entity.getId()));
|
||||
saveComboItems(entity.getId(), entity.getSpuType(), entity.getComboItems());
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeComboItemsByComboIds(List<Long> comboIds) {
|
||||
if (CollUtil.isEmpty(comboIds)) {
|
||||
return;
|
||||
}
|
||||
comboItemMapper.delete(Wrappers.<CanteenOnlineComboItemEntity>lambdaQuery()
|
||||
.in(CanteenOnlineComboItemEntity::getComboSpuId, comboIds));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillAppComboItems(List<APPOnlineSpuVO> vos, List<CanteenOnlineSpuEntity> entities) {
|
||||
if (CollUtil.isEmpty(vos) || CollUtil.isEmpty(entities)) {
|
||||
return;
|
||||
}
|
||||
List<Long> comboIds = new ArrayList<>();
|
||||
for (CanteenOnlineSpuEntity e : entities) {
|
||||
if (resolveSpuType(e) == 2 && e.getId() != null) {
|
||||
comboIds.add(e.getId());
|
||||
}
|
||||
}
|
||||
Map<Long, List<CanteenOnlineComboItemEntity>> comboMap = loadComboItems(comboIds);
|
||||
for (int i = 0; i < vos.size() && i < entities.size(); i++) {
|
||||
CanteenOnlineSpuEntity entity = entities.get(i);
|
||||
int type = resolveSpuType(entity);
|
||||
vos.get(i).setSpuType(type);
|
||||
if (type == 2) {
|
||||
List<CanteenOnlineComboItemEntity> lines = comboMap.getOrDefault(entity.getId(), Collections.emptyList());
|
||||
// getDetail 已装载时直接用,避免 map 再查空
|
||||
if (CollUtil.isEmpty(lines) && CollUtil.isNotEmpty(entity.getComboItems())) {
|
||||
lines = entity.getComboItems();
|
||||
}
|
||||
vos.get(i).setComboItems(toAppComboVos(lines));
|
||||
}
|
||||
else {
|
||||
vos.get(i).setComboItems(Collections.emptyList());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int resolveSpuType(CanteenOnlineSpuEntity entity) {
|
||||
Integer type = entity.getSpuType();
|
||||
if (type == null) {
|
||||
return 1;
|
||||
}
|
||||
int v = type.intValue();
|
||||
return (v == 2) ? 2 : 1;
|
||||
}
|
||||
|
||||
private void normalizeSpuType(CanteenOnlineSpuEntity entity) {
|
||||
if (entity.getSpuType() == null || (entity.getSpuType() != 1 && entity.getSpuType() != 2)) {
|
||||
entity.setSpuType(1);
|
||||
}
|
||||
if (Objects.equals(entity.getSpuType(), 2)) {
|
||||
// 套餐不参与择一/单品必选
|
||||
entity.setRequiredChoice(0);
|
||||
entity.setChoiceGroupId(null);
|
||||
entity.setLinkSpuId(null);
|
||||
}
|
||||
else if (entity.getRequiredChoice() == null) {
|
||||
entity.setRequiredChoice(0);
|
||||
}
|
||||
}
|
||||
|
||||
private void validateCombo(CanteenOnlineSpuEntity entity, Long selfId) {
|
||||
if (!Objects.equals(entity.getSpuType(), 2)) {
|
||||
return;
|
||||
}
|
||||
List<CanteenOnlineComboItemEntity> items = entity.getComboItems();
|
||||
if (CollUtil.isEmpty(items) || items.stream().filter(i -> i.getChildSpuId() != null).count() < 2) {
|
||||
throw new IllegalArgumentException("套餐至少选择 2 个组成菜品");
|
||||
}
|
||||
Set<Long> childIds = new HashSet<>();
|
||||
for (CanteenOnlineComboItemEntity item : items) {
|
||||
if (item.getChildSpuId() == null) {
|
||||
continue;
|
||||
}
|
||||
if (!childIds.add(item.getChildSpuId())) {
|
||||
throw new IllegalArgumentException("套餐组成菜品不能重复");
|
||||
}
|
||||
if (selfId != null && Objects.equals(item.getChildSpuId(), selfId)) {
|
||||
throw new IllegalArgumentException("套餐不能包含自身");
|
||||
}
|
||||
}
|
||||
List<CanteenOnlineSpuEntity> children = baseMapper.selectBatchIds(childIds);
|
||||
if (children.size() != childIds.size()) {
|
||||
throw new IllegalArgumentException("套餐组成菜品不存在或已删除");
|
||||
}
|
||||
for (CanteenOnlineSpuEntity child : children) {
|
||||
if (entity.getMerchantId() != null && !Objects.equals(child.getMerchantId(), entity.getMerchantId())) {
|
||||
throw new IllegalArgumentException("套餐组成菜品必须属于同一商户:" + child.getName());
|
||||
}
|
||||
Integer childType = child.getSpuType() == null ? 1 : child.getSpuType();
|
||||
if (Objects.equals(childType, 2)) {
|
||||
throw new IllegalArgumentException("套餐组成不能再包含套餐:" + child.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void saveComboItems(Long comboSpuId, Integer spuType, List<CanteenOnlineComboItemEntity> items) {
|
||||
if (!Objects.equals(spuType, 2) || CollUtil.isEmpty(items)) {
|
||||
return;
|
||||
}
|
||||
int sort = 0;
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
for (CanteenOnlineComboItemEntity item : items) {
|
||||
if (item.getChildSpuId() == null) {
|
||||
continue;
|
||||
}
|
||||
CanteenOnlineComboItemEntity line = new CanteenOnlineComboItemEntity();
|
||||
line.setComboSpuId(comboSpuId);
|
||||
line.setChildSpuId(item.getChildSpuId());
|
||||
line.setQuantity(item.getQuantity() == null || item.getQuantity() < 1 ? 1 : item.getQuantity());
|
||||
line.setSortOrder(item.getSortOrder() != null ? item.getSortOrder() : sort++);
|
||||
line.setCreateTime(now);
|
||||
comboItemMapper.insert(line);
|
||||
}
|
||||
}
|
||||
|
||||
private Map<Long, List<CanteenOnlineComboItemEntity>> loadComboItems(List<Long> comboIds) {
|
||||
if (CollUtil.isEmpty(comboIds)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
List<CanteenOnlineComboItemEntity> lines = comboItemMapper.selectList(
|
||||
Wrappers.<CanteenOnlineComboItemEntity>lambdaQuery()
|
||||
.in(CanteenOnlineComboItemEntity::getComboSpuId, comboIds)
|
||||
.orderByAsc(CanteenOnlineComboItemEntity::getSortOrder)
|
||||
.orderByAsc(CanteenOnlineComboItemEntity::getId));
|
||||
if (CollUtil.isEmpty(lines)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
Set<Long> childIds = lines.stream().map(CanteenOnlineComboItemEntity::getChildSpuId)
|
||||
.filter(Objects::nonNull).collect(Collectors.toSet());
|
||||
Map<Long, CanteenOnlineSpuEntity> childMap = childIds.isEmpty() ? Collections.emptyMap()
|
||||
: baseMapper.selectBatchIds(childIds).stream()
|
||||
.collect(Collectors.toMap(CanteenOnlineSpuEntity::getId, c -> c, (a, b) -> a));
|
||||
for (CanteenOnlineComboItemEntity line : lines) {
|
||||
CanteenOnlineSpuEntity child = childMap.get(line.getChildSpuId());
|
||||
if (child != null) {
|
||||
line.setChildSpuName(child.getName());
|
||||
line.setChildSpuPicUrl(child.getPicUrl());
|
||||
line.setChildSpuPrice(child.getPrice());
|
||||
}
|
||||
}
|
||||
return lines.stream().collect(Collectors.groupingBy(CanteenOnlineComboItemEntity::getComboSpuId,
|
||||
LinkedHashMap::new, Collectors.toList()));
|
||||
}
|
||||
|
||||
private List<OnlineSpuComboItemVO> toAppComboVos(List<CanteenOnlineComboItemEntity> lines) {
|
||||
if (CollUtil.isEmpty(lines)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<OnlineSpuComboItemVO> list = new ArrayList<>(lines.size());
|
||||
for (CanteenOnlineComboItemEntity line : lines) {
|
||||
OnlineSpuComboItemVO vo = new OnlineSpuComboItemVO();
|
||||
vo.setChildSpuId(line.getChildSpuId());
|
||||
vo.setName(line.getChildSpuName());
|
||||
vo.setPicUrl(line.getChildSpuPicUrl());
|
||||
vo.setQuantity(line.getQuantity());
|
||||
vo.setSortOrder(line.getSortOrder());
|
||||
vo.setPrice(line.getChildSpuPrice());
|
||||
list.add(vo);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public R<List<APPOnlineSpuVO>> getCanteenOnlineSpuList(String categoryId, String merchantId, String time,
|
||||
Integer minPrice, Integer maxPrice, Integer status,
|
||||
@@ -137,6 +353,7 @@ public class CanteenOnlineSpuServiceImpl extends ServiceImpl<CanteenOnlineSpuMap
|
||||
bean.get(i).setSoldOut(st == null || st <= 0);
|
||||
}
|
||||
fillAppOnlineSpuChoiceGroups(bean, finallyCanteenSpuEntities);
|
||||
fillAppComboItems(bean, finallyCanteenSpuEntities);
|
||||
return R.ok(bean);
|
||||
|
||||
}
|
||||
@@ -412,9 +629,26 @@ public class CanteenOnlineSpuServiceImpl extends ServiceImpl<CanteenOnlineSpuMap
|
||||
LambdaQueryWrapper<CanteenOnlineSpuEntity> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.like(StrUtil.isNotBlank(canteenOnlineSpu.getName()), CanteenOnlineSpuEntity::getName, canteenOnlineSpu.getName())
|
||||
.eq(Objects.nonNull(canteenOnlineSpu.getCategoryId()), CanteenOnlineSpuEntity::getCategoryId, canteenOnlineSpu.getCategoryId())
|
||||
.eq(Objects.nonNull(canteenOnlineSpu.getMerchantId()), CanteenOnlineSpuEntity::getMerchantId, canteenOnlineSpu.getMerchantId())
|
||||
// 套餐组成只可选单品(spu_type 为空或 1)
|
||||
.and(w -> w.isNull(CanteenOnlineSpuEntity::getSpuType).or().eq(CanteenOnlineSpuEntity::getSpuType, 1))
|
||||
.eq(CanteenOnlineSpuEntity::getStatus, 0)
|
||||
.orderByAsc(CanteenOnlineSpuEntity::getSort).orderByDesc(CanteenOnlineSpuEntity::getId);
|
||||
Page<CanteenOnlineSpuEntity> pageData = baseMapper.selectPageByScope(page, wrapper, DataScope.of());
|
||||
List<CanteenOnlineSpuSimpleVO> voList = BeanUtils.toBean(pageData.getRecords(), CanteenOnlineSpuSimpleVO.class);
|
||||
List<CanteenOnlineSpuSimpleVO> voList = new ArrayList<>();
|
||||
if (CollUtil.isNotEmpty(pageData.getRecords())) {
|
||||
for (CanteenOnlineSpuEntity record : pageData.getRecords()) {
|
||||
CanteenOnlineSpuSimpleVO vo = new CanteenOnlineSpuSimpleVO();
|
||||
vo.setId(record.getId());
|
||||
vo.setName(record.getName());
|
||||
vo.setPicUrl(record.getPicUrl());
|
||||
vo.setPrice(record.getPrice());
|
||||
vo.setLinkSpuId(record.getLinkSpuId());
|
||||
vo.setRequiredChoice(record.getRequiredChoice());
|
||||
vo.setChoiceGroupId(record.getChoiceGroupId());
|
||||
voList.add(vo);
|
||||
}
|
||||
}
|
||||
Page<CanteenOnlineSpuSimpleVO> resultPage = new Page<>();
|
||||
resultPage.setRecords(voList);
|
||||
resultPage.setCurrent(pageData.getCurrent());
|
||||
@@ -432,6 +666,9 @@ public class CanteenOnlineSpuServiceImpl extends ServiceImpl<CanteenOnlineSpuMap
|
||||
if (CollUtil.isNotEmpty(records)) {
|
||||
// 为每条记录添加菜品类型标识
|
||||
records.forEach(record -> {
|
||||
if (record.getSpuType() == null) {
|
||||
record.setSpuType(1);
|
||||
}
|
||||
if (record.getLinkSpuId() == null) {
|
||||
record.setDishTypeName("常驻菜品");
|
||||
record.setDishType(1);
|
||||
|
||||
+1
@@ -13,6 +13,7 @@
|
||||
<result property="sliderPicUrls" column="slider_pic_urls"/>
|
||||
<result property="sort" column="sort"/>
|
||||
<result property="status" column="status"/>
|
||||
<result property="spuType" column="spu_type"/>
|
||||
<result property="requiredChoice" column="required_choice"/>
|
||||
<result property="choiceGroupId" column="choice_group_id"/>
|
||||
<result property="price" column="price"/>
|
||||
|
||||
@@ -78,11 +78,6 @@ public class UserDTO extends SysUser implements BaseIsIncludeTreeInterface {
|
||||
*/
|
||||
private String nameOrPhone;
|
||||
|
||||
/**
|
||||
* 用户id
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
private List<Long> userIds;
|
||||
|
||||
/**
|
||||
|
||||
+27
-28
@@ -444,6 +444,12 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
if (userId == null) {
|
||||
throw new RuntimeException("用户ID不能为空");
|
||||
}
|
||||
SysUser dbUser = this.getById(userId);
|
||||
if (dbUser == null) {
|
||||
throw new RuntimeException("用户不存在或用户ID无效,请刷新后重试");
|
||||
}
|
||||
// 以库中主键为准,避免前端 Long 精度丢失后 ne 条件排除失败
|
||||
userId = dbUser.getUserId();
|
||||
userDto.setUserId(userId);
|
||||
sysUserIdentityService.validateDto(userDto);
|
||||
// 更新用户表信息
|
||||
@@ -460,12 +466,12 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
|
||||
// 脱敏手机号不参与更新,避免把 138****1234 写回库
|
||||
if (StrUtil.isNotBlank(userDto.getPhone()) && userDto.getPhone().contains("*")) {
|
||||
SysUser dbUser = this.getById(userId);
|
||||
sysUser.setPhone(dbUser != null ? dbUser.getPhone() : null);
|
||||
sysUser.setPhone(dbUser.getPhone());
|
||||
}
|
||||
|
||||
// 判断用户username是否重复
|
||||
if (existUsername(userId, userDto.getUsername())) {
|
||||
// 用户名未变更则不校验;变更时排除自身
|
||||
if (!StrUtil.equals(dbUser.getUsername(), userDto.getUsername())
|
||||
&& existUsername(userId, userDto.getUsername())) {
|
||||
throw new RuntimeException("该用户名已存在");
|
||||
}
|
||||
// 判断手机号是否重复
|
||||
@@ -1214,48 +1220,41 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
return com.bsd.pjcloud.common.core.util.BeanUtils.toBean(sysUsers, SimpleUserListVO.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户名是否已被占用。
|
||||
* 编辑时必须传入正确的 userId,用 ne 排除自身;若 userId 因前端 Long 精度丢失而不等于库中值,
|
||||
* 会误把当前用户算作“他人占用”。调用方应先 getById 校验并回填真实主键。
|
||||
*/
|
||||
private boolean existUsername(Long userId, String username) {
|
||||
Long count = baseMapper.selectCount(new LambdaQueryWrapper<SysUser>()
|
||||
.eq(ObjectUtil.isNotEmpty(username), SysUser::getUsername, username)
|
||||
.ne(ObjectUtil.isNotEmpty(userId), SysUser::getUserId, userId)
|
||||
if (StrUtil.isBlank(username)) {
|
||||
return false;
|
||||
}
|
||||
Long count = baseMapper.selectCount(Wrappers.<SysUser>lambdaQuery()
|
||||
.eq(SysUser::getUsername, username.trim())
|
||||
.ne(userId != null, SysUser::getUserId, userId)
|
||||
);
|
||||
if (ObjectUtil.isNotEmpty(userId)) {
|
||||
return count >= 1;
|
||||
}
|
||||
return count > 0;
|
||||
return count != null && count > 0;
|
||||
}
|
||||
|
||||
private boolean existPhone(Long userId, String phone) {
|
||||
if (StrUtil.isBlank(phone) || phone.contains("*")) {
|
||||
return false;
|
||||
}
|
||||
Long count = baseMapper.selectCount(new LambdaQueryWrapper<SysUser>()
|
||||
Long count = baseMapper.selectCount(Wrappers.<SysUser>lambdaQuery()
|
||||
.eq(SysUser::getPhone, phone)
|
||||
.ne(ObjectUtil.isNotEmpty(userId), SysUser::getUserId, userId)
|
||||
.ne(userId != null, SysUser::getUserId, userId)
|
||||
);
|
||||
if (ObjectUtil.isNotEmpty(userId)) {
|
||||
return count >= 1;
|
||||
}
|
||||
return count > 0;
|
||||
return count != null && count > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* UserDTO 子类重复声明了 userId,Jackson 可能只写入父类字段,需兼容读取。
|
||||
* 读取更新用的用户ID(兼容历史请求体)。
|
||||
* 注意:UserDTO 曾重复声明 userId,可能导致 Jackson 只写入父类字段。
|
||||
*/
|
||||
private Long resolveUserIdForUpdate(UserDTO userDto) {
|
||||
if (userDto.getUserId() != null) {
|
||||
return userDto.getUserId();
|
||||
}
|
||||
try {
|
||||
java.lang.reflect.Field field = SysUser.class.getDeclaredField("userId");
|
||||
field.setAccessible(true);
|
||||
Object value = field.get(userDto);
|
||||
if (value instanceof Long) {
|
||||
return (Long) value;
|
||||
}
|
||||
} catch (ReflectiveOperationException ignored) {
|
||||
// ignore
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+1
@@ -32,6 +32,7 @@ public interface WalletManageMapper extends PjcloudBaseMapper<WalletManageEntity
|
||||
.eq(ObjectUtil.isNotEmpty(dto.getWalletTypeId()), WalletManageEntity::getWalletTypeId,
|
||||
dto.getWalletTypeId())
|
||||
.eq(ObjectUtil.isNotEmpty(dto.getIsFreeze()), WalletManageEntity::getIsFreeze, dto.getIsFreeze())
|
||||
.like(ObjectUtil.isNotEmpty(dto.getCardNumber()), WalletManageEntity::getCardNumber, dto.getCardNumber())
|
||||
.in(ObjectUtil.isNotEmpty(dto.getWalletIds()), WalletManageEntity::getId, dto.getWalletIds())
|
||||
.in(ObjectUtil.isNotEmpty(dto.getUserIds()), WalletManageEntity::getUserId, dto.getUserIds())
|
||||
.between(
|
||||
|
||||
Reference in new issue
Block a user