Files
XQKqueue/server/README.md
brother7 78df07e074 实现叫号播报并调整现场业务规则
需求描述:发布屏在员工叫号后播放语音;同场次手机号被叫号后可重新取号;登录连续失败限制调整为10次。

实现思路:发布屏按新批次去重触发中文语音;重复手机号仅拦截WAITING号码;登录限流使用10次阈值,并补充前后端回归测试与接口说明。
2026-07-31 16:36:55 +08:00

81 lines
3.8 KiB
Markdown

# Queue API
Go 1.26 modular-monolith API for the scenic queue system. It uses the standard
library HTTP router, GORM, PostgreSQL, versioned embedded SQL migrations and
database-backed sessions.
## Local run
1. Start PostgreSQL and create the database in `DATABASE_URL`.
2. Copy `.env.example` to `.env`, replace both cryptographic keys, and export
the variables. Keys must decode to exactly 32 random bytes.
3. Run `go run ./cmd/api`. With `MIGRATE_ON_START=true`, embedded migrations run
under a PostgreSQL advisory lock.
4. Seed the local demo users, projects, queues, batches, devices and audit data with:
```sh
ADMIN_PASSWORD='replace-me' go run ./cmd/seed
```
The command is repeatable and prints the demo display and visitor paths. It
resets only the `DEMO`, `RAFT` and `CABLE` projects. Default users are the
protected `xqkwljtadmin` account and `staff`; override the staff credential
and primary-project values with
`ADMIN_USERNAME`, `STAFF_USERNAME`, `ADMIN_PASSWORD`, `PROJECT_CODE` and
`PROJECT_NAME`.
For a production release, run `go run ./cmd/migrate` as a separate release Job
with `MIGRATE_ON_START=false`, then rotate the protected administrator password
with `SUPER_ADMIN_PASSWORD='...' go run ./cmd/bootstrap-admin`. Do not run the
seed command against production.
`POST /api/staff/projects/{id}/tickets` and
`POST /api/staff/projects/{id}/call-next` require an `Idempotency-Key` header.
Ticket creation requires an immutable integer `party_size` inside the project's
configured `min_party_size` / `max_party_size` range. A call-next request uses
`{ "expected_revision": 12, "mode": "TICKET|PEOPLE", "count": 5 }`.
`TICKET` selects up to `count` consecutive FIFO tickets. `PEOPLE` selects the
longest consecutive FIFO prefix whose total party size does not exceed `count`;
it never splits or skips a ticket and rejects when the first ticket alone is
larger than the requested target. Each mode has a separate project-level
anti-mistouch maximum.
If a phone already has waiting tickets in the current queue session, ticket creation returns
`DUPLICATE_PHONE`; repeat with the same request body except
`allow_duplicate: true` and a new idempotency key after the employee confirms.
Once the earlier ticket has been called, the same phone can take a new ticket
without duplicate confirmation.
`GET /api/public/projects` returns projects currently open for visitor
self-service, including each project's allowed party-size range.
`POST /api/public/projects/{id}/tickets` uses the same ticket
validation, queue locking and idempotency rules as the staff ticket flow, but
returns only the public ticket projection and a private status token. Public
ticket creation is rate-limited and audited as `PUBLIC_TICKET_CREATED`.
`POST /api/public/status/search` is a temporary non-production operational-test
endpoint. It accepts `{ "phone": "..." }` and returns all current active
tickets associated with that phone. It is disabled when `APP_ENV=production`;
replace it with OTP or an external identity interface before formal launch.
`POST /api/internal/status/search` exposes the same active-ticket lookup to
trusted backend services in every environment. It accepts `{ "phone": "..." }`
and only allows direct peers on private or loopback networks. Do not publish
this path through the public Ingress; callers must use the internal service
address. Forwarded client-IP headers are intentionally ignored.
## Tests
```sh
go test ./...
go vet ./...
```
From the repository root, `make test-db` creates a disposable PostgreSQL
database and runs migration/maintenance integration tests.
Unit tests cover FIFO ticket/people selection, people-ahead ETA, phone
normalization, authenticated encryption, token hashing and password hashing.
PostgreSQL integration tests run through
`make test-db` against a disposable database.