Create wiki page 'Database'

2026-04-24 10:58:53 +03:00
parent dd7d69086c
commit 6d7fa6a649
+132
@@ -0,0 +1,132 @@
# Database
GM-Relay uses PostgreSQL. Schema changes are managed by DbUp migrations embedded in `GmRelay.Bot`.
## Migrations
Current migrations:
- `V001__initial_schema.sql` — base tables for players, groups, sessions and participants.
- `V002__add_session_batch.sql``sessions.batch_id` for batch scheduling.
- `V003__add_thread_id.sql``sessions.thread_id` for Telegram forum topics.
- `V004__add_reschedule_proposals.sql` — proposal/vote tables for rescheduling.
- `V005__add_batch_message_id.sql``sessions.batch_message_id` for editing the original batch message.
## Core tables
### players
Known Telegram users.
Important fields:
- `telegram_id` — unique Telegram user ID.
- `display_name` — current display name captured from Telegram.
- `telegram_username` — optional username.
### game_groups
Telegram groups where games are organized.
Important fields:
- `telegram_chat_id` — unique Telegram chat ID.
- `name` — current Telegram chat title.
- `gm_telegram_id` — Telegram ID of the GM for this group.
### game_group_members
Membership table between groups and players. The current feature set mostly works through session participation and `gm_telegram_id`; this table is part of the base schema for group membership.
### sessions
Individual game sessions.
Important fields:
- `batch_id` — groups multiple sessions created by one `/newsession` command.
- `group_id` — owning Telegram group.
- `title` — game title.
- `join_link` — connection link sent before the game.
- `scheduled_at` — UTC timestamp.
- `status``Planned`, `ConfirmationSent`, `Confirmed`, or `Cancelled`.
- `confirmation_message_id` — Telegram message ID for RSVP prompt.
- `link_message_id` — Telegram message ID for pre-game link reminder.
- `thread_id` — Telegram forum topic ID, if created.
- `batch_message_id` — original Telegram message with batch schedule.
There is a partial index `ix_sessions_pending` over `scheduled_at` for active statuses.
### session_participants
Per-session player participation and RSVP state.
Important fields:
- `session_id` and `player_id` — unique pair.
- `is_gm` — whether participant is the GM.
- `rsvp_status``Pending`, `Confirmed`, or `Declined`.
- `responded_at` — RSVP timestamp.
## Reschedule tables
### reschedule_proposals
Tracks one active reschedule flow per session.
Important fields:
- `session_id` — target session.
- `proposed_at` — proposed new UTC time; null while waiting for GM input.
- `proposed_by` — GM Telegram ID.
- `status``AwaitingTime`, `Voting`, `Approved`, `Rejected`.
- `vote_message_id` and `vote_chat_id` — Telegram voting message location.
A partial unique index allows only one active proposal per session while status is `AwaitingTime` or `Voting`.
### reschedule_votes
Stores participant votes for a proposal.
Important fields:
- `proposal_id`.
- `player_id`.
- `vote``yes` or `no`.
- `voted_at`.
Each participant has one vote per proposal; repeated voting updates the stored vote.
## Status model
Session statuses:
```text
Planned -> ConfirmationSent -> Confirmed
Planned -> Cancelled
ConfirmationSent -> Cancelled
Confirmed -> ConfirmationSent, if a confirmed participant later declines
```
Reschedule statuses:
```text
AwaitingTime -> Voting -> Approved
AwaitingTime -> Voting -> Rejected
AwaitingTime -> Approved, if no participants exist
```
RSVP statuses:
```text
Pending -> Confirmed
Pending -> Declined
Confirmed -> Declined
Declined -> Confirmed
```
## Time handling
User-facing input and output are Moscow time (`UTC+3`). `MoscowTime.TryParseMoscow` converts accepted local formats into UTC before saving to `scheduled_at`.
Web edit form shows Moscow time, then converts it back to UTC before updating the database.