Files
biz_xfj_cloud/lib/common/models/api/hard_api_models.dart
T
dzc 9cc99deed7 feat:同时核销几笔订单
feat:人脸质量检测
2026-08-31 17:59:03 +08:00

1187 lines
30 KiB
Dart

import 'package:json_annotation/json_annotation.dart';
import 'package:pj_supermarket_cloud/common/index.dart';
part 'hard_api_models.g.dart';
/// 终端提交订单识别证据元数据和现场图片时共用的强类型请求。
@JsonSerializable(includeIfNull: false)
class OrderEvidenceRequest {
/// 创建一条与服务端证据位置协议一致的请求。
const OrderEvidenceRequest({
this.androidOrderCode,
this.orderId,
required this.evidenceType,
required this.evidenceRole,
required this.sequenceNo,
required this.userId,
this.faceSampleId,
this.referenceImageUrl,
this.referenceImageVersion,
this.similarity,
this.similarityThreshold,
required this.capturedAt,
this.imageHash,
this.imageSize,
this.imageWidth,
this.imageHeight,
this.status,
this.failureReason,
required this.appVersion,
});
/// 终端稳定订单号,用于服务端按设备对账现场创建的订单;预约核销证据允许为空。
final String? androidOrderCode;
/// 已由当前设备核销的服务端预约订单 ID;现场创建的订单证据允许为空。
final String? orderId;
/// 证据业务类型,使用 `OrderEvidenceType.code`。
final String evidenceType;
/// 图片角色,使用 `OrderEvidenceRole.code`。
final String evidenceRole;
/// 同一订单、类型和角色下从 0 开始的序号。
final int sequenceNo;
/// 识别用户主键,服务端会再次校验与订单用户一致。
final String userId;
/// 虹软样本编号;人脸证据必填,其他类型允许为空。
final String? faceSampleId;
/// 识别时记录的后台参考人脸地址,仅参考图角色提交。
final String? referenceImageUrl;
/// 识别时本地人脸快照对应的后台更新时间,用于识别相同地址上的内容替换。
final DateTime? referenceImageVersion;
/// 人脸比对相似度快照,范围 0 到 1。
final double? similarity;
/// 人脸比对成功阈值快照,范围 0 到 1。
final double? similarityThreshold;
/// 真正比对成功帧的终端采集时间。
final DateTime capturedAt;
/// 图片 SHA-256;现场图片必填,参考图内容未知时允许为空。
final String? imageHash;
/// 图片大小,单位字节。
final int? imageSize;
/// 图片宽度,单位像素。
final int? imageWidth;
/// 图片高度,单位像素。
final int? imageHeight;
/// 元数据提交目标状态,仅允许服务端协议的 PENDING 或 UNAVAILABLE。
final String? status;
/// 永久缺失的单行摘要,不得包含终端完整文件路径。
final String? failureReason;
/// 产生证据的终端应用版本快照。
final String appVersion;
/// 从 JSON 响应或测试夹具恢复请求对象。
factory OrderEvidenceRequest.fromJson(Map<String, dynamic> json) =>
_$OrderEvidenceRequestFromJson(json);
/// 转换为统一 Dio 可提交的 JSON 或 multipart 字段 Map。
Map<String, dynamic> toJson() => _$OrderEvidenceRequestToJson(this);
}
/// 服务端单条订单识别证据状态,用于终端对账和幂等恢复。
@JsonSerializable()
class ServiceOrderEvidenceImage {
/// 创建一条服务端证据状态快照。
const ServiceOrderEvidenceImage({
required this.id,
required this.evidenceType,
required this.evidenceRole,
required this.sequenceNo,
required this.status,
this.imageHash,
this.imageUrl,
this.failureReason,
});
/// 服务端证据记录主键。
@JsonKey(fromJson: JsonTool.anyToRequiredString)
final String id;
/// 服务端稳定证据类型编码。
final String evidenceType;
/// 服务端稳定图片角色编码。
final String evidenceRole;
/// 同一角色下的图片序号。
final int sequenceNo;
/// 服务端证据状态,取 PENDING、AVAILABLE 或 UNAVAILABLE。
final String status;
/// 服务端已登记的图片 SHA-256。
final String? imageHash;
/// PC 可访问的服务端证据图片地址。
final String? imageUrl;
/// 永久缺失或复制失败摘要。
final String? failureReason;
/// 从服务端 JSON 解析证据状态。
factory ServiceOrderEvidenceImage.fromJson(Map<String, dynamic> json) =>
_$ServiceOrderEvidenceImageFromJson(json);
/// 转换为测试或诊断使用的 JSON。
Map<String, dynamic> toJson() => _$ServiceOrderEvidenceImageToJson(this);
}
/// 按终端订单号对账返回的服务端订单和全部证据位置。
@JsonSerializable()
class ServiceOrderEvidenceResolve {
/// 创建一份服务端订单对账结果。
const ServiceOrderEvidenceResolve({
required this.orderId,
required this.orderStatus,
this.evidenceImages = const [],
});
/// 服务端订单主键。
@JsonKey(fromJson: JsonTool.anyToRequiredString)
final String orderId;
/// 服务端订单状态编码,只有已支付、已核销或退款订单允许继续补传。
final String orderStatus;
/// 服务端当前已登记的证据位置及状态。
final List<ServiceOrderEvidenceImage> evidenceImages;
/// 从统一响应中的 data 对象解析订单对账结果。
factory ServiceOrderEvidenceResolve.fromJson(Map<String, dynamic> json) =>
_$ServiceOrderEvidenceResolveFromJson(json);
/// 转换为测试或诊断使用的 JSON。
Map<String, dynamic> toJson() => _$ServiceOrderEvidenceResolveToJson(this);
}
/// 服务端提交元数据或上传现场图片后的幂等结果。
@JsonSerializable()
class ServiceOrderEvidenceUploadResult {
/// 创建一份服务端证据写入结果。
const ServiceOrderEvidenceUploadResult({
required this.evidenceId,
required this.orderId,
required this.status,
required this.uploaded,
required this.message,
this.imageUrl,
});
/// 服务端证据记录主键。
@JsonKey(fromJson: JsonTool.anyToRequiredString)
final String evidenceId;
/// 服务端订单主键。
@JsonKey(fromJson: JsonTool.anyToRequiredString)
final String orderId;
/// 服务端证据状态。
final String status;
/// 本次请求是否实际新写入文件;幂等重复成功时为 false。
final bool uploaded;
/// 面向任务日志的简短服务端处理结果。
final String message;
/// AVAILABLE 时的服务端证据图片地址。
final String? imageUrl;
/// 从统一响应中的 data 对象解析上传结果。
factory ServiceOrderEvidenceUploadResult.fromJson(
Map<String, dynamic> json,
) =>
_$ServiceOrderEvidenceUploadResultFromJson(json);
/// 转换为测试或诊断使用的 JSON。
Map<String, dynamic> toJson() =>
_$ServiceOrderEvidenceUploadResultToJson(this);
}
@JsonSerializable()
class ServiceHardware extends ServiceBase {
/// 编号
final String? id;
/// 设备名
final String? name;
/// 设备类型
final String? type;
/// 设备类型enum
final String? typeEnum;
/// 商户id
final String? merchantId;
/// 商户部门id
final String? merchantDeptId;
/// 硬件分组id
final String? hardGroupId;
/// 商户名
final String? merchantStr;
/// mq连接id
final String? mqClientId;
/// android唯一id
final String? uniqueCode;
/// 当前设备的topic
final String? mainTopic;
/// mq地址
final String? mqSocketAddress;
/// mq端口
final String? mqSocketPort;
/// mq用户名
final String? mqUsername;
/// mq密码
final String? mqPassword;
/// 同步次数版本
final int? mqSyncCount;
/// 人脸appId
final String? faceAppId;
/// 人脸sdkKey
final String? faceSdkKey;
/// 人脸activeKey
final String? faceActiveKey;
ServiceHardware({
this.id,
this.name,
this.type,
this.typeEnum,
this.merchantId,
this.merchantDeptId,
this.hardGroupId,
this.merchantStr,
this.mqClientId,
this.uniqueCode,
this.mainTopic,
this.mqSocketAddress,
this.mqSocketPort,
this.mqUsername,
this.mqPassword,
this.mqSyncCount,
this.faceAppId,
this.faceSdkKey,
this.faceActiveKey,
});
factory ServiceHardware.fromJson(Map<String, dynamic> json) =>
_$ServiceHardwareFromJson(json);
@override
Map<String, dynamic> toJson() => _$ServiceHardwareToJson(this);
}
@JsonSerializable()
class ServiceCar {
/// 编号
@JsonKey(fromJson: JsonTool.anyToString)
final String? id;
/// 父购物车id
@JsonKey(fromJson: JsonTool.anyToString)
final String? parentCarId;
/// 商品名
final String? productName;
/// 商品价格
final int? productPrice;
/// 商品id
@JsonKey(fromJson: JsonTool.anyToString)
final String? productId;
/// 数量
final int? productCount;
/// 商品性质,1 为按件商品,2 为称重商品。
final String? productNature;
/// 称重商品重量,单位沿用服务端购物车快照。
@JsonKey(fromJson: JsonTool.anyToNullableDouble)
final double? productWeight;
/// 总价(分),兼容服务端 Long 返回数字或字符串。
@JsonKey(
fromJson: JsonTool.anyToNullableInt,
toJson: JsonTool.intToString,
)
final int? totalPrice;
/// 商品图片
final String? productPic;
ServiceCar({
this.id,
this.parentCarId,
this.productName,
this.productPrice,
this.productId,
this.productCount,
this.productNature,
this.productWeight,
this.totalPrice,
this.productPic,
});
factory ServiceCar.fromJson(Map<String, dynamic> json) =>
_$ServiceCarFromJson(json);
Map<String, dynamic> toJson() => _$ServiceCarToJson(this);
}
@JsonSerializable()
class ServiceGenerateInvoice {
/// 图片
final String? pic;
/// 记录id
final String? historyId;
ServiceGenerateInvoice({
this.pic,
this.historyId,
});
factory ServiceGenerateInvoice.fromJson(Map<String, dynamic> json) =>
_$ServiceGenerateInvoiceFromJson(json);
Map<String, dynamic> toJson() => _$ServiceGenerateInvoiceToJson(this);
}
@JsonSerializable()
class ServiceQRCode {
/// 总id
@JsonKey(fromJson: JsonTool.intToString, toJson: JsonTool.stringToInt)
final String? id;
/// 子id
@JsonKey(fromJson: JsonTool.intToString, toJson: JsonTool.stringToInt)
final String? itemId;
/// 类型id 比如钱包类型
@JsonKey(fromJson: JsonTool.intToString, toJson: JsonTool.stringToInt)
final String? typeId;
/// 用户id
@JsonKey(fromJson: JsonTool.intToString, toJson: JsonTool.stringToInt)
final String? userId;
/// 订单类型
@JsonKey(
fromJson: JsonTool.stringToOrderType,
toJson: JsonTool.orderTypeToString,
)
final OrderType? orderType;
/// 支付类型
@JsonKey(
fromJson: JsonTool.stringToOrderPayType,
toJson: JsonTool.orderPayTypeToString,
)
final OrderPayType? payType;
/// 过期时间 -1 代表没有限制
final int? exceedTime;
/// 额外的用户信息
final String? extra;
ServiceQRCode({
this.id,
this.itemId,
this.typeId,
this.userId,
this.orderType,
this.payType,
this.exceedTime,
this.extra,
});
factory ServiceQRCode.fromJson(Map<String, dynamic> json) =>
_$ServiceQRCodeFromJson(json);
Map<String, dynamic> toJson() => _$ServiceQRCodeToJson(this);
}
@JsonSerializable()
class ServiceHardOrder {
/// 服务端订单主键。
@JsonKey(fromJson: JsonTool.anyToString)
final String? id;
/// 业务订单号。
final String? orderNo;
/// 用户id
@JsonKey(fromJson: JsonTool.anyToString)
final String? userId;
/// 用户名
final String? username;
/// 用户手机号
final String? userMobile;
/// 用户头像
final String? userAvatar;
/// 订单类型
final String? orderType;
/// 订单状态
final String? orderStatus;
/// 支付方式
final String? payType;
/// 钱包id
@JsonKey(fromJson: JsonTool.anyToString)
final String? walletId;
/// 用餐时段。
final String? hourType;
/// 预约用餐时段,旧预约订单可能只返回该字段。
final String? apptHourType;
/// 商品摘要。
final String? productDesc;
/// 用户所属部门。
final String? userDeptName;
/// 商品总价(分)。
@JsonKey(fromJson: JsonTool.anyToNullableInt)
final int? totalPrice;
/// 额外支付(分)。
@JsonKey(fromJson: JsonTool.anyToNullableInt)
final int? extraPrice;
/// 实际支付(分)。
@JsonKey(fromJson: JsonTool.anyToNullableInt)
final int? payPrice;
/// 终端订单号。
final String? androidOrderCode;
/// 下单时间。
final DateTime? createTime;
ServiceHardOrder({
this.id,
this.orderNo,
this.userId,
this.username,
this.userMobile,
this.userAvatar,
this.orderType,
this.orderStatus,
this.payType,
this.walletId,
this.hourType,
this.apptHourType,
this.productDesc,
this.userDeptName,
this.totalPrice,
this.extraPrice,
this.payPrice,
this.androidOrderCode,
this.createTime,
});
factory ServiceHardOrder.fromJson(Map<String, dynamic> json) =>
_$ServiceHardOrderFromJson(json);
Map<String, dynamic> toJson() => _$ServiceHardOrderToJson(this);
}
/// 当前终端预约核销记录的服务端查询参数。
@JsonSerializable(includeIfNull: false)
class VerificationRecordQueryRequest {
const VerificationRecordQueryRequest({
required this.hardId,
required this.startDate,
required this.endDate,
this.verificationType,
});
final int hardId;
final String startDate;
final String endDate;
final String? verificationType;
factory VerificationRecordQueryRequest.fromJson(Map<String, dynamic> json) =>
_$VerificationRecordQueryRequestFromJson(json);
Map<String, dynamic> toJson() => _$VerificationRecordQueryRequestToJson(this);
}
/// 核销记录只承载列表展示字段,不复用本地订单实体,避免混淆远端与本地状态。
@JsonSerializable()
class ServiceVerificationRecord {
const ServiceVerificationRecord({
required this.orderId,
required this.orderNo,
required this.verificationType,
required this.verificationTypeName,
required this.username,
required this.productDesc,
required this.payTypeName,
required this.totalPrice,
required this.verificationTime,
this.userDeptName,
});
/// 后端 Long 为避免跨端精度丢失可能序列化为字符串,终端同时兼容数字返回。
@JsonKey(fromJson: JsonTool.anyToInt)
final int orderId;
final String orderNo;
final String verificationType;
final String verificationTypeName;
final String username;
final String? userDeptName;
final String productDesc;
final String payTypeName;
/// 金额仍按整数分使用,同时兼容部分环境将数值序列化为字符串。
@JsonKey(fromJson: JsonTool.anyToInt)
final int totalPrice;
final DateTime verificationTime;
factory ServiceVerificationRecord.fromJson(Map<String, dynamic> json) =>
_$ServiceVerificationRecordFromJson(json);
Map<String, dynamic> toJson() => _$ServiceVerificationRecordToJson(this);
}
@JsonSerializable()
class ServiceVerificationRecordPage extends ServicePageBase {
ServiceVerificationRecordPage({this.records});
final List<ServiceVerificationRecord>? records;
factory ServiceVerificationRecordPage.fromJson(Map<String, dynamic> json) =>
_$ServiceVerificationRecordPageFromJson(json);
@override
Map<String, dynamic> toJson() => _$ServiceVerificationRecordPageToJson(this);
}
@JsonSerializable()
class ServiceOpenCard {
/// 用户名
String? username;
/// 用户手机号
String? mobile;
/// 用户头像
String? avatar;
/// 饭卡状态
String? cardStatus;
/// 编号
String? id;
/// 部门名
String? deptId;
/// 部门名
String? deptName;
/// 用户编号
String? userId;
/// 饭卡类型Id
String? walletTypeId;
/// 饭卡类型
String? walletTypeUniqueCode;
/// 饭卡图标
String? walletTypeIcon;
/// 用户卡号
String? cardNumber;
/// 钱包编号
String? walletId;
/// 是否激活
@JsonKey(fromJson: JsonTool.stringToBoolean, toJson: JsonTool.booleanToString)
bool? isActiveHardware;
ServiceOpenCard({
this.username,
this.mobile,
this.avatar,
this.cardStatus,
this.id,
this.deptId,
this.deptName,
this.userId,
this.walletTypeId,
this.walletTypeUniqueCode,
this.walletTypeIcon,
this.cardNumber,
this.walletId,
this.isActiveHardware,
});
factory ServiceOpenCard.fromJson(Map<String, dynamic> json) =>
_$ServiceOpenCardFromJson(json);
Map<String, dynamic> toJson() => _$ServiceOpenCardToJson(this);
}
@JsonSerializable()
class ServiceOpenCardPage extends ServicePageBase {
List<ServiceOpenCard>? records;
ServiceOpenCardPage({
this.records,
});
factory ServiceOpenCardPage.fromJson(Map<String, dynamic> json) =>
_$ServiceOpenCardPageFromJson(
json,
);
Map<String, dynamic> toJson() => _$ServiceOpenCardPageToJson(this);
}
@JsonSerializable()
class ServiceChartLatitude {
/// 早餐、中餐、晚餐
final List<ServiceChartLatitudeItem> dayTotal;
/// 每天的交易量
final List<ServiceChartLatitudeItem> weekTotal;
/// 每天的交易金额
final List<ServiceChartLatitudeItem> monthTotal;
/// 每周的交易量
final List<ServiceChartLatitudeItem> yearTotal;
/// 每周的交易量
final List<ServiceChartLatitudeItem> allTotal;
ServiceChartLatitude({
required this.dayTotal,
required this.weekTotal,
required this.monthTotal,
required this.yearTotal,
required this.allTotal,
});
factory ServiceChartLatitude.fromJson(Map<String, dynamic> json) =>
_$ServiceChartLatitudeFromJson(
json,
);
Map<String, dynamic> toJson() => _$ServiceChartLatitudeToJson(this);
}
@JsonSerializable()
class ServiceChartLatitudeItem {
/// 早餐、中餐、晚餐
final String? hourType;
/// 每月的交易量
final String? deptId;
/// 每月的交易量
final String? sum;
/// 每月的交易量
final String? count;
ServiceChartLatitudeItem({
this.hourType,
this.deptId,
this.sum,
this.count,
});
factory ServiceChartLatitudeItem.fromJson(Map<String, dynamic> json) =>
_$ServiceChartLatitudeItemFromJson(
json,
);
Map<String, dynamic> toJson() => _$ServiceChartLatitudeItemToJson(this);
}
@JsonSerializable()
class ServiceBroadcastToday {
/// 广播id
final String id;
/// 预定用户
final String userId;
/// 用户名
final String username;
/// 用户手机号
final String userMobile;
/// 硬件id
final String hardId;
/// mq主题
final String topic;
/// 业务类型
final String? bizType;
/// 关联业务编号
final String? bizId;
/// 预定标题
final String title;
/// 预定内容
final String content;
/// 当前广播次数
final int? broadcastCount;
/// 最大广播次数
final int? broadcastMaxCount;
/// 是否广播语音
@JsonKey(fromJson: JsonTool.stringToBoolean, toJson: JsonTool.booleanToString)
final bool isBroadcast;
/// 用餐时间段
final String? hourType;
/// 商品介绍
String productDesc;
/// 支付价格
int payPrice;
/// 创建时间
String createTime;
ServiceBroadcastToday({
required this.id,
required this.userId,
required this.username,
required this.userMobile,
required this.hardId,
required this.topic,
this.bizType,
this.bizId,
required this.title,
required this.content,
this.broadcastCount,
this.broadcastMaxCount,
required this.isBroadcast,
this.hourType,
required this.productDesc,
required this.payPrice,
required this.createTime,
});
factory ServiceBroadcastToday.fromJson(Map<String, dynamic> json) =>
_$ServiceBroadcastTodayFromJson(
json,
);
Map<String, dynamic> toJson() => _$ServiceBroadcastTodayToJson(this);
}
@JsonSerializable()
class ServiceBroadcastTodayPage extends ServicePageBase {
List<ServiceBroadcastToday>? records;
ServiceBroadcastTodayPage({
this.records,
});
factory ServiceBroadcastTodayPage.fromJson(Map<String, dynamic> json) =>
_$ServiceBroadcastTodayPageFromJson(
json,
);
Map<String, dynamic> toJson() => _$ServiceBroadcastTodayPageToJson(this);
}
@JsonSerializable()
class ServiceHardCreateHardQrCodeScanOrder {
/// 订单id
String orderId;
/// 订单id
String mchId;
/// 订单id
String qrCodeData;
ServiceHardCreateHardQrCodeScanOrder({
required this.orderId,
required this.mchId,
required this.qrCodeData,
});
factory ServiceHardCreateHardQrCodeScanOrder.fromJson(
Map<String, dynamic> json) =>
_$ServiceHardCreateHardQrCodeScanOrderFromJson(
json,
);
Map<String, dynamic> toJson() =>
_$ServiceHardCreateHardQrCodeScanOrderToJson(this);
}
/// 收银终端支付宝、微信聚合订单码创建结果。
///
/// 该模型只接收 `AGGREGATE_ORDER_PAY` HTTPS 收银地址,不承载自有钱包码或平台原生码。
@JsonSerializable()
class ServiceHardAggregateOrderCodePay {
/// Hardware 业务订单 ID,状态查询必须与 [aggregateNo] 一起提交。
final String orderId;
/// 当前终端绑定的收款商户 ID。
final String mchId;
/// Thirdparty 服务生成并持久化绑定到 Hardware 订单的聚合会话编号。
final String aggregateNo;
/// 支付宝和微信均可扫码访问的 HTTPS 聚合收银地址。
final String qrCode;
/// 二维码协议类型,服务端固定返回 `AGGREGATE_ORDER_PAY`。
final String qrCodeType;
/// 服务端确定的聚合二维码失效时间。
final DateTime expireTime;
/// 创建不可变的聚合订单码结果。
const ServiceHardAggregateOrderCodePay({
required this.orderId,
required this.mchId,
required this.aggregateNo,
required this.qrCode,
required this.qrCodeType,
required this.expireTime,
});
/// 将 Hardware 接口 JSON 转换为聚合订单码结果。
factory ServiceHardAggregateOrderCodePay.fromJson(
Map<String, dynamic> json,
) =>
_$ServiceHardAggregateOrderCodePayFromJson(json);
/// 将聚合订单码结果转换为 JSON,供测试和跨 Engine 消息核对使用。
Map<String, dynamic> toJson() =>
_$ServiceHardAggregateOrderCodePayToJson(this);
}
/// Hardware 聚合订单码状态查询结果。
///
/// [paySuccess] 为 `true` 时,服务端已在订单锁内完成 Hardware 订单和库存更新。
@JsonSerializable()
class ServiceHardAggregateOrderCodePayStatus {
/// Hardware 业务订单 ID。
final String orderId;
/// 与 Hardware 订单持久化绑定的聚合会话编号。
final String aggregateNo;
/// 聚合会话状态编码:10 等待、15 创建中、20 支付中、30 成功、40 关闭、50 过期、60 创建失败。
final String status;
/// 首个有效扫码选定的平台,尚未扫码时为空。
final String? selectedPlatform;
/// 支付宝或微信实际子订单号,尚未创建时为空。
final String? payNo;
/// 是否已经由支付平台确认成功并同步 Hardware 业务订单。
final bool paySuccess;
/// 聚合二维码服务端失效时间;已由本地成功态短路返回时允许为空。
final DateTime? expireTime;
/// Hardware 业务订单当前状态编码。
final String orderStatus;
/// 创建不可变的聚合支付状态。
const ServiceHardAggregateOrderCodePayStatus({
required this.orderId,
required this.aggregateNo,
required this.status,
this.selectedPlatform,
this.payNo,
required this.paySuccess,
this.expireTime,
required this.orderStatus,
});
/// 将 Hardware 接口 JSON 转换为聚合支付状态。
factory ServiceHardAggregateOrderCodePayStatus.fromJson(
Map<String, dynamic> json,
) =>
_$ServiceHardAggregateOrderCodePayStatusFromJson(json);
/// 将聚合支付状态转换为 JSON,供日志脱敏筛选和测试使用。
Map<String, dynamic> toJson() =>
_$ServiceHardAggregateOrderCodePayStatusToJson(this);
}
/// 终端本人预约菜单查询参数。
@JsonSerializable(includeIfNull: false)
class ReservationMenuQueryRequest {
const ReservationMenuQueryRequest({
required this.hardId,
required this.recognitionType,
required this.maskName,
this.cardNumber,
this.faceUserId,
});
/// 当前终端设备 ID。
final int hardId;
/// 本人识别方式,沿用后端 CARD、FACE 契约。
final String recognitionType;
/// 是否由服务端脱敏用户姓名。
final bool maskName;
/// 饭卡卡号,仅 CARD 识别时传递。
final String? cardNumber;
/// 人脸插件识别出的用户 ID,仅 FACE 识别时传递。
final int? faceUserId;
factory ReservationMenuQueryRequest.fromJson(Map<String, dynamic> json) =>
_$ReservationMenuQueryRequestFromJson(json);
Map<String, dynamic> toJson() => _$ReservationMenuQueryRequestToJson(this);
}
/// 终端识别本人后返回的预约菜单,姓名由服务端按终端配置决定是否脱敏。
@JsonSerializable(explicitToJson: true)
class ServiceReservationMenuQuery {
/// 服务端按终端配置返回的用户姓名;字段名保留用于兼容既有协议。
final String maskedName;
/// 用户所属部门名称。
final String? deptName;
/// 当前终端绑定的食堂名称。
final String merchantName;
/// 查询结果中包含预约的日期数量。
final int totalDayCount;
/// 查询结果中包含预约的餐段数量。
final int totalMealCount;
/// 按预约日期升序排列的菜单列表。
final List<ServiceReservationDay> days;
const ServiceReservationMenuQuery({
required this.maskedName,
this.deptName,
required this.merchantName,
required this.totalDayCount,
required this.totalMealCount,
required this.days,
});
factory ServiceReservationMenuQuery.fromJson(Map<String, dynamic> json) =>
_$ServiceReservationMenuQueryFromJson(json);
Map<String, dynamic> toJson() => _$ServiceReservationMenuQueryToJson(this);
}
@JsonSerializable(explicitToJson: true)
class ServiceReservationDay {
/// 预约用餐日期,格式为 yyyy-MM-dd。
final String date;
/// 当天按餐段顺序排列的预约菜单。
final List<ServiceReservationMeal> meals;
const ServiceReservationDay({
required this.date,
required this.meals,
});
factory ServiceReservationDay.fromJson(Map<String, dynamic> json) =>
_$ServiceReservationDayFromJson(json);
Map<String, dynamic> toJson() => _$ServiceReservationDayToJson(this);
}
@JsonSerializable(explicitToJson: true)
class ServiceReservationMeal {
/// 预约餐段编码,沿用硬件订单餐段契约。
final String hourType;
/// 预约餐段显示名称。
final String mealTitle;
/// 当前餐段所有预约订单的去重餐品汇总,用于兼容旧服务端和旧终端。
final List<String> items;
/// 当前餐段可核销的预约订单 ID 列表。
@JsonKey(fromJson: JsonTool.anyListToIntList)
final List<int> orderIds;
/// 当前餐段内每笔预约订单与餐品的明确对应关系。
final List<ServiceReservationOrder> orders;
const ServiceReservationMeal({
required this.hourType,
required this.mealTitle,
required this.items,
this.orderIds = const [],
this.orders = const [],
});
factory ServiceReservationMeal.fromJson(Map<String, dynamic> json) =>
_$ServiceReservationMealFromJson(json);
Map<String, dynamic> toJson() => _$ServiceReservationMealToJson(this);
}
/// 同一餐段内单笔预约与餐品的对应关系;旧服务端没有该字段时保持空列表。
@JsonSerializable(explicitToJson: true)
class ServiceReservationOrder {
/// 可核销的预约订单 ID。
@JsonKey(fromJson: JsonTool.anyToInt)
final int orderId;
/// 该笔预约订单实际购买的商品与数量明细。
final List<ServiceReservationOrderItem> items;
const ServiceReservationOrder({
required this.orderId,
required this.items,
});
factory ServiceReservationOrder.fromJson(Map<String, dynamic> json) =>
_$ServiceReservationOrderFromJson(json);
Map<String, dynamic> toJson() => _$ServiceReservationOrderToJson(this);
}
/// 单笔预约订单中的商品与购买数量。
@JsonSerializable(explicitToJson: true)
class ServiceReservationOrderItem {
/// 订单中的菜品库商品 SPU ID;旧服务端未返回时为空。
@JsonKey(fromJson: JsonTool.anyToNullableInt)
final int? productId;
/// 订单中的商品名称。
final String productName;
/// 订单中的商品图片地址。
final String? productPic;
/// 订单中的商品购买数量;历史异常数据缺失时允许为空。
final int? productCount;
/// 商品类型:1 为单品,2 为套餐;旧服务端缺失时按单品处理。
final int spuType;
/// 套餐内的组成菜品;单品或旧服务端返回时为空列表。
final List<ServiceReservationComboItem> comboItems;
/// 创建服务端预约订单商品;新字段均提供兼容旧服务端的默认值。
const ServiceReservationOrderItem({
this.productId,
required this.productName,
this.productPic,
this.productCount,
this.spuType = 1,
this.comboItems = const [],
});
/// 从预约菜单接口 JSON 创建订单商品。
factory ServiceReservationOrderItem.fromJson(Map<String, dynamic> json) =>
_$ServiceReservationOrderItemFromJson(json);
/// 将订单商品转换为可传输 JSON。
Map<String, dynamic> toJson() => _$ServiceReservationOrderItemToJson(this);
}
/// 预约订单中的套餐组成菜品,只承担服务端 JSON 与终端展示模型之间的传输。
@JsonSerializable()
class ServiceReservationComboItem {
/// 组成菜品 SPU ID;菜品已删除或历史数据缺失时为空。
@JsonKey(fromJson: JsonTool.anyToNullableInt)
final int? childSpuId;
/// 组成菜品名称;关联菜品缺失时为空。
final String? name;
/// 组成菜品封面地址;未配置时为空。
final String? picUrl;
/// 套餐内组成菜品的份数;异常或缺失时由页面兜底为 1。
final int? quantity;
/// 套餐组成显示顺序;缺失时按接口返回顺序保留。
final int? sortOrder;
/// 组成菜品展示单价,单位为分;缺失时不展示价格。
final int? price;
/// 创建服务端套餐组成传输模型,缺失字段保持为空并交由页面模型规范化。
const ServiceReservationComboItem({
this.childSpuId,
this.name,
this.picUrl,
this.quantity,
this.sortOrder,
this.price,
});
/// 从预约菜单接口 JSON 创建套餐组成。
factory ServiceReservationComboItem.fromJson(Map<String, dynamic> json) =>
_$ServiceReservationComboItemFromJson(json);
/// 将套餐组成转换为可传输 JSON。
Map<String, dynamic> toJson() => _$ServiceReservationComboItemToJson(this);
}