酒店-餐厅对账功能
status: in-progress
created: 2026-09-30
complexity: ⭐⭐⭐中等
需求依据:用户口述 + 需求汇总讨论(2026-09-30)
1. 背景与目标
1.1 业务背景
酒店与餐厅为独立法人实体(同一老板、不同公司),属于合作关系。顾客在酒店房间扫码点餐,钱付给酒店(通过支付宝等渠道)。酒店需要按月与餐厅对账,确认应付金额后付款给餐厅。
1.2 目标
- 酒店端按月自动生成对账单,汇总该月顾客点餐订单
- 退款订单单独标注,系统提供「排除」能力(排除后自动重算应付金额)
- 餐厅端可查看、确认对账单
- 双方均可导出 Excel
- 对账单状态流转:待确认 → 已确认 → 已结算
1.3 不做的事
- ❌ 不实现平台抽成/服务费计算(暂不扣除)
- ❌ 不实现线上签字/电子签章
- ❌ 不按餐厅维度拆分(目前只有一个餐厅)
- ❌ 不改动现有订单模块逻辑
2. 多租户架构(方案一:受控跨租户)
对账单数据归属酒店租户,餐厅通过后端受控跨租户访问。
酒店端(tenant_id = A):
生成对账单 / 排除订单 / 标记结算 / 导出
→ 正常操作,TenantLine 自动追加 tenant_id = A
餐厅端(tenant_id = B):
查看对账单 / 确认 / 导出
→ 后端 TenantContextHolder.executeWithTenant(A, ...) 切到酒店租户
→ 仅暴露对账相关接口,不暴露订单/支付等其他数据
安全边界:
- 餐厅角色仅配
hotel:reconciliation:partner:* 权限
- 餐厅仅能访问
/hotel/reconciliation/partner/** 专用接口
- 跨租户接口内部写死只查对账相关表
3. 功能点
3.1 酒店端
| # |
功能 |
说明 |
| F1 |
生成对账单 |
选月份 → 自动拉取该月已完成订单(status=6),生成对账单 |
| F2 |
对账单列表 |
按月查看,状态筛选(待确认/已确认/已结算) |
| F3 |
对账单详情 |
查看每笔订单明细:订单号、房间号、联系人、金额、订单状态、退款状态 |
| F4 |
排除订单 |
对争议订单点击「排除」,排除后自动重算应付金额 |
| F5 |
导出 Excel |
导出对账单明细(含排除标记) |
| F6 |
标记已结算 |
餐厅确认后,酒店财务标记结算完成,填写结算备注 |
3.2 餐厅端
| # |
功能 |
说明 |
| F7 |
查看对账单列表 |
只看到「已确认」和「已结算」的对账单(待确认的还没提交) |
| F8 |
查看对账单详情 |
查看明细(含被排除的订单,排除订单标注) |
| F9 |
确认对账单 |
核对无误后点击确认 |
| F10 |
导出 Excel |
同酒店端导出内容 |
4. 业务规则
| 规则 |
内容 |
| R1 |
对账范围:仅顾客点餐订单(hotel_order 中 status = 6 已完成的订单) |
| R2 |
对账单编号格式:DZ-YYYYMM-NNN(如 DZ-202609-001) |
| R3 |
同一月份只能生成一张对账单(重复生成提示已存在) |
| R4 |
退款订单默认包含在对账单中,酒店可手动排除 |
| R5 |
排除订单需填写排除原因 |
| R6 |
应付金额 = 订单总额 - 排除金额(自动重算) |
| R7 |
状态流转:待确认(0) → 已确认(1) → 已结算(2),单向不可逆 |
| R8 |
餐厅端只能看到「已确认」和「已结算」状态的对账单 |
| R9 |
只有「已确认」状态的对账单才能被酒店标记为「已结算」 |
| R10 |
对账单生成后,对应的订单数据快照到明细表,后续订单状态变更不影响已生成的对账单 |
5. 数据库设计
5.1 hotel_reconciliation(对账单主表)
| 字段 |
类型 |
说明 |
| id |
bigint NOT NULL |
主键(雪花算法) |
| tenant_id |
bigint NOT NULL DEFAULT 1 |
租户ID(酒店租户) |
| reconciliation_no |
varchar(20) NOT NULL |
对账单编号(DZ-YYYYMM-NNN) |
| period_start |
date NOT NULL |
对账周期开始 |
| period_end |
date NOT NULL |
对账周期结束 |
| order_count |
int NOT NULL DEFAULT 0 |
订单总笔数(含排除) |
| total_amount |
decimal(10,2) NOT NULL DEFAULT 0 |
订单总额 |
| excluded_count |
int NOT NULL DEFAULT 0 |
排除笔数 |
| excluded_amount |
decimal(10,2) NOT NULL DEFAULT 0 |
排除金额 |
| settlement_amount |
decimal(10,2) NOT NULL DEFAULT 0 |
应付金额 = total - excluded |
| status |
tinyint NOT NULL DEFAULT 0 |
0=待确认 / 1=已确认 / 2=已结算 |
| confirmed_by |
bigint DEFAULT NULL |
确认人 |
| confirmed_time |
datetime DEFAULT NULL |
确认时间 |
| settled_by |
bigint DEFAULT NULL |
结算操作人 |
| settled_time |
datetime DEFAULT NULL |
结算时间 |
| settled_remark |
varchar(500) DEFAULT NULL |
结算备注 |
| del_flag |
bigint NOT NULL DEFAULT 0 |
逻辑删除 |
| create_by / create_time / create_dept / update_by / update_time |
— |
审计字段 |
5.2 hotel_reconciliation_item(对账单明细)
| 字段 |
类型 |
说明 |
| id |
bigint NOT NULL |
主键 |
| tenant_id |
bigint NOT NULL DEFAULT 1 |
租户ID |
| reconciliation_id |
bigint NOT NULL |
对账单ID |
| order_id |
bigint NOT NULL |
关联 hotel_order.id |
| order_no |
varchar(30) |
冗余订单号 |
| room_no |
varchar(10) |
冗余房间号 |
| contact_name |
varchar(50) |
联系人 |
| pay_amount |
decimal(10,2) |
实付金额 |
| order_status |
tinyint |
订单状态(冗余快照) |
| refund_status |
tinyint |
退款状态(冗余快照,0/1/2) |
| excluded |
tinyint NOT NULL DEFAULT 0 |
是否排除(0=否 / 1=是) |
| exclude_reason |
varchar(200) DEFAULT NULL |
排除原因 |
| del_flag |
bigint NOT NULL DEFAULT 0 |
逻辑删除 |
| create_by / create_time / create_dept / update_by / update_time |
— |
审计字段 |
5.3 字典
| 字典类型 |
dict_value |
dict_label |
list_class |
| hotel_reconciliation_status |
0 |
待确认 |
warning |
| hotel_reconciliation_status |
1 |
已确认 |
primary |
| hotel_reconciliation_status |
2 |
已结算 |
success |
6. 后端接口设计
6.1 酒店端(/hotel/reconciliation)
| 方法 |
路径 |
说明 |
权限 |
| GET |
/page |
对账单分页列表 |
hotel:reconciliation:query |
| GET |
/detail |
对账单详情(含明细列表) |
hotel:reconciliation:query |
| POST |
/generate |
生成对账单 |
hotel:reconciliation:generate |
| POST |
/excludeItem |
排除/恢复明细 |
hotel:reconciliation:exclude |
| POST |
/settle |
标记已结算 |
hotel:reconciliation:settle |
| GET |
/export |
导出 Excel |
hotel:reconciliation:export |
6.2 餐厅端(/hotel/reconciliation/partner)
| 方法 |
路径 |
说明 |
权限 |
| GET |
/page |
对账单分页列表(仅已确认+已结算) |
hotel:reconciliation:partner:query |
| GET |
/detail |
对账单详情 |
hotel:reconciliation:partner:query |
| POST |
/confirm |
确认对账单 |
hotel:reconciliation:partner:confirm |
| GET |
/export |
导出 Excel |
hotel:reconciliation:partner:export |
7. 前端页面设计
7.1 酒店端 reconciliation.vue
- AiCrudPage 列表(隐藏新增/批量删除/选择列)
- 工具栏:生成对账单按钮
- 搜索筛选:状态(DictSelect)、月份范围
- 表格列:对账单编号、周期、订单笔数、总额、排除笔数/金额、应付金额、状态(DictTag)、操作
- 操作列:详情(text-info)、排除管理(text-warning,仅待确认)、导出(text-success)、确认提交(仅待确认→提交给餐厅看)、标记结算(text-primary,仅已确认)
- 详情弹窗:汇总信息 + 明细表格(排除订单灰显+标注原因)
- 排除弹窗:选择要排除的订单 + 填写原因
7.2 餐厅端 reconciliationPartner.vue
- AiCrudPage 列表(只读,隐藏新增/批量删除/选择列)
- 搜索筛选:状态(仅已确认+已结算)
- 表格列:同酒店端(去掉排除管理操作)
- 操作列:详情(text-info)、确认(text-success,仅已确认)、导出(text-success)
- 详情弹窗:同酒店端(排除订单灰显标注)
8. 菜单与权限
对账管理(一级菜单,sort=12,与餐厅管理同级)
├── 对账单(酒店端) path=/hotel/reconciliation component=hotel/reconciliation
│ └── 按钮权限:hotel:reconciliation:query / generate / exclude / settle / export / submit
└── 对账单(餐厅端) path=/hotel/reconciliation/partner component=hotel/reconciliationPartner
└── 按钮权限:hotel:reconciliation:partner:query / confirm / export
9. Excel 导出配置
config_key: hotel_reconciliation_export
data_source_bean: hotelReconciliationServiceImpl
query_method: queryExportList
导出列:对账单编号、周期、订单笔数、总额、排除笔数、排除金额、应付金额、状态、确认时间、结算时间
10. 技术决策
| 决策 |
说明 |
| 多租户方案 |
方案一:受控跨租户。对账单归酒店租户,餐厅通过 TenantContextHolder.executeWithTenant() 访问 |
| 对账单编号生成 |
按月份查当前最大序号 +1,格式 DZ-YYYYMM-NNN |
| 订单数据快照 |
生成对账单时将订单关键信息复制到 hotel_reconciliation_item,后续订单变更不影响已生成对账单 |
| 退款订单处理 |
默认包含,酒店可排除;排除后自动重算应付金额 |
| 餐厅可见范围 |
餐厅只能看到「已确认」和「已结算」的对账单,酒店需先「提交」才推送给餐厅 |
| 导出方式 |
复用 sys_excel_export_config + sys_excel_column_config 配置化导出 |
11. 对现有模块的影响
| 模块 |
影响 |
| hotel_order |
只读,生成对账单时 SELECT 该月已完成订单 |
| hotel_order_item |
只读,取明细金额 |
| 租户/角色/菜单 |
新增对账菜单 + 按钮权限(Flyway 脚本) |
| 现有代码 |
零改动,纯增量开发 |
12. 代码结构
reconciliation/
├── controller/
│ ├── HotelReconciliationController.java # 酒店端 /hotel/reconciliation/**
│ └── HotelReconciliationPartnerController.java # 餐厅端 /hotel/reconciliation/partner/**
├── domain/
│ ├── HotelReconciliation.java
│ └── HotelReconciliationItem.java
├── dto/
│ └── ReconciliationGenerateDTO.java # 生成请求(yearMonth)
├── vo/
│ ├── HotelReconciliationVO.java
│ └── ReconciliationDetailVO.java # 含明细列表
├── mapper/
│ ├── HotelReconciliationMapper.java
│ └── HotelReconciliationItemMapper.java
└── service/
├── HotelReconciliationService.java
└── impl/
└── HotelReconciliationServiceImpl.java
前端:
forge-admin-ui/src/views/hotel/reconciliation.vue — 酒店端
forge-admin-ui/src/views/hotel/reconciliationPartner.vue — 餐厅端
forge-admin-ui/src/api/hotel.js — 追加对账相关 API 函数