feat:钱包操作、被监护人操作消费消息提醒、增加消息模块

This commit is contained in:
dzc committed 2026-08-14 19:49:06 +08:00
1 parent 6e1af7c84d
commit f7ff135416
104 files changed
+6734 -88

No files matched your search

@@ -0,0 +1,70 @@
package com.bsd.pjcloud.hard.api.constant;
import cn.hutool.core.util.ObjectUtil;
import java.util.Arrays;
/**
* 订单购物车商品来源枚举。
* 枚举编码持久化到 {@code hard_parent_car.product_source},同时作为 App 商品详情路由协议,禁止随意改码。
*/
public enum HardProductSourceEnum {
/** 每日菜谱,购物车商品 ID 为 {@code canteen_spu.id},来源详情 ID 为 {@code canteen_daily_menu.id}。 */
CANTEEN_DAILY_MENU("CANTEEN_DAILY_MENU", "每日菜谱"),
/** 食堂在线商品,购物车商品 ID 和来源详情 ID 均为 {@code canteen_online_spu.id}。 */
CANTEEN_ONLINE_SPU("CANTEEN_ONLINE_SPU", "食堂在线商品"),
/** 食堂基础菜品,购物车商品 ID 和来源详情 ID 均为 {@code canteen_spu.id}。 */
CANTEEN_SPU("CANTEEN_SPU", "食堂基础菜品"),
/** 共富商城商品,购物车商品 ID 为 SKU ID,来源详情 ID 为商城商品 SPU ID。 */
MALL_PRODUCT("MALL_PRODUCT", "共富商城商品");
/** 持久化和跨端传输使用的稳定编码。 */
private final String type;
/** 商品来源中文说明,仅用于服务端展示和诊断。 */
private final String description;
/**
* 创建商品来源枚举值。
*
* @param type 持久化及跨端协议编码
* @param description 中文业务说明
*/
HardProductSourceEnum(String type, String description) {
this.type = type;
this.description = description;
}
/**
* 获取持久化和跨端传输使用的稳定编码。
*
* @return 商品来源编码
*/
public String getType() {
return type;
}
/**
* 获取商品来源中文说明。
*
* @return 商品来源说明
*/
public String getDescription() {
return description;
}
/**
* 按持久化编码解析商品来源,空值或未知编码返回 {@code null} 以兼容历史购物车。
*
* @param type 数据库或接口中的商品来源编码
* @return 匹配的商品来源;无法识别时返回 {@code null}
*/
public static HardProductSourceEnum valueOfByType(String type) {
if (ObjectUtil.isEmpty(type)) return null;
return Arrays.stream(values()).filter(value -> ObjectUtil.equals(value.getType(), type)).findFirst().orElse(null);
}
}
@@ -6,22 +6,37 @@ import lombok.Data;
import java.math.BigDecimal;
/**
* 创建购物车商品请求。
* 商品计价 ID 与详情来源 ID 分离,避免每日菜谱和商城 SKU 在订单详情中再次跨服务反查。
*/
@Data
public class HardCreateCarDto {
/** 父购物车 ID,由服务端创建分组购物车时回填,App 批量上传场景可为空。 */
@Schema(description = "父购物车id", requiredMode = Schema.RequiredMode.REQUIRED)
private Long parentCarId;
/** 当前商品计价和库存校验使用的 ID,具体数据表由购物车来源类型决定。 */
@Schema(description = "商品id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1034")
private Long productId;
/**
* 商品来源详情 ID,仅在商品 ID 不能直接用于详情页时由调用方提供。
* 新版 App 的每日菜谱传 {@code canteen_daily_menu.id};旧客户端未传时仍允许下单,但该订单不提供商品详情跳转。
* 其他来源由服务端根据已校验商品补齐,不信任客户端传值。
*/
@Schema(description = "商品来源详情ID")
private Long sourceProductId;
/** 商品计价性质,决定使用数量还是重量计算金额。 */
@Schema(description = "食堂性质", requiredMode = Schema.RequiredMode.REQUIRED, example = "20798")
private HardProductNatureEnum productNature;
// TODO 食堂特有
/** 按件商品数量;称重商品场景可为空。 */
@Schema(description = "数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20798")
private Integer productCount;
// TODO 超市特有
/** 称重商品重量,单位沿用现有超市和智能柜协议;按件商品场景可为空。 */
@Schema(description = "重量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20798")
private BigDecimal productWeight;
}
@@ -46,6 +46,14 @@ public class HardCarEntity extends Model<HardCarEntity> {
@Schema(description = "商品id")
private Long productId;
/**
* 商品来源详情 ID,由创建购物车时按父购物车商品来源固化。
* 每日菜谱对应 {@code canteen_daily_menu.id},食堂在线/基础菜品等于商品 ID,共富商城对应商品 SPU ID;
* 无法唯一识别的历史数据为空。
*/
@Schema(description = "商品来源详情ID")
private Long sourceProductId;
/**
* 商品名
*/
@@ -131,4 +139,4 @@ public class HardCarEntity extends Model<HardCarEntity> {
*/
@Schema(description = "租户ID")
private Long tenantId;
}
}
@@ -0,0 +1,86 @@
package com.bsd.pjcloud.hard.api.entity.order;
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.bsd.pjcloud.common.core.util.TenantTable;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* Hardware用餐核销业务消息Transactional Outbox,保存订单状态成功转换时的不可变展示快照。
*/
@Data
@TenantTable
@TableName("hard_message_outbox")
public class HardMessageOutboxEntity implements Serializable {
/** Outbox主键,由MyBatis-Plus雪花算法生成并用于稳定事件ID。 */
@TableId(type = IdType.ASSIGN_ID)
private Long id;
/** 固定消息事件编码,首期仅为MEAL_VERIFIED。 */
private String eventCode;
/** 被核销的Hardware预约订单ID。 */
private Long orderId;
/** 实际用餐用户ID,也是本人消息接收人。 */
private Long subjectUserId;
/** 订单实际所属商户ID。 */
private Long sourceMchId;
/** 核销发生时的商户名称快照,远程查询失败时允许为空。 */
private String sourceMchName;
/** 餐段、商品或套餐摘要快照,来源于订单商品描述。 */
private String mealName;
/** 订单由PAY成功转换到CANCEL的服务器时间。 */
private LocalDateTime occurredTime;
/** 处理状态,PENDING、PROCESSING、RETRY、SUCCESS或FAILED。 */
private String status;
/** 向Thirdparty提交的累计尝试次数,最多8次。 */
private Integer attemptCount;
/** 下次允许重试时间,非RETRY状态为空。 */
private LocalDateTime nextRetryTime;
/** Thirdparty幂等接收成功时间。 */
private LocalDateTime processedTime;
/** 最近一次脱敏失败摘要,不保存请求报文或设备凭证。 */
private String lastError;
/** 创建人,系统核销通常由公共填充器写入。 */
@TableField(fill = FieldFill.INSERT)
private String createBy;
/** Outbox创建时间,用于扫描和保留清理。 */
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
/** 最近修改人。 */
@TableField(fill = FieldFill.INSERT_UPDATE)
private String updateBy;
/** 最近修改时间,也用于处理中超时恢复。 */
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
/** 逻辑删除标记,0有效,1删除。 */
@TableLogic
@TableField(fill = FieldFill.INSERT)
private String delFlag;
/** 记录所属租户ID。 */
private Long tenantId;
}
@@ -51,6 +51,13 @@ public class HardParentCarEntity extends Model<HardParentCarEntity> {
@Schema(description = "硬件设备类型")
private String hardType;
/**
* 购物车商品来源类型,值来自 {@link com.bsd.pjcloud.hard.api.constant.HardProductSourceEnum}。
* 同一父购物车内的商品必须属于同一来源;历史或不支持详情跳转的购物车为空。
*/
@Schema(description = "购物车商品来源类型")
private String productSource;
/**
* 订单状态
*/
@@ -3,27 +3,42 @@ package com.bsd.pjcloud.hard.api.vo.order;
import com.bsd.pjcloud.hard.api.entity.order.HardCarEntity;
import lombok.Data;
/**
* 订单购物车展示对象,在持久化快照之外补充统计字段和 App 商品详情路由协议。
*/
@Data
public class HardCarVo extends HardCarEntity {
// 商品id【超市特有】
/** 超市商品 SPU ID,仅超市统计和展示场景赋值。 */
private Long spuId;
// 商品规格【超市特有】
/** 超市商品规格,仅超市商品存在规格时赋值。 */
private String spec;
// 商品规格【超市特有】
/** 超市商品单位,仅超市商品存在单位时赋值。 */
private String unit;
// 商品数量【统计使用】
/** 商品数量汇总值,仅统计查询赋值。 */
private Long count;
// 购买次数【统计使用】
/** 商品购买次数汇总值,仅统计查询赋值。 */
private Long payCount;
// 统计使用
/** 统计结果所属商户 ID,不作为购物车持久化字段。 */
private Long merchantId;
/** 统计结果所属商户名称,不作为购物车持久化字段。 */
private String merchantName;
/**
* App 商品详情数据来源,值来自 {@link com.bsd.pjcloud.hard.api.constant.HardProductSourceEnum};
* 为空表示历史订单或当前商品类型没有可用详情页,调用方不得按 ID 猜测数据表。
*/
private String detailSource;
/**
* App 商品详情页使用的业务 ID,直接取创建购物车时固化的 {@link #getSourceProductId()}。
*/
private Long detailProductId;
}