VEU.WathBody/1-docs/2-db
virus-home f41bf9a0d2 Этап 7, итерация 2 завершена: m06-fit-import + m07-fit-fetch
m06 (Server.WatchBody.Import + --mode import): FitParser на официальном
Garmin FIT SDK 21.218.0 (Dynastream.Fit; события Decode, типы по Mesg.Num)
→ канонический факт workout-facts/1 (+avg_hr, hr_recovery_s, fit_file_id);
TcxGpxParser (упрощённый факт); WorkoutImporter — дедуп fit_file_id,
сопоставление телефонной тренировке ±15 мин (Ф-8.4), иначе строка
«только .fit»; ProgramPackageImporter — пакет program-import.json по
external_id (повтор → новая версия max+1, отсутствующие упражнения
создаются); ImportService — подпапки-атлеты, архив, коды 0/1/2.
Errata З-35: program_select/get rev.2 (+external_id, DROP старой
сигнатуры), маппинг ProgramRepository.

m07 (Server.WatchBody.Fetch + --mode fetch): GarminClient — SSO по
контракту garminconnect (embed→csrf→signin→ticket→OAuth1→Bearer),
список активностей, скачивание .fit; FitFetcher — атлет по
Garmin.AthleteName, фильтр strength_training, дедуп 2 рубежей
(кэш activityId + fit_file_id в БД); коды 0/1/2, auth-fail →
подсказка про m06-fallback. Против живого Garmin — ручная валидация
прототипа; тесты — FakeGarminHandler + .fit-энкодер SDK.

Тесты: Web 98/98 (m06 — 12, m07 — 5), Core 56/56, psql 123/123.
Конфиг: Import.Dir/ArchiveDir, Garmin.* (в т.ч. новый AthleteName —
tech-req 4.2). Эксплуатационные файлы в коммит не включены.
2026-10-18 23:58:53 +05:00
..
ref Этап 7: итерации 1–2 — m01–m05 серверной части + обе волны ревью 2026-10-18 (З-35…З-42) 2026-10-18 20:11:40 +05:00
src Этап 7, итерация 2 завершена: m06-fit-import + m07-fit-fetch 2026-10-18 23:58:53 +05:00
readme.md Этап 7: итерации 1–2 — m01–m05 серверной части + обе волны ревью 2026-10-18 (З-35…З-42) 2026-10-18 20:11:40 +05:00

readme.md

БД WatchBody (PostgreSQL)

Документация БД серверной части — шаг 6 процесса (std1\_process\process.md), правила d-db (std1\_rules\d\d-db.md), db-func (std1\_rules\db\db-func.md). Решение шага 6 — 0-mng\plan.md.

Общие сведения

  • СУБД: PostgreSQL 17+; доступ — только через хранимые функции (Kit.Helpers SqlHelperAbstract/SqlHelperPostgres — fluent PrepareExecute<T>(), tech-requirements разд. 3; З-42 — фактическое имя компонента).
  • Схемы-слои: src — основные данные (атлеты, тренировки, программы, метрики); ref — справочники (двигательные группы).
  • Изоляция атлетов (🛡): каждая таблица данных несёт athlete_id; все функции слоя src принимают p_athlete_id и выбирают/пишут только в пределах атлета (requirements, Ф-8.5, инвариант раздела 5).
  • Идемпотентность (🛡, Р2-Б): PK клиентских сущностей — UUID; телефон генерирует UUID (строки «только .fit» — сервер), повторная вставка с тем же UUID возвращает существующую запись; ссылки дочерних записей — те же UUID, маппинг серверных id не нужен.
  • JSON: версии программ и факты .fit — jsonb с проверкой схемы на стороне приложения (не в БД).

Состав

Файл Содержание
ref\tables.md справочники слоя ref
src\tables.md таблицы слоя src
{слой}\functions.md списки функций (после утверждения таблиц)

План миграции (d-db-1)

  1. Схемы: CREATE SCHEMA IF NOT EXISTS src; CREATE SCHEMA IF NOT EXISTS ref;
  2. Справочники: ref\exercise_group.psql — таблица + вставка 5 значений (идемпотентно, ON CONFLICT (code) DO NOTHING).
  3. Таблицы src: порядок — athlete → athlete_profile → exercise → exercise_replacement → program → program_version → workout → workout_set → command_log → daily_log → workout_metrics → breaks (FK-зависимости).
  4. Функции: файлы {слой}\функции.psql по сущностям в том же порядке (CREATE OR REPLACE — перезапуск безопасен).
  5. Версионирование: каталог 2-db\migrations\ — NNN_описание.sql по возрастанию; каждая миграция идемпотентна (IF NOT EXISTS / OR REPLACE); факт применения — одна запись на файл в src.migration (id, filename, applied_at).
  6. Применение (З-36): Server.WatchBody.Web --mode migrate (--config <path>) — файлы каталога 2-db\migrations\ по возрастанию имён, журнал — src.migration (MigrationRepository), транзакция на файл, коды возврата 0/1; ключ конфига Db.MigrationsDir (умолчание — migrations рядом с исполняемым файлом).

Таблица llm_calls (v2)

Журнал вызовов LLM-планировщика (дизайн LLM-планирования, разд. 8) создаётся в v2 вместе с LlmPlanner — в v1 не проектируется.