Files
wyndham-Condon/README.md
T

271 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# CONDO Owner Desk
CONDO Owner Desk 是一套面向酒店公寓运营团队的业主年度住宿权益管理系统。它把业主账户、房型规则、入住使用记录和年度剩余权益集中在一个工作台中,并由后端统一计算房晚、扣减倍率和余额,避免浏览器直接修改权威数据。
当前版本由原生 Web 前端、TypeScript/Fastify API 和 PostgreSQL 数据层组成,可通过 Docker 部署,也可使用 Mock API 或本地历史审计快照进行演示。
## 主要功能
- 受保护的运营人员登录、12 小时 HttpOnly 会话和主动退出。
- Dashboard 展示业主房间数、剩余权益、已用权益、房型分布与月度使用情况。
- 按编号、业主、房号、单元号、会员号和房型查询业主账户。
- 查询、筛选和分页浏览使用记录及业主详情。
- 新增使用记录时预览扣减结果;Night、倍率、Use 和 Balance 最终由后端计算。
- 删除使用记录时通过事务恢复账户余额。
- 英语、简体中文和泰语界面切换。
- 支持 PostgreSQL 持久化模式、完整历史快照预览模式和内置原型数据模式。
## 系统架构
```mermaid
flowchart LR
Browser[浏览器<br/>HTML / CSS / JavaScript]
Nginx[Nginx<br/>静态资源与 /api 反向代理]
API[Fastify API<br/>认证、校验、业务事务]
DB[(PostgreSQL<br/>booking_test / condon)]
Browser --> Nginx
Nginx --> API
API --> DB
```
- 前端没有打包步骤,可直接由任意静态 Web 服务器托管。
- Docker 模式下,浏览器只访问 Nginx;`/api/*` 被同源代理到后端,后端端口不对外发布。
- PostgreSQL 不包含在 `docker-compose.yml` 中,后端连接现有的 `booking_test` 数据库,并且只使用隔离的 `condon` schema。
- 浏览器不接触数据库凭据,也不直接连接 PostgreSQL。
## 快速体验
### 前置条件
- Node.js 24 或更高版本。
- Python 3(仅用于下面的本地静态文件服务;也可换成其他静态服务器)。
### 使用内置原型数据
这是全新克隆仓库后最容易复现的方式,不需要 PostgreSQL,也不会写入真实数据。
在第一个终端启动本地认证 Mock API:
```bash
node tests/mock-api-server.mjs
```
在第二个终端从仓库根目录启动前端:
```bash
python3 -m http.server 4173 --bind 127.0.0.1
```
打开 <http://127.0.0.1:4173/?mode=demo>,使用本地开发账号登录:
```text
Username: wyndhamcondon
Password: wyndhamcondon
```
`?mode=demo` 使用前端内置的 190 条原型账户;登录由 Mock API 完成。演示期间新增或删除的数据只保存在当前进程内存中,进程重启后恢复初始状态。
> 默认账号只用于本地开发和演示。任何共享或生产环境都必须通过环境变量更换密码。
## 运行模式
### 1. PostgreSQL 持久化模式
前端默认运行在 API 模式。后端需要可访问且已经应用 `condon` 迁移的 `booking_test` 数据库。
```bash
cd backend
npm ci
cp .env.example .env
```
编辑 `.env` 中的数据库连接和认证信息,然后在 zsh/bash 中加载环境变量并启动后端:
```bash
set -a
source .env
set +a
npm run dev
```
另开终端,在仓库根目录启动前端:
```bash
python3 -m http.server 4173 --bind 127.0.0.1
```
打开 <http://127.0.0.1:4173>。前端会连接当前主机的 `3000` 端口,并在认证成功后加载数据库中的业主、使用记录和 Dashboard 聚合数据。
数据库迁移、导入和只读部署验证需要额外的运维步骤,详见 [后端说明](./backend/README.md) 和 [Docker 部署说明](./DOCKER_DEPLOYMENT.md)。
### 2. 完整历史快照预览
历史预览不连接 PostgreSQL,提供与正式 API 相同的认证和业务接口。但预览所需的审计 JSON 含业务数据,位于 Git 忽略目录,**不会随仓库克隆或推送**。
只有已安全取得该批次材料时才可使用此模式。默认目录为:
```text
.planning/data_import_audit/import_batch_2026_07_31
```
也可以通过 `CONDO_IMPORT_SNAPSHOT_DIR` 指向外部安全目录。准备好材料后执行:
```bash
cd backend
npm ci
npm run build
npm run preview:history:check
npm run preview:history
```
再从仓库根目录启动 `4173` 端口的前端并打开默认 URL。快照写入只存在内存中,预览进程停止后即丢失。
当前脚本校验的历史基线为:388 个业主账户、157 条使用记录、2026 年已使用 438 个权益晚、剩余 5,394 个权益晚。
### 3. Docker 部署
复制生产环境示例文件:
```bash
cp deploy/.env.production.example .env
```
至少填写 `DB_HOST`、`DB_USER`、`DB_PASSWORD` 和 `AUTH_PASSWORD`。如果不是通过 `http://localhost:8080` 访问,还要把 `CORS_ORIGINS` 改为浏览器实际访问的完整 Origin;HTTPS 环境应设置 `AUTH_COOKIE_SECURE=true`。
```bash
docker compose build
docker compose up -d
```
默认访问地址为 <http://localhost:8080>。停止服务:
```bash
docker compose down
```
部署拓扑、迁移命令和连接输入格式见 [Docker 部署说明](./DOCKER_DEPLOYMENT.md)。
## 核心业务规则
每个业主房号独立拥有年度权益期间,当前默认年度新增为 15 晚,可包含上一年度结转。一次使用的权威计算为:
```text
Night = Check-out - Check-in
Multiplier = max(1, Used Tier - Purchased Tier + 1)
Use = Night × Multiplier
Balance After = Balance Before - Use
```
房型分级如下:
| Tier | 房型 |
| --- | --- |
| 1 | RM1、RM2、RM3、RM4、UG1、UG2 |
| 2 | SU1、SU2、SU6 |
| 3 | SU3 |
AC2 不进入自动分级;购买房型或使用房型涉及 AC2 时,运营人员必须选择 1–3 的人工倍率,后端再次校验。
使用记录创建和删除、权益流水及当前余额在 PostgreSQL 事务中同步更新。系统拒绝余额不足、日期无效、跨权益年度、房型规则不符和幂等键冲突等请求。完整表结构和规则见 [后端数据模型](./backend-data-model.md)。
## API 概览
除三个 `/auth/*` 接口和 CORS 预检外,其他接口(包括 `/docs`)都要求有效的 `condon_session` Cookie。
| Method | Path | 说明 |
| --- | --- | --- |
| POST | `/auth/login` | 登录并创建会话 |
| GET | `/auth/session` | 查询当前会话 |
| POST | `/auth/logout` | 注销当前会话 |
| GET | `/health` | 检查数据库、schema 和迁移版本 |
| GET | `/room-types` | 获取房型与倍率规则元数据 |
| GET | `/owner-accounts` | 搜索和分页查询业主账户 |
| GET | `/owner-accounts/:id` | 查询业主账户详情与年度余额 |
| GET | `/usage-records` | 查询使用记录 |
| POST | `/usage-records` | 事务性新增使用记录并扣减余额 |
| DELETE | `/usage-records/:id` | 事务性删除使用记录并恢复余额 |
| GET | `/dashboard` | 查询年度 Dashboard 聚合 |
后端运行时可通过 `/docs` 查看 OpenAPI UI。请求字段、返回模型和数据库函数详见 [后端说明](./backend/README.md)。
## 主要配置
后端本地配置模板为 [`backend/.env.example`](./backend/.env.example),Docker 配置模板为 [`deploy/.env.production.example`](./deploy/.env.production.example)。
| 变量 | 默认值/要求 | 用途 |
| --- | --- | --- |
| `API_HOST` | `127.0.0.1` | 后端监听地址 |
| `API_PORT` | `3000` | 后端监听端口 |
| `CORS_ORIGINS` | 本地 `4173` Origin | 允许携带 Cookie 的前端来源,逗号分隔 |
| `AUTH_USERNAME` | 本地默认 `wyndhamcondon` | 运营登录名 |
| `AUTH_PASSWORD` | 生产必须设置 | 运营登录密码 |
| `AUTH_SESSION_TTL_HOURS` | `12` | 会话有效期,允许 1–168 小时 |
| `AUTH_COOKIE_SECURE` | 生产默认 `true` | 是否只通过 HTTPS 发送 Cookie |
| `DB_HOST` / `DB_USER` / `DB_PASSWORD` | 必填 | PostgreSQL 连接信息 |
| `DB_NAME` | 必须为 `booking_test` | 防止误连其他数据库 |
| `DB_SSL` | `false` | 是否启用数据库 SSL |
| `CONDO_API_BASE_URL` | Docker 默认 `/api` | 前端 API 根地址 |
| `CONDO_DEFAULT_MODE` | `api` | 前端默认数据模式 |
| `CONDO_PERIOD_YEAR` | 当前 UTC 年 | Dashboard 与账户权益年度 |
应用不会自动读取 `.env` 文件;本地运行需要先把其中的值导出到当前 shell。不要提交真实环境文件或凭据。
## 目录结构
```text
.
├── index.html / styles.css / app.js # 原生前端界面与交互
├── api-client.js / runtime-config.js # API 客户端与前端运行时配置
├── owners-data.js # demo 模式原型数据
├── backend/
│ ├── src/ # Fastify API、认证、仓储和配置
│ ├── migrations/ # condon schema SQL 迁移
│ ├── scripts/ # 迁移、导入、冒烟和部署验证工具
│ └── tests/ # 后端单元与仓储测试
├── tests/ # 前端 Node 测试和 Mock API
├── deploy/ # Nginx 与 Docker 运行时配置
├── docker-compose.yml # 前后端容器编排
├── backend-data-model.md # 数据模型与业务规则规格
└── DOCKER_DEPLOYMENT.md # Docker 运维说明
```
`业主账户.md` 和 `使用记录.md` 是历史业务资料摘要,含个人与运营数据。共享、复制或导出前请遵循适用的数据保护要求。
## 开发与验证
前端测试:
```bash
node --test tests/*.test.mjs
```
后端检查:
```bash
cd backend
npm ci
npm run typecheck
npm test
npm run build
npm run db:check-migrations
```
需要真实数据库的命令包括 `db:inventory`、`db:migrate:up`、`db:verify`、`db:verify-import` 和 `db:test-integration`。其中 `db:test-integration` 只允许针对空的测试 schema 执行,不能用于已导入业务数据的环境。
## 安全与当前边界
- 生产环境必须更换默认登录凭据,并通过 Secret Manager 或运行时环境变量注入数据库密码。
- 会话令牌只通过 HttpOnly Cookie 发送,服务端只保存其 SHA-256 键;当前会话存储在后端内存中,后端重启后所有会话失效。
- 后端日志对 Cookie、认证信息和数据库密码做脱敏处理。
- 当前版本是单一运营账号模型,尚未实现多用户身份、角色权限和持久化会话。
- 当前不支持人工余额调整或跨权益年度入住。
- 数据库回滚属于显式运维操作;业务数据导入后不要执行迁移回滚。
## 相关文档
- [后端 API、数据库命令与验证](./backend/README.md)
- [后端数据模型与业务规则](./backend-data-model.md)
- [Docker 部署与数据库运维](./DOCKER_DEPLOYMENT.md)
- [前端设计系统](./design-system/condo-owner-desk/MASTER.md)