[backend] Модель данных: identity / clinical / audit, репозитории, create_all #6

Closed
opened 2026-10-03 14:38:53 +03:00 by Eleboba · 0 comments
Owner

Описание

SPEC §5 + ADR-002 (daily_checkins) + ADR-003 (две БД в одном Postgres, без Alembic).

Желаемый результат

  • app/db/identity.py: patients (token, display_name, snils, tg_chat_id, birth_year, sex, clinic_id, doctor_id, consent_at, consent_ver, revoked_at), doctors, connect_codes (код подключения от врача → токен).
  • app/db/clinical.py: patient_profile (token, modules[], therapy_start, next_visit, age_band, sex — без ФИО), item_responses, scale_results, daily_checkins (mood, med_taken, sleep_bucket, alcohol_bucket, side_effects, quit_intent, free_text_scrubbed), prescriptions, doses, alerts, messages, dialog_state (token, state, data JSONB), safety_plans.
  • app/db/audit.py: audit(actor, action, token, details).
  • Два engine/sessionmaker; clinical-код не импортирует identity (проверка в тесте импортов).
  • init_db() на старте приложения.

Как проверить

make up → таблицы созданы в обеих БД; tests/test_db.py на sqlite/aiosqlite или на compose-Postgres.


Лог выполнения

2026-10-03

2026-10-03

  • Что сделано:
    • app/db/identity.py — IdentityBase: patients, doctors, connect_codes; app/db/identity_repo.py — регистрация, согласие/отзыв, привязка чата, коды подключения, дежурные врачи.
    • app/db/clinical.py — ClinicalBase: patient_profiles, item_responses, scale_results (+item9, scheduled, flags), daily_checkins (unique token+day), prescriptions, doses, alerts, messages, dialog_state, safety_plans, clock_state.
    • app/db/audit.py — AuditLog (в clinical) + audit(session, *, actor, action, token, details, ts).
    • app/db/repo.py — тонкие хелперы clinical (чек-ины с merge, шкалы, алерты + ack_alert с аудитом, dialog_state, сообщения, офсет демо-часов).
    • app/db/session.py — два ленивых engine/sessionmaker, get_identity_session() / get_clinical_session(), configure(), dispose(); app/db/bootstrap.py — init_db() (create_all в обеих БД); вызов в lifespan app/main.py.
    • app/db/types.py — JSONType (JSONB на Postgres), TZDateTime (UTC, наивные datetime отклоняются — ADR-005).
  • Результат: tests/test_db.py — 17 тестов (sqlite in-memory, две раздельные БД): create_all, CRUD, уникальность СНИЛС/чата/чек-ина за день, ack → audit, upsert dialog_state, rollback, guardrail #5 (AST + граф импортов). Тот же набор зелёный на compose-Postgres (TEST_PG_IDENTITY_URL/TEST_PG_CLINICAL_URL); роль clinical_app не может подключиться к identity.
  • Заметки/решения:
    • Нет server_default=now() — время всегда передаётся параметром из app.core.clock.
    • В профиле birth_year вместо age_band (возрастную группу считает UI); поле алкоголя — alcohol_bucket (как в ADR-002).
    • session.py не импортирует модели, поэтому clinical-код может его использовать без identity; оба набора метаданных видит только bootstrap.py.
    • Если БД недоступна при старте, lifespan логирует ошибку и продолжает работу (нужно для test_smoke без Postgres); в compose Postgres поднимается до app.
## Описание SPEC §5 + ADR-002 (`daily_checkins`) + ADR-003 (две БД в одном Postgres, без Alembic). ## Желаемый результат - `app/db/identity.py`: patients (token, display_name, snils, tg_chat_id, birth_year, sex, clinic_id, doctor_id, consent_at, consent_ver, revoked_at), doctors, connect_codes (код подключения от врача → токен). - `app/db/clinical.py`: patient_profile (token, modules[], therapy_start, next_visit, age_band, sex — без ФИО), item_responses, scale_results, daily_checkins (mood, med_taken, sleep_bucket, alcohol_bucket, side_effects, quit_intent, free_text_scrubbed), prescriptions, doses, alerts, messages, dialog_state (token, state, data JSONB), safety_plans. - `app/db/audit.py`: `audit(actor, action, token, details)`. - Два engine/sessionmaker; clinical-код не импортирует identity (проверка в тесте импортов). - `init_db()` на старте приложения. ## Как проверить `make up` → таблицы созданы в обеих БД; `tests/test_db.py` на sqlite/aiosqlite или на compose-Postgres. --- ## Лог выполнения ### 2026-10-03 ### 2026-10-03 - **Что сделано:** - `app/db/identity.py` — `IdentityBase`: `patients`, `doctors`, `connect_codes`; `app/db/identity_repo.py` — регистрация, согласие/отзыв, привязка чата, коды подключения, дежурные врачи. - `app/db/clinical.py` — `ClinicalBase`: `patient_profiles`, `item_responses`, `scale_results` (+`item9`, `scheduled`, `flags`), `daily_checkins` (unique token+day), `prescriptions`, `doses`, `alerts`, `messages`, `dialog_state`, `safety_plans`, `clock_state`. - `app/db/audit.py` — `AuditLog` (в clinical) + `audit(session, *, actor, action, token, details, ts)`. - `app/db/repo.py` — тонкие хелперы clinical (чек-ины с merge, шкалы, алерты + `ack_alert` с аудитом, dialog_state, сообщения, офсет демо-часов). - `app/db/session.py` — два ленивых engine/sessionmaker, `get_identity_session()` / `get_clinical_session()`, `configure()`, `dispose()`; `app/db/bootstrap.py` — `init_db()` (create_all в обеих БД); вызов в lifespan `app/main.py`. - `app/db/types.py` — `JSONType` (JSONB на Postgres), `TZDateTime` (UTC, наивные datetime отклоняются — ADR-005). - **Результат:** `tests/test_db.py` — 17 тестов (sqlite in-memory, две раздельные БД): create_all, CRUD, уникальность СНИЛС/чата/чек-ина за день, ack → audit, upsert dialog_state, rollback, guardrail #5 (AST + граф импортов). Тот же набор зелёный на compose-Postgres (`TEST_PG_IDENTITY_URL`/`TEST_PG_CLINICAL_URL`); роль `clinical_app` не может подключиться к `identity`. - **Заметки/решения:** - Нет `server_default=now()` — время всегда передаётся параметром из `app.core.clock`. - В профиле `birth_year` вместо `age_band` (возрастную группу считает UI); поле алкоголя — `alcohol_bucket` (как в ADR-002). - `session.py` не импортирует модели, поэтому clinical-код может его использовать без identity; оба набора метаданных видит только `bootstrap.py`. - Если БД недоступна при старте, lifespan логирует ошибку и продолжает работу (нужно для `test_smoke` без Postgres); в compose Postgres поднимается до app.
Eleboba added this to the M1 Каркас milestone 2026-10-03 14:38:53 +03:00
Eleboba added the size/1P0backendfeature labels 2026-10-03 14:38:53 +03:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Reference: MedITron/PTSRaiAgent#6