拆单:一个用户订单如果涉及多个供应商,系统自动拆成多个子订单,每个子订单对应一个供应商。并单:结算周期结束时,将同一代理商多个小额子单合并为一张结算单,减少对账和打款工作量。
数据模型
-- orders 表新增字段
ALTER TABLE orders ADD COLUMN parent_order_id BIGINT REFERENCES orders(id);
ALTER TABLE orders ADD COLUMN split_sequence SMALLINT DEFAULT 0;
CREATE TABLE consolidation (
id SERIAL PRIMARY KEY,
agent_id BIGINT NOT NULL,
period_start DATE NOT NULL,
period_end DATE NOT NULL,
order_ids BIGINT[] NOT NULL,
total_amount DECIMAL(12, 2) NOT NULL,
currency VARCHAR(3) DEFAULT 'CNY',
status VARCHAR(16) DEFAULT 'pending', -- pending / confirmed / settled
created_at TIMESTAMPTZ DEFAULT NOW()
);
接口设计
POST /api/orders/{id}/split # 手动触发拆单(通常由系统自动触发)
GET /api/orders/{id}/sub-orders # 查询子订单列表
POST /api/settlement/consolidate # 触发并单结算
GET /api/settlement/consolidations # 并单结算列表
业务逻辑
下单时,系统根据匹配结果判断涉及的供应商数量,若 >1 则自动拆单,生成一个 parent_order_id 关联的子订单组。结算周期结束时,定时任务汇总同一代理商的已完成订单,按供应商维度生成并单记录。
支持按渠道、供应商、酒店、房型粒度配置取消政策。政策类型包括:免费取消(限期前免费)、有条件取消(逾期收取罚金)、不可取消(全额罚金)。下单时返回适用的取消政策,用户取消时自动计算罚金。
数据模型
id SERIAL PRIMARY KEY,
supplier_id BIGINT,
channel_id BIGINT,
hotel_id BIGINT,
room_type_id BIGINT,
policy_type VARCHAR(24) NOT NULL, -- free / conditional / non_refundable
free_cancel_before INT, -- 入住前 N 小时可免费取消(NULL=不允许免费取消)
penalty_type VARCHAR(16), -- percentage / fixed_night / fixed_amount
penalty_value DECIMAL(10, 2),
effective_from DATE NOT NULL,
effective_to DATE NOT NULL,
priority SMALLINT DEFAULT 0,
created_at TIMESTAMPTZ DEFAULT NOW()
);
**接口设计**
```yaml
GET /api/orders/{id}/cancellation-policy # 获取订单适用的取消政策
POST /api/orders/{id}/cancel # 提交取消请求
GET /api/admin/cancellation-policies # 管理端查看所有政策
POST /api/admin/cancellation-policies # 创建取消政策
业务逻辑
查价/下单时,根据酒店、房型、渠道匹配优先级最高的取消政策并返回给代理商。用户发起取消时,系统根据当前时间与入住时间的差值和 free_cancel_before 判断是否免罚,否则按 penalty_type 和 penalty_value 计算罚金。
不同供应商可能要求信用卡担保(入住时扣款)或预付全款(下单时扣款)。查价时返回支付要求,下单时根据规则执行对应支付流程。
数据模型
CREATE TABLE payment_rule (
id SERIAL PRIMARY KEY,
supplier_id BIGINT NOT NULL,
channel_id BIGINT,
hotel_id BIGINT,
payment_type VARCHAR(16) NOT NULL, -- guarantee / prepay / postpay
guarantee_amount DECIMAL(10, 2), -- 担保金额(NULL=全额担保)
prepay_days INT, -- 提前 N 天预付(NULL=立即预付)
payment_methods JSONB, -- 支持的支付方式,如 ["credit_card", "bank_transfer"]
effective_from DATE NOT NULL,
effective_to DATE NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW()
);
接口设计
GET /api/orders/{id}/payment-requirement # 获取订单支付要求
POST /api/payments # 发起支付
GET /api/payments/{id} # 查询支付状态
GET /api/admin/payment-rules # 管理端查看支付规则
业务逻辑
查价时,根据供应商和渠道匹配支付规则,在报价结果中附加 payment_type、guarantee_amount 等信息。下单流程中,若规则为 prepay,则在订单创建后跳转支付网关;若为 guarantee,则验证信用卡信息后确认订单。
下单后若在规定时间内未确认或未支付,系统自动取消订单并释放已占用的库存。超时时长按渠道和供应商维度可配置。
数据模型
-- orders 表新增字段
ALTER TABLE orders ADD COLUMN confirmed_at TIMESTAMPTZ;
ALTER TABLE orders ADD COLUMN paid_at TIMESTAMPTZ;
CREATE TABLE order_timeout_config (
id SERIAL PRIMARY KEY,
channel_id BIGINT,
supplier_id BIGINT,
confirm_timeout_min INT NOT NULL DEFAULT 30, -- 确认超时(分钟)
payment_timeout_min INT NOT NULL DEFAULT 60, -- 支付超时(分钟)
created_at TIMESTAMPTZ DEFAULT NOW()
);
接口设计
GET /api/admin/order-timeout-configs # 查看超时配置列表
POST /api/admin/order-timeout-configs # 创建/更新配置
GET /api/admin/orders/expiring # 即将超时的订单列表
业务逻辑
定时任务每分钟扫描 orders 表中 status = 'pending' 且 created_at 超过 confirm_timeout_min 的订单,以及 status = 'confirmed' 且 confirmed_at 超过 payment_timeout_min 的订单,自动将状态改为 cancelled_timeout,释放 Redis 中对应的库存占位。