Files
duty-teller/docs/import-format.md
Nikolay Tatarinov e6bc60b436
Some checks failed
CI / lint-and-test (push) Failing after 23s
chore: update project configuration and documentation
- 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.
2026-02-24 13:30:58 +03:00

2.8 KiB
Raw Blame History

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

{
  "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).