From 905389467364a2b08a565f59033189735a18ab67 Mon Sep 17 00:00:00 2001 From: zjf <1799650030@qq.com> Date: Thu, 9 Apr 2026 18:20:03 +0800 Subject: [PATCH] =?UTF-8?q?=E8=8F=9C=E5=93=81=E5=BF=85=E7=82=B9=EF=BC=8C?= =?UTF-8?q?=E9=AA=91=E6=89=8B=E6=8E=A5=E5=8D=95=E6=9B=B4=E6=96=B0=E7=8A=B6?= =?UTF-8?q?=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feign/RemoteOnlineCanteenSpuService.java | 9 + .../CanteenOnlineSpuSaveItemDto.java | 9 + .../CanteenOnlineSpuChoiceGroupEntity.java | 93 ++++++++++ .../entity/CanteenOnlineSpuEntity.java | 12 ++ .../pjcloud/canteen/vo/APPOnlineSpuVO.java | 13 ++ .../canteen/vo/app/CanteenOnlineSpuAppVO.java | 12 ++ .../vo/app/OnlineSpuChoiceGroupRuleVO.java | 45 +++++ .../vo/app/OnlineSpuChoiceGroupsVO.java | 81 +++++++++ .../vo/erp/CanteenOnlineSpuSimpleVO.java | 6 + .../CanteenDeliveryOrderController.java | 6 +- ...CanteenOnlineSpuChoiceGroupController.java | 160 ++++++++++++++++++ .../CanteenOnlineSpuController.java | 109 +++++++++++- .../CanteenOnlineSpuChoiceGroupMapper.java | 9 + .../CanteenOnlineSpuChoiceGroupService.java | 15 ++ .../service/CanteenOnlineSpuService.java | 7 + .../impl/CanteenDeliveryOrderServiceImpl.java | 29 ++++ ...anteenOnlineSpuChoiceGroupServiceImpl.java | 28 +++ .../impl/CanteenOnlineSpuServiceImpl.java | 60 ++++++- .../mapper/CanteenOnlineSpuMapper.xml | 2 + .../impl/order/HardOrderServiceImpl.java | 11 ++ 20 files changed, 711 insertions(+), 5 deletions(-) create mode 100644 pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/entity/CanteenOnlineSpuChoiceGroupEntity.java create mode 100644 pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/vo/app/OnlineSpuChoiceGroupRuleVO.java create mode 100644 pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/vo/app/OnlineSpuChoiceGroupsVO.java create mode 100644 pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/controller/CanteenOnlineSpuChoiceGroupController.java create mode 100644 pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/mapper/CanteenOnlineSpuChoiceGroupMapper.java create mode 100644 pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/CanteenOnlineSpuChoiceGroupService.java create mode 100644 pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/impl/CanteenOnlineSpuChoiceGroupServiceImpl.java diff --git a/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/api/feign/RemoteOnlineCanteenSpuService.java b/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/api/feign/RemoteOnlineCanteenSpuService.java index 70d6a0a3..8a670743 100644 --- a/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/api/feign/RemoteOnlineCanteenSpuService.java +++ b/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/api/feign/RemoteOnlineCanteenSpuService.java @@ -24,6 +24,7 @@ import com.bsd.pjcloud.canteen.dto.CanteenSpuUpdateStockReqDTO; import com.bsd.pjcloud.canteen.entity.CanteenOnlineSpuEntity; import com.bsd.pjcloud.canteen.vo.APPOnlineSpuVO; import com.bsd.pjcloud.canteen.vo.app.CanteenOnlineSpuAppVO; +import com.bsd.pjcloud.canteen.vo.app.OnlineSpuChoiceGroupsVO; import com.bsd.pjcloud.common.core.constant.ServiceNameConstants; import com.bsd.pjcloud.common.core.util.R; import org.springframework.cloud.openfeign.FeignClient; @@ -51,6 +52,14 @@ public interface RemoteOnlineCanteenSpuService { R> getCanteenSpuList(@RequestParam(value = "categoryId", required = false) String categoryId, @RequestParam(value = "merchantId") String merchantId); + /** + * 下单前获取分组规则(聚合) + * + * @param merchantId 商户 id + */ + @GetMapping("/canteenOnlineSpu/app/getChoiceGroups") + R getChoiceGroups(@RequestParam(value = "merchantId") String merchantId); + /** diff --git a/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/dto/canteenonline/CanteenOnlineSpuSaveItemDto.java b/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/dto/canteenonline/CanteenOnlineSpuSaveItemDto.java index c0ff5cb2..c5ccae21 100644 --- a/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/dto/canteenonline/CanteenOnlineSpuSaveItemDto.java +++ b/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/dto/canteenonline/CanteenOnlineSpuSaveItemDto.java @@ -42,6 +42,15 @@ public class CanteenOnlineSpuSaveItemDto { @Schema(description="商品状态: 0 上架(默认/开启) 1 下架(禁用) -1 回收") private Integer status; + /** + * 是否必选:0 否 1 是 + */ + @Schema(description = "是否必选:0否 1是,默认 0") + private Integer requiredChoice; + + @Schema(description = "择一/组合分组 id,须已存在 canteen_online_spu_choice_group") + private Long choiceGroupId; + /** * 商品价格,单位使用:分 */ diff --git a/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/entity/CanteenOnlineSpuChoiceGroupEntity.java b/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/entity/CanteenOnlineSpuChoiceGroupEntity.java new file mode 100644 index 00000000..c8e0ffbf --- /dev/null +++ b/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/entity/CanteenOnlineSpuChoiceGroupEntity.java @@ -0,0 +1,93 @@ +package com.bsd.pjcloud.canteen.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import com.bsd.pjcloud.common.core.util.TenantTable; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.time.LocalDateTime; + +/** + * 在线点餐 SPU 择一/组合规则组(同组商品共享 min/max 规则) + */ +@Data +@TenantTable +@TableName("canteen_online_spu_choice_group") +@EqualsAndHashCode(callSuper = true) +@Schema(description = "在线点餐 SPU 择一/组合规则组") +public class CanteenOnlineSpuChoiceGroupEntity extends Model { + + @TableId(type = IdType.ASSIGN_ID) + @Schema(description = "主键") + private Long id; + + @Schema(description = "分组名称,如:主食、饮料") + @TableField("name") + private String name; + + @Schema(description = "商户 id") + @TableField("merchant_id") + private Long merchantId; + + @Schema(description = "部门 id") + @TableField("dept_id") + private Long deptId; + + /** + * 购物车内该组中「数量>0 的不同 SPU 种数」下限;0 表示整组可不选(与单品 required_choice 独立) + */ + @Schema(description = "至少几种 SPU 要有数量;0 表示整组可选") + @TableField("min_kinds") + private Integer minKinds; + + /** + * 至多几种;0 表示不限制种数上限 + */ + @Schema(description = "至多几种;0 表示不限制") + @TableField("max_kinds") + private Integer maxKinds; + + @Schema(description = "组内合计件数下限,0 不校验") + @TableField("min_total_qty") + private Integer minTotalQty; + + @Schema(description = "组内合计件数上限,0 不限制") + @TableField("max_total_qty") + private Integer maxTotalQty; + + @Schema(description = "排序") + @TableField("sort") + private Integer sort; + + @Schema(description = "创建人") + @TableField(value = "create_by", fill = FieldFill.INSERT) + private String createBy; + + @Schema(description = "创建时间") + @TableField(value = "create_time", fill = FieldFill.INSERT) + private LocalDateTime createTime; + + @Schema(description = "更新人") + @TableField(value = "update_by", fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + @Schema(description = "更新时间") + @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + @TableLogic + @Schema(description = "删除标记") + @TableField(value = "del_flag", fill = FieldFill.INSERT) + private String delFlag; + + @Schema(description = "租户") + @TableField("tenant_id") + private Long tenantId; +} diff --git a/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/entity/CanteenOnlineSpuEntity.java b/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/entity/CanteenOnlineSpuEntity.java index 18e9411d..becfb1df 100644 --- a/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/entity/CanteenOnlineSpuEntity.java +++ b/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/entity/CanteenOnlineSpuEntity.java @@ -83,6 +83,18 @@ public class CanteenOnlineSpuEntity extends Model { @Schema(description="商品状态: 0 上架(默认/开启) 1 下架(禁用) -1 回收") private Integer status; + /** + * 是否必选:0 否 1 是(前端下单需包含该品,如米饭) + */ + @Schema(description = "是否必选:0否 1是") + private Integer requiredChoice; + + /** + * 择一/组合分组 id,与同组 SPU 共享 {@link CanteenOnlineSpuChoiceGroupEntity} 规则;null 表示不按组校验 + */ + @Schema(description = "择一/组合分组 id,同组商品一起参与 minKinds/maxKinds 等校验") + private Long choiceGroupId; + /** * 商品价格,单位使用:分 */ diff --git a/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/vo/APPOnlineSpuVO.java b/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/vo/APPOnlineSpuVO.java index 7666994a..0ffeaede 100644 --- a/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/vo/APPOnlineSpuVO.java +++ b/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/vo/APPOnlineSpuVO.java @@ -1,5 +1,6 @@ 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; @@ -102,6 +103,18 @@ public class APPOnlineSpuVO { @Schema(description = "商品状态: 0 上架 1 下架") private Integer status; + /** + * 是否必选:0 否 1 是 + */ + @Schema(description = "是否必选:0否 1是") + private Integer requiredChoice; + + @Schema(description = "择一/组合分组 id,可与列表中同 id 的其它 SPU 归并展示;null 仅看 requiredChoice") + private Long choiceGroupId; + + @Schema(description = "分组规则(有 choiceGroupId 时由服务端填充,含 minKinds/maxKinds 等)") + private OnlineSpuChoiceGroupRuleVO choiceGroup; + /** * 是否售罄(库存为空或≤0) */ diff --git a/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/vo/app/CanteenOnlineSpuAppVO.java b/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/vo/app/CanteenOnlineSpuAppVO.java index c6447752..53385237 100644 --- a/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/vo/app/CanteenOnlineSpuAppVO.java +++ b/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/vo/app/CanteenOnlineSpuAppVO.java @@ -92,6 +92,18 @@ public class CanteenOnlineSpuAppVO { @Schema(description="库存") private Integer stock; + /** + * 是否必选:0 否 1 是 + */ + @Schema(description = "是否必选:0否 1是") + private Integer requiredChoice; + + @Schema(description = "择一/组合分组 id") + private Long choiceGroupId; + + @Schema(description = "分组规则") + private OnlineSpuChoiceGroupRuleVO choiceGroup; + /** * 赠送积分 */ diff --git a/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/vo/app/OnlineSpuChoiceGroupRuleVO.java b/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/vo/app/OnlineSpuChoiceGroupRuleVO.java new file mode 100644 index 00000000..f2ca9418 --- /dev/null +++ b/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/vo/app/OnlineSpuChoiceGroupRuleVO.java @@ -0,0 +1,45 @@ +package com.bsd.pjcloud.canteen.vo.app; + +import com.bsd.pjcloud.canteen.entity.CanteenOnlineSpuChoiceGroupEntity; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * App 端展示的分组规则(挂载在 SPU 上,同组 id 相同) + */ +@Data +@Schema(description = "择一/组合分组规则:同组 SPU 共享;校验见各字段说明") +public class OnlineSpuChoiceGroupRuleVO { + + @Schema(description = "分组 id") + private Long id; + + @Schema(description = "分组名称") + private String name; + + @Schema(description = "至少几种 SPU 要有数量;0 表示整组可选") + private Integer minKinds; + + @Schema(description = "至多几种;0 表示不限制") + private Integer maxKinds; + + @Schema(description = "组内合计件数下限,0 不校验") + private Integer minTotalQty; + + @Schema(description = "组内合计件数上限,0 不限制") + private Integer maxTotalQty; + + public static OnlineSpuChoiceGroupRuleVO fromEntity(CanteenOnlineSpuChoiceGroupEntity e) { + if (e == null) { + return null; + } + OnlineSpuChoiceGroupRuleVO v = new OnlineSpuChoiceGroupRuleVO(); + v.setId(e.getId()); + v.setName(e.getName()); + v.setMinKinds(e.getMinKinds()); + v.setMaxKinds(e.getMaxKinds()); + v.setMinTotalQty(e.getMinTotalQty()); + v.setMaxTotalQty(e.getMaxTotalQty()); + return v; + } +} diff --git a/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/vo/app/OnlineSpuChoiceGroupsVO.java b/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/vo/app/OnlineSpuChoiceGroupsVO.java new file mode 100644 index 00000000..0c3b4100 --- /dev/null +++ b/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/vo/app/OnlineSpuChoiceGroupsVO.java @@ -0,0 +1,81 @@ +package com.bsd.pjcloud.canteen.vo.app; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +/** + * 移动端下单前:在线点餐 SPU 的分组(择一/组合)聚合结构 + */ +@Data +@Schema(description = "在线点餐分组聚合(用于移动端必选/多选校验)") +public class OnlineSpuChoiceGroupsVO { + + @Schema(description = "商户 id") + @JsonSerialize(using = ToStringSerializer.class) + private Long merchantId; + + @Schema(description = "分组列表(choiceGroupId 维度聚合)") + private List groups; + + @Schema(description = "单品必选列表(requiredChoice=1 且不属于任何分组)") + private List requiredSpus; + + @Data + @Schema(description = "分组") + public static class Group { + @Schema(description = "分组 id") + @JsonSerialize(using = ToStringSerializer.class) + private Long groupId; + + @Schema(description = "分组名称") + private String groupName; + + @Schema(description = "是否必选组:true 表示该组需要满足 minSelect/minTotalQty 约束") + private Boolean required; + + @Schema(description = "至少选择几种 SPU(按种数计)") + private Integer minSelect; + + @Schema(description = "最多选择几种 SPU(0 表示不限制)") + private Integer maxSelect; + + @Schema(description = "组内合计件数下限(0 不校验)") + private Integer minTotalQty; + + @Schema(description = "组内合计件数上限(0 不限制)") + private Integer maxTotalQty; + + @Schema(description = "组内可选项(SPU 列表)") + private List items; + } + + @Data + @Schema(description = "分组内可选项(SPU)") + public static class Item { + @Schema(description = "spuId") + @JsonSerialize(using = ToStringSerializer.class) + private Long spuId; + + @Schema(description = "spuName") + private String spuName; + + @Schema(description = "价格(分)") + private Integer price; + } + + @Data + @Schema(description = "单品必选 SPU") + public static class RequiredSpu { + @Schema(description = "spuId") + @JsonSerialize(using = ToStringSerializer.class) + private Long spuId; + + @Schema(description = "spuName") + private String spuName; + } +} + diff --git a/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/vo/erp/CanteenOnlineSpuSimpleVO.java b/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/vo/erp/CanteenOnlineSpuSimpleVO.java index b4134314..b84a7783 100644 --- a/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/vo/erp/CanteenOnlineSpuSimpleVO.java +++ b/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/vo/erp/CanteenOnlineSpuSimpleVO.java @@ -18,4 +18,10 @@ public class CanteenOnlineSpuSimpleVO { @Schema(description = "关联线下菜品id") private Long linkSpuId; + + @Schema(description = "是否必选:0否 1是") + private Integer requiredChoice; + + @Schema(description = "择一/组合分组 id") + private Long choiceGroupId; } diff --git a/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/controller/CanteenDeliveryOrderController.java b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/controller/CanteenDeliveryOrderController.java index 543fbd12..2f8546d4 100644 --- a/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/controller/CanteenDeliveryOrderController.java +++ b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/controller/CanteenDeliveryOrderController.java @@ -84,14 +84,16 @@ public class CanteenDeliveryOrderController { @SysLog("取餐拍照") @PostMapping("/app/pickup") - @Operation(summary = "骑手端-到店取餐拍照") + @Operation(summary = "骑手端-到店取餐拍照", + description = "本地状态改为配送中后,会 Feign 调用硬件服务 POST /hard-order/update-take-out-status,status=TAKE_OUT_ING(sourceOrderId 即硬件订单 id)。") public R pickup(@Valid @RequestBody CanteenDeliveryPhotoDTO dto) { return canteenDeliveryOrderService.pickup(SecurityUtils.getUser().getId(), dto); } @SysLog("送达拍照") @PostMapping("/app/deliver") - @Operation(summary = "骑手端-送达拍照") + @Operation(summary = "骑手端-送达拍照", + description = "本地状态改为已完成后,会 Feign 调用硬件服务 POST /hard-order/update-take-out-status,status=DONE。") public R deliver(@Valid @RequestBody CanteenDeliveryPhotoDTO dto) { return canteenDeliveryOrderService.deliver(SecurityUtils.getUser().getId(), dto); } diff --git a/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/controller/CanteenOnlineSpuChoiceGroupController.java b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/controller/CanteenOnlineSpuChoiceGroupController.java new file mode 100644 index 00000000..6c5eb955 --- /dev/null +++ b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/controller/CanteenOnlineSpuChoiceGroupController.java @@ -0,0 +1,160 @@ +package com.bsd.pjcloud.canteen.controller; + +import cn.hutool.core.collection.CollUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.bsd.pjcloud.canteen.entity.CanteenOnlineSpuChoiceGroupEntity; +import com.bsd.pjcloud.canteen.service.CanteenOnlineSpuChoiceGroupService; +import com.bsd.pjcloud.common.core.util.R; +import com.bsd.pjcloud.common.core.constant.enums.MerchantTypeEnum; +import com.bsd.pjcloud.common.log.annotation.SysLog; +import com.bsd.pjcloud.common.security.util.SecurityUtils; +import com.bsd.pjcloud.wallet.api.feign.RemoteMchService; +import com.bsd.pjcloud.wallet.api.vo.MchManageVo; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpHeaders; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 在线点餐 SPU 择一/组合规则组(管理端维护,SPU 上填 choiceGroupId 关联) + */ +@RestController +@RequiredArgsConstructor +@RequestMapping("/canteenOnlineSpuChoiceGroup") +@Tag(name = "在线点餐择一/组合分组", description = "minKinds/maxKinds 控制几种 SPU;minTotalQty/maxTotalQty 控制件数") +@SecurityRequirement(name = HttpHeaders.AUTHORIZATION) +public class CanteenOnlineSpuChoiceGroupController { + + private final CanteenOnlineSpuChoiceGroupService choiceGroupService; + private final RemoteMchService remoteMchService; + + @GetMapping("/page") + @Operation(summary = "分页查询分组", description = "走数据权限 selectPageByScope;merchantId 不传则按数据权限返回可见范围内的全部分组,传了则按商户筛选") + @PreAuthorize("@pms.hasPermission('canteen_canteenOnlineSpu_view')") + public R> page(@RequestParam(required = false) Long merchantId, + @RequestParam(required = false) String name, + Page page) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); + wrapper.eq(merchantId != null, CanteenOnlineSpuChoiceGroupEntity::getMerchantId, merchantId) + .like(name != null && !name.trim().isEmpty(), CanteenOnlineSpuChoiceGroupEntity::getName, name.trim()) + .orderByAsc(CanteenOnlineSpuChoiceGroupEntity::getSort) + .orderByDesc(CanteenOnlineSpuChoiceGroupEntity::getId); + return R.ok(choiceGroupService.pageByScope(page, wrapper)); + } + + @GetMapping("/list") + @Operation(summary = "列出分组", description = "merchantId 不传则默认当前登录单位对应的食堂商户") + @PreAuthorize("@pms.hasPermission('canteen_canteenOnlineSpu_view')") + public R> list(@RequestParam(required = false) Long merchantId) { + MchManageVo mch = resolveMchOrNull(merchantId); + if (mch == null) { + return R.failed("商户不存在"); + } + List list = choiceGroupService.listByScope( + Wrappers.lambdaQuery() + .eq(CanteenOnlineSpuChoiceGroupEntity::getMerchantId, mch.getId()) + .orderByAsc(CanteenOnlineSpuChoiceGroupEntity::getSort) + .orderByDesc(CanteenOnlineSpuChoiceGroupEntity::getId)); + return R.ok(list); + } + + @Operation(summary = "新增分组") + @SysLog("新增在线点餐择一分组") + @PostMapping + @PreAuthorize("@pms.hasPermission('canteen_canteenOnlineSpu_add')") + public R save(@RequestBody CanteenOnlineSpuChoiceGroupEntity body) { + MchManageVo mch = resolveMchOrNull(body.getMerchantId()); + if (mch == null) { + return R.failed("商户不存在"); + } + String err = validate(body); + if (err != null) { + return R.failed(err); + } + normalizeDefaults(body); + body.setMerchantId(mch.getId()); + // deptId 用商户绑定的部门,便于按部门做数据权限隔离 + body.setDeptId(mch.getDeptId()); + return R.ok(choiceGroupService.save(body)); + } + + @Operation(summary = "修改分组") + @SysLog("修改在线点餐择一分组") + @PutMapping + @PreAuthorize("@pms.hasPermission('canteen_canteenOnlineSpu_edit')") + public R update(@RequestBody CanteenOnlineSpuChoiceGroupEntity body) { + MchManageVo mch = resolveMchOrNull(body.getMerchantId()); + if (mch == null) { + return R.failed("商户不存在"); + } + String err = validate(body); + if (err != null) { + return R.failed(err); + } + normalizeDefaults(body); + body.setMerchantId(mch.getId()); + body.setDeptId(mch.getDeptId()); + return R.ok(choiceGroupService.updateById(body)); + } + + @Operation(summary = "删除分组") + @SysLog("删除在线点餐择一分组") + @DeleteMapping + @PreAuthorize("@pms.hasPermission('canteen_canteenOnlineSpu_del')") + public R remove(@RequestBody Long[] ids) { + return R.ok(choiceGroupService.removeBatchByIds(CollUtil.toList(ids))); + } + + private static void normalizeDefaults(CanteenOnlineSpuChoiceGroupEntity e) { + if (e.getMinKinds() == null) { + e.setMinKinds(0); + } + if (e.getMaxKinds() == null) { + e.setMaxKinds(0); + } + if (e.getMinTotalQty() == null) { + e.setMinTotalQty(0); + } + if (e.getMaxTotalQty() == null) { + e.setMaxTotalQty(0); + } + if (e.getSort() == null) { + e.setSort(0); + } + } + + private static String validate(CanteenOnlineSpuChoiceGroupEntity e) { + int minK = e.getMinKinds() == null ? 0 : e.getMinKinds(); + int maxK = e.getMaxKinds() == null ? 0 : e.getMaxKinds(); + if (maxK > 0 && minK > maxK) { + return "maxKinds 不能小于 minKinds"; + } + int minQ = e.getMinTotalQty() == null ? 0 : e.getMinTotalQty(); + int maxQ = e.getMaxTotalQty() == null ? 0 : e.getMaxTotalQty(); + if (maxQ > 0 && minQ > maxQ) { + return "maxTotalQty 不能小于 minTotalQty"; + } + return null; + } + + private MchManageVo resolveMchOrNull(Long merchantId) { + R resp; + if (merchantId != null) { + resp = remoteMchService.getById(merchantId); + } else { + Long deptId = SecurityUtils.getUser().getDeptId(); + resp = remoteMchService.getByDeptId(deptId, MerchantTypeEnum.CANTEEN); + } + if (resp == null || !resp.isOk() || resp.getData() == null) { + return null; + } + return resp.getData(); + } +} diff --git a/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/controller/CanteenOnlineSpuController.java b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/controller/CanteenOnlineSpuController.java index 4a580d15..978b2b81 100644 --- a/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/controller/CanteenOnlineSpuController.java +++ b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/controller/CanteenOnlineSpuController.java @@ -12,10 +12,14 @@ import com.bsd.pjcloud.canteen.dto.canteenonline.CanteenOnlineSpuSaveDto; import com.bsd.pjcloud.canteen.vo.APPOnlineSpuVO; import com.bsd.pjcloud.canteen.vo.app.CanteenOnlineSpuAppVO; import com.bsd.pjcloud.canteen.vo.app.MchSimpleAppVO; +import com.bsd.pjcloud.canteen.vo.app.OnlineSpuChoiceGroupsVO; +import com.bsd.pjcloud.canteen.vo.app.OnlineSpuChoiceGroupRuleVO; import com.bsd.pjcloud.common.core.util.BeanUtils; import com.bsd.pjcloud.common.core.util.R; import com.bsd.pjcloud.common.log.annotation.SysLog; import com.bsd.pjcloud.canteen.entity.CanteenOnlineSpuEntity; +import com.bsd.pjcloud.canteen.entity.CanteenOnlineSpuChoiceGroupEntity; +import com.bsd.pjcloud.canteen.service.CanteenOnlineSpuChoiceGroupService; import com.bsd.pjcloud.canteen.service.CanteenOnlineSpuService; import com.bsd.pjcloud.common.security.util.SecurityUtils; import com.bsd.pjcloud.common.core.constant.enums.MerchantTypeEnum; @@ -33,8 +37,11 @@ import lombok.RequiredArgsConstructor; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; +import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Objects; +import java.util.stream.Collectors; /** * 在线点餐spu @@ -50,6 +57,7 @@ import java.util.Objects; public class CanteenOnlineSpuController { private final CanteenOnlineSpuService canteenOnlineSpuService; + private final CanteenOnlineSpuChoiceGroupService canteenOnlineSpuChoiceGroupService; private final RemoteMchService remoteMchService; /** @@ -125,6 +133,12 @@ public class CanteenOnlineSpuController { @PostMapping @PreAuthorize("@pms.hasPermission('canteen_canteenOnlineSpu_add')") public R save(@RequestBody CanteenOnlineSpuEntity canteenOnlineSpu) { + if (canteenOnlineSpu.getChoiceGroupId() != null) { + 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)); } @@ -148,6 +162,12 @@ public class CanteenOnlineSpuController { @PutMapping @PreAuthorize("@pms.hasPermission('canteen_canteenOnlineSpu_edit')") public R updateById(@RequestBody CanteenOnlineSpuEntity canteenOnlineSpu) { + if (canteenOnlineSpu.getChoiceGroupId() != null) { + CanteenOnlineSpuChoiceGroupEntity g = canteenOnlineSpuChoiceGroupService.getById(canteenOnlineSpu.getChoiceGroupId()); + if (g == null) { + return R.failed("择一分组不存在(可能是前端 long 精度丢失导致 id 被圆整),请重新选择分组"); + } + } return R.ok(canteenOnlineSpuService.updateById(canteenOnlineSpu)); } @@ -217,7 +237,7 @@ public class CanteenOnlineSpuController { * @param priceOrder 按价格排序:asc 升序 desc 降序,不传则按 sort、id */ @GetMapping("/app/getCanteenSpuList") - @Operation(summary = "获取在线点餐的菜品列表", description = "商户 id 必传;支持价格区间、上架状态、是否售罄筛选及按价格排序;返回含 status、soldOut") + @Operation(summary = "获取在线点餐的菜品列表", description = "商户 id 必传;返回含 status、requiredChoice、choiceGroupId+choiceGroup(择一/组合规则)、soldOut") public R> getCanteenSpuList( @RequestParam(value = "categoryId", required = false) @Parameter(description = "分类 id,可选") String categoryId, @RequestParam(value = "merchantId") @Parameter(description = "商户 id,必填") String merchantId, @@ -240,10 +260,92 @@ public class CanteenOnlineSpuController { if (bean != null && canteenOnlineSpuEntity != null) { Integer st = canteenOnlineSpuEntity.getStock(); bean.setSoldOut(st == null || st <= 0); + canteenOnlineSpuService.fillAppOnlineSpuChoiceGroups(Collections.singletonList(bean), + Collections.singletonList(canteenOnlineSpuEntity)); } return R.ok(bean); } + @GetMapping("/app/getChoiceGroups") + @Operation(summary = "下单前获取分组规则(聚合)", + description = "按 choiceGroupId 聚合组内 SPU 列表;并返回 requiredChoice=1 且未进组的单品必选列表。") + public R getChoiceGroups(@RequestParam("merchantId") Long merchantId, + @RequestParam(value = "status", required = false) Integer status) { + if (status == null) { + status = 0; + } + LambdaQueryWrapper w = Wrappers.lambdaQuery(); + w.eq(CanteenOnlineSpuEntity::getMerchantId, merchantId); + // 默认仅返回上架菜,避免下单规则里混入下架项 + w.eq(CanteenOnlineSpuEntity::getStatus, status); + w.orderByAsc(CanteenOnlineSpuEntity::getSort).orderByDesc(CanteenOnlineSpuEntity::getId); + List spus = canteenOnlineSpuService.list(w); + + // 1) requiredChoice=1 且未进组 + List requiredSpus = spus.stream() + .filter(s -> Objects.equals(s.getRequiredChoice(), 1) && s.getChoiceGroupId() == null) + .map(s -> { + OnlineSpuChoiceGroupsVO.RequiredSpu r = new OnlineSpuChoiceGroupsVO.RequiredSpu(); + r.setSpuId(s.getId()); + r.setSpuName(s.getName()); + return r; + }).collect(Collectors.toList()); + + // 2) 分组聚合:choiceGroupId -> items + Map> byGroup = spus.stream() + .filter(s -> s.getChoiceGroupId() != null) + .collect(Collectors.groupingBy(CanteenOnlineSpuEntity::getChoiceGroupId)); + + // 3) 加载分组规则:直接按 groupId 查分组表,避免间接映射导致规则丢失 + final Map ruleMap; + if (CollUtil.isEmpty(byGroup)) { + ruleMap = Collections.emptyMap(); + } else { + List groups = canteenOnlineSpuChoiceGroupService.listByIds(byGroup.keySet()); + ruleMap = CollUtil.isEmpty(groups) + ? Collections.emptyMap() + : groups.stream().collect(Collectors.toMap(CanteenOnlineSpuChoiceGroupEntity::getId, OnlineSpuChoiceGroupRuleVO::fromEntity, (a, b) -> a)); + } + + List groups = byGroup.entrySet().stream() + .map(e -> { + Long gid = e.getKey(); + OnlineSpuChoiceGroupRuleVO rule = ruleMap.get(gid); + OnlineSpuChoiceGroupsVO.Group g = new OnlineSpuChoiceGroupsVO.Group(); + g.setGroupId(gid); + g.setGroupName(rule != null ? rule.getName() : null); + Integer min = rule != null ? rule.getMinKinds() : 0; + Integer minQty = rule != null ? rule.getMinTotalQty() : 0; + g.setRequired((min != null && min > 0) || (minQty != null && minQty > 0)); + g.setMinSelect(rule != null ? rule.getMinKinds() : 0); + g.setMaxSelect(rule != null ? rule.getMaxKinds() : 0); + g.setMinTotalQty(rule != null ? rule.getMinTotalQty() : 0); + g.setMaxTotalQty(rule != null ? rule.getMaxTotalQty() : 0); + List items = e.getValue().stream().map(s -> { + OnlineSpuChoiceGroupsVO.Item it = new OnlineSpuChoiceGroupsVO.Item(); + it.setSpuId(s.getId()); + it.setSpuName(s.getName()); + it.setPrice(s.getPrice()); + return it; + }).collect(Collectors.toList()); + g.setItems(items); + return g; + }) + .sorted((a, b) -> { + if (a.getGroupId() == null && b.getGroupId() == null) return 0; + if (a.getGroupId() == null) return 1; + if (b.getGroupId() == null) return -1; + return a.getGroupId().compareTo(b.getGroupId()); + }) + .collect(Collectors.toList()); + + OnlineSpuChoiceGroupsVO vo = new OnlineSpuChoiceGroupsVO(); + vo.setMerchantId(merchantId); + vo.setGroups(groups); + vo.setRequiredSpus(requiredSpus); + return R.ok(vo); + } + @GetMapping("/app/checkSpuStock") @SysLog("购物车效验库存") @@ -310,7 +412,10 @@ public class CanteenOnlineSpuController { // @PreAuthorize("@pms.hasPermission('canteen_canteenSpu_view')") public R> getByIds(@RequestBody List ids) { List list = canteenOnlineSpuService.list(new LambdaQueryWrapper().in(CanteenOnlineSpuEntity::getId, ids)); - List canteenOnlineSpuAppVOS = BeanUtils.toBean(list, CanteenOnlineSpuAppVO.class); + Map byId = list.stream().collect(Collectors.toMap(CanteenOnlineSpuEntity::getId, e -> e, (a, b) -> a)); + List ordered = ids.stream().map(byId::get).filter(Objects::nonNull).collect(Collectors.toList()); + List canteenOnlineSpuAppVOS = BeanUtils.toBean(ordered, CanteenOnlineSpuAppVO.class); + canteenOnlineSpuService.fillOnlineSpuAppChoiceGroups(canteenOnlineSpuAppVOS, ordered); return R.ok(canteenOnlineSpuAppVOS); } diff --git a/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/mapper/CanteenOnlineSpuChoiceGroupMapper.java b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/mapper/CanteenOnlineSpuChoiceGroupMapper.java new file mode 100644 index 00000000..5a8e0755 --- /dev/null +++ b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/mapper/CanteenOnlineSpuChoiceGroupMapper.java @@ -0,0 +1,9 @@ +package com.bsd.pjcloud.canteen.mapper; + +import com.bsd.pjcloud.canteen.entity.CanteenOnlineSpuChoiceGroupEntity; +import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface CanteenOnlineSpuChoiceGroupMapper extends PjcloudBaseMapper { +} diff --git a/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/CanteenOnlineSpuChoiceGroupService.java b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/CanteenOnlineSpuChoiceGroupService.java new file mode 100644 index 00000000..54ce00a5 --- /dev/null +++ b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/CanteenOnlineSpuChoiceGroupService.java @@ -0,0 +1,15 @@ +package com.bsd.pjcloud.canteen.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.bsd.pjcloud.canteen.entity.CanteenOnlineSpuChoiceGroupEntity; + +import java.util.List; + +public interface CanteenOnlineSpuChoiceGroupService extends IService { + + List listByScope(LambdaQueryWrapper wrapper); + + Page pageByScope(Page page, LambdaQueryWrapper wrapper); +} diff --git a/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/CanteenOnlineSpuService.java b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/CanteenOnlineSpuService.java index bc3f71b6..c68a86e4 100644 --- a/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/CanteenOnlineSpuService.java +++ b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/CanteenOnlineSpuService.java @@ -8,6 +8,7 @@ import com.bsd.pjcloud.canteen.dto.CanteenOnlineSpuUpdateStockReqDTO; import com.bsd.pjcloud.canteen.dto.canteenonline.CanteenOnlineSpuSaveDto; import com.bsd.pjcloud.canteen.entity.CanteenOnlineSpuEntity; import com.bsd.pjcloud.canteen.vo.APPOnlineSpuVO; +import com.bsd.pjcloud.canteen.vo.app.CanteenOnlineSpuAppVO; import com.bsd.pjcloud.canteen.vo.erp.CanteenOnlineSpuSimpleVO; import com.bsd.pjcloud.common.core.util.R; @@ -37,6 +38,12 @@ public interface CanteenOnlineSpuService extends IService vos, List entities); + + void fillOnlineSpuAppChoiceGroups(List vos, List entities); /** * 修改商品库存 diff --git a/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/impl/CanteenDeliveryOrderServiceImpl.java b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/impl/CanteenDeliveryOrderServiceImpl.java index 9d317edd..b1a8bd4b 100644 --- a/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/impl/CanteenDeliveryOrderServiceImpl.java +++ b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/impl/CanteenDeliveryOrderServiceImpl.java @@ -26,6 +26,8 @@ import com.bsd.pjcloud.canteen.service.CanteenDeliveryOrderService; import com.bsd.pjcloud.canteen.vo.app.CanteenDeliveryOrderAppVO; import com.bsd.pjcloud.common.core.util.BeanUtils; import com.bsd.pjcloud.common.core.util.R; +import com.bsd.pjcloud.hard.api.dto.order.remote.HardUpdateTakeOutStatusDto; +import com.bsd.pjcloud.hard.api.feign.RemoteHardOrderService; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; @@ -51,6 +53,7 @@ public class CanteenDeliveryOrderServiceImpl extends ServiceImpl r = remoteHardOrderService.updateTakeOutStatus(dto); + if (r == null || !r.isOk() || !Boolean.TRUE.equals(r.getData())) { + String msg = r == null ? "无响应" : r.getMsg(); + throw new IllegalStateException("同步硬件外卖订单状态失败: " + msg); + } + } } diff --git a/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/impl/CanteenOnlineSpuChoiceGroupServiceImpl.java b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/impl/CanteenOnlineSpuChoiceGroupServiceImpl.java new file mode 100644 index 00000000..ee692d44 --- /dev/null +++ b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/impl/CanteenOnlineSpuChoiceGroupServiceImpl.java @@ -0,0 +1,28 @@ +package com.bsd.pjcloud.canteen.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.bsd.pjcloud.canteen.entity.CanteenOnlineSpuChoiceGroupEntity; +import com.bsd.pjcloud.canteen.mapper.CanteenOnlineSpuChoiceGroupMapper; +import com.bsd.pjcloud.canteen.service.CanteenOnlineSpuChoiceGroupService; +import com.bsd.pjcloud.common.data.datascope.DataScope; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class CanteenOnlineSpuChoiceGroupServiceImpl + extends ServiceImpl + implements CanteenOnlineSpuChoiceGroupService { + + @Override + public List listByScope(LambdaQueryWrapper wrapper) { + return baseMapper.selectListByScope(wrapper, DataScope.of()); + } + + @Override + public Page pageByScope(Page page, LambdaQueryWrapper wrapper) { + return baseMapper.selectPageByScope(page, wrapper, DataScope.of()); + } +} diff --git a/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/impl/CanteenOnlineSpuServiceImpl.java b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/impl/CanteenOnlineSpuServiceImpl.java index 9fedc8a2..fd56fb7e 100644 --- a/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/impl/CanteenOnlineSpuServiceImpl.java +++ b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/impl/CanteenOnlineSpuServiceImpl.java @@ -11,12 +11,16 @@ 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.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.CanteenOnlineSpuMapper; +import com.bsd.pjcloud.canteen.service.CanteenOnlineSpuChoiceGroupService; import com.bsd.pjcloud.canteen.service.CanteenOnlineSpuService; +import com.bsd.pjcloud.canteen.vo.app.CanteenOnlineSpuAppVO; +import com.bsd.pjcloud.canteen.vo.app.OnlineSpuChoiceGroupRuleVO; import com.bsd.pjcloud.canteen.vo.APPOnlineSpuVO; import com.bsd.pjcloud.canteen.vo.erp.CanteenOnlineSpuSimpleVO; import com.bsd.pjcloud.common.core.util.BeanUtils; @@ -30,11 +34,12 @@ import org.springframework.transaction.annotation.Transactional; import java.time.LocalDate; import java.time.format.DateTimeFormatter; +import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; -import java.util.Objects; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; @@ -55,6 +60,8 @@ public class CanteenOnlineSpuServiceImpl extends ServiceImpl> getCanteenOnlineSpuList(String categoryId, String merchantId, String time, Integer minPrice, Integer maxPrice, Integer status, @@ -109,10 +116,50 @@ public class CanteenOnlineSpuServiceImpl extends ServiceImpl vos, List entities) { + if (CollUtil.isEmpty(vos) || CollUtil.isEmpty(entities) || vos.size() != entities.size()) { + return; + } + Map ruleMap = loadChoiceGroupRuleMap( + entities.stream().map(CanteenOnlineSpuEntity::getChoiceGroupId).filter(Objects::nonNull).collect(Collectors.toSet())); + for (int i = 0; i < vos.size(); i++) { + Long gid = entities.get(i).getChoiceGroupId(); + vos.get(i).setChoiceGroupId(gid); + vos.get(i).setChoiceGroup(gid == null ? null : ruleMap.get(gid)); + } + } + + @Override + public void fillOnlineSpuAppChoiceGroups(List vos, List entities) { + if (CollUtil.isEmpty(vos) || CollUtil.isEmpty(entities) || vos.size() != entities.size()) { + return; + } + Map ruleMap = loadChoiceGroupRuleMap( + entities.stream().map(CanteenOnlineSpuEntity::getChoiceGroupId).filter(Objects::nonNull).collect(Collectors.toSet())); + for (int i = 0; i < vos.size(); i++) { + Long gid = entities.get(i).getChoiceGroupId(); + vos.get(i).setChoiceGroupId(gid); + vos.get(i).setChoiceGroup(gid == null ? null : ruleMap.get(gid)); + } + } + + private Map loadChoiceGroupRuleMap(Set groupIds) { + if (CollUtil.isEmpty(groupIds)) { + return Collections.emptyMap(); + } + List groups = canteenOnlineSpuChoiceGroupService.listByIds(groupIds); + if (CollUtil.isEmpty(groups)) { + return Collections.emptyMap(); + } + return groups.stream().collect(Collectors.toMap(CanteenOnlineSpuChoiceGroupEntity::getId, OnlineSpuChoiceGroupRuleVO::fromEntity)); + } + @Override public R updateOnlineSpuSkuStock(CanteenOnlineSpuUpdateStockReqDTO canteenOnlineSpuUpdateStockReqDTO) { // 下单等场景:库存与销量联动(incrCount<0 视为售出) @@ -208,7 +255,18 @@ public class CanteenOnlineSpuServiceImpl extends ServiceImpl c)); Long deptId = SecurityUtils.getUser().getDeptId(); + for (CanteenOnlineSpuEntity c : canteenSpuEntities) { + if (c.getChoiceGroupId() != null) { + CanteenOnlineSpuChoiceGroupEntity g = canteenOnlineSpuChoiceGroupService.getById(c.getChoiceGroupId()); + if (g == null || !Objects.equals(g.getMerchantId(), merchantId)) { + return R.failed("择一分组不存在或不属于当前商户:" + StrUtil.blankToDefault(c.getName(), String.valueOf(c.getChoiceGroupId()))); + } + } + } canteenSpuEntities.forEach(c -> { + if (c.getRequiredChoice() == null) { + c.setRequiredChoice(0); + } CanteenCategoryEntity canteenCategoryEntity = canteenCategoryEntityMap.get(c.getCategoryId()); if (canteenCategoryEntity != null) { String name = canteenCategoryEntity.getName(); diff --git a/pjcloud-canteen/pjcloud-canteen-biz/src/main/resources/mapper/CanteenOnlineSpuMapper.xml b/pjcloud-canteen/pjcloud-canteen-biz/src/main/resources/mapper/CanteenOnlineSpuMapper.xml index d3d1fce6..620a4880 100644 --- a/pjcloud-canteen/pjcloud-canteen-biz/src/main/resources/mapper/CanteenOnlineSpuMapper.xml +++ b/pjcloud-canteen/pjcloud-canteen-biz/src/main/resources/mapper/CanteenOnlineSpuMapper.xml @@ -13,6 +13,8 @@ + + diff --git a/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/service/impl/order/HardOrderServiceImpl.java b/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/service/impl/order/HardOrderServiceImpl.java index 7aec07e3..9ba5381e 100644 --- a/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/service/impl/order/HardOrderServiceImpl.java +++ b/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/service/impl/order/HardOrderServiceImpl.java @@ -22,6 +22,7 @@ import com.bsd.pjcloud.canteen.api.feign.RemoteOnlineCanteenSpuService; import com.bsd.pjcloud.canteen.dto.CanteenSpuUpdateStockReqDTO; import com.bsd.pjcloud.canteen.dto.delivery.CanteenDeliveryCartItemDTO; import com.bsd.pjcloud.canteen.dto.delivery.CanteenDeliveryOrderSyncDTO; +import com.bsd.pjcloud.canteen.vo.app.OnlineSpuChoiceGroupsVO; import com.bsd.pjcloud.common.core.constant.CacheConstants; import com.bsd.pjcloud.common.core.constant.CommonConstants; import com.bsd.pjcloud.common.core.constant.CommonRoleConstant; @@ -147,6 +148,7 @@ public class HardOrderServiceImpl extends ServiceImpl choiceGroups = remoteOnlineCanteenSpuService.getChoiceGroups(String.valueOf(parentCar.getMerchantId())); + if (!choiceGroups.isOk()){ + throw new RuntimeException("未选择必选菜品"); + } + // 查询商户 MchManageVo hardManager = remoteMchService.getById(parentCar.getMerchantId()).getData(); if (ObjectUtil.isEmpty(hardManager)) throw new RuntimeException("商户不存在"); // 查询父购物车 List carList = hardCarService.getByParentCarId(dto.getCarParentId()); if (ObjectUtil.isEmpty(carList)) throw new RuntimeException("购物车不存在"); + Integer balance = wallet.getBalance(); int carPrice = (int) carList.stream().mapToLong(HardCarEntity::getTotalPrice).sum(); int totalPrice = carPrice;