Some checks failed
CI / lint-and-test (push) Failing after 23s
- Added *.egg-info/ to .gitignore to prevent egg metadata from being tracked. - Updated virtual environment instructions in CONTRIBUTING.md and README.md to use .venv for consistency. - Revised mkdocs.yml to include a placeholder for the repository URL when publishing. - Cleaned up pyproject.toml by removing unnecessary pylint configuration. - Enhanced import-format.md and runbook.md documentation for clarity on user roles and health check endpoints.
61 lines
2.8 KiB
Markdown
61 lines
2.8 KiB
Markdown
# Duty-schedule import format
|
||
|
||
The **duty-schedule** format is used by the `/import_duty_schedule` command. Only users in `ADMIN_USERNAMES` or `ADMIN_PHONES`, or users with the **admin** role in the database (assigned via `/set_role`), can import.
|
||
|
||
## Import flow
|
||
|
||
1. **Handover time** — The bot asks for the shift handover time and optional timezone (e.g. `09:00 Europe/Moscow` or `06:00 UTC`). This is converted to UTC and used as the boundary between duty periods when creating records.
|
||
2. **JSON file** — Send a file in duty-schedule format (see below). On re-import, duties in the same date range for each user are replaced by the new data.
|
||
|
||
## Format specification
|
||
|
||
- **meta** (required) — Object with:
|
||
- **start_date** (required) — First day of the schedule, `YYYY-MM-DD`.
|
||
- **weeks** (optional) — Not used to limit length; the number of days is derived from the longest `duty` string (see below).
|
||
|
||
- **schedule** (required) — Array of objects. Each object:
|
||
- **name** (required) — Full name of the person (string).
|
||
- **duty** (required) — String of cells separated by **`;`**. Each cell corresponds to one day starting from `meta.start_date` (first cell = start_date, second = start_date + 1 day, etc.). Empty or whitespace = no event for that day.
|
||
|
||
### Cell values (single character, case-sensitive where noted)
|
||
|
||
| Value | Meaning | Notes |
|
||
|-------|----------------|--------------------------|
|
||
| **в**, **В**, **б**, **Б** | Duty | Any of these four |
|
||
| **Н** | Unavailable | Exactly `Н` |
|
||
| **О** | Vacation | Exactly `О` |
|
||
| (empty/space/other) | No event | Ignored for import |
|
||
|
||
The number of days in the schedule is the maximum length of any `duty` string when split by `;`. If `duty` is empty or missing, it is treated as an empty list of cells.
|
||
|
||
## Example JSON
|
||
|
||
```json
|
||
{
|
||
"meta": {
|
||
"start_date": "2025-02-01",
|
||
"weeks": 4
|
||
},
|
||
"schedule": [
|
||
{
|
||
"name": "Ivanov Ivan",
|
||
"duty": ";;В;;;Н;;О;;В;;"
|
||
},
|
||
{
|
||
"name": "Petrov Petr",
|
||
"duty": ";;;В;;;;;;В;;;"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
- **start_date** is 2025-02-01; the longest `duty` has 14 cells (after splitting by `;`), so the schedule spans 14 days (2025-02-01 … 2025-02-14).
|
||
- First person: duty on day index 2 (В), unavailable on 6 (Н), vacation on 8 (О), duty on 11 (В). Other cells are empty.
|
||
- Second person: duty on day indices 3 and 10.
|
||
|
||
## Validation
|
||
|
||
- `meta` and `meta.start_date` must be present and valid; `start_date` must parse as `YYYY-MM-DD`.
|
||
- `schedule` must be an array; each item must be an object with string `name` (non-empty after strip) and string `duty` (if missing, treated as `""`).
|
||
- Invalid JSON or encoding raises an error; the parser reports missing or invalid fields (see `duty_teller.importers.duty_schedule.DutyScheduleParseError`).
|