VEU.WathBody/1-docs/4-modules/m06-fit-import
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
..
api_specs Этап 7, итерация 2 завершена: m06-fit-import + m07-fit-fetch 2026-10-18 23:58:53 +05:00
SKILL.md Этап 7, итерация 2 завершена: m06-fit-import + m07-fit-fetch 2026-10-18 23:58:53 +05:00
module_reqs.md Этап 7, итерация 2 завершена: m06-fit-import + m07-fit-fetch 2026-10-18 23:58:53 +05:00
readme.md Этап 7, итерация 2 завершена: m06-fit-import + m07-fit-fetch 2026-10-18 23:58:53 +05:00

readme.md

m06-fit-import — план работ (d-dev)

Модуль: Server.WatchBody.Import (FitParser/TcxGpxParser/ WorkoutImporter/ProgramPackageImporter/ImportService) + режим --mode import в единой точке входа CLI. Алгоритм: std1\_rules\d\d-dev.md (итерационная разработка по модулям). Требования: module_reqs.md. Зависимости: m01 (репозитории, DONE), m02 (единая точка входа CLI — DONE), m03 (ProgramStore — создание версий пакета, DONE).

Шаг Что делаем Статус
0 Модульные документы: module_reqs.md / readme.md / SKILL.md ✅ 2026-10-18
1 Список единиц (классы/методы/конфиг/тесты) ✅ 2026-10-18
1.3 Пользователь! утверждение списка ⬜
2 Спецификации: api_specs (facts-схема, сопоставление, пакет) ✅ 2026-10-18
2.4 Пользователь! утверждение спецификаций ✅ 2026-10-18
3 Реализация + тесты ✅ 2026-10-18 (тесты Web 93/93, из них m06 — 12; Core 56/56; psql 123/123; CLI-смок --mode import пройден)
3.4 Пользователь! утверждение реализации (закрытие модуля) ✅ 2026-10-18
4 Завершение: план, примечания ✅ 2026-10-18 — Модуль завершён (2026-10-18). Следующий по плану этапа 7 — m07-fit-fetch (итерация 2).

Статусы: ⬜ не начат · 🔄 в работе · ✅ готов.

Примечания по ходу работ

  1. SDK: NuGet Garmin.FIT.Sdk 21.218.0, namespace Dynastream.Fit (не Garmin.Fit.*); API потоковый: Decode.IsFIT/CheckIntegrity/Read (Stream), события MesgEvent доставляют базовый Mesg — типы конструируются из него по Mesg.Num (new SessionMesg(mesg)); у SetMesg — GetRepetitions (не NumReps); Encode для .fit-фикстур тестов.
  2. Errata З-35 (доведение): program_select/program_get не возвращали external_id — rev. 2 обеих функций (+ DROP прежней row-типной сигнатуры), маппинг в ProgramRepository.Select/Get, синхронизированы func_specs и mock-колонки Core.Tests; psql-тесты перегнаны — PASS.
  3. Errata m01: workout_insert fit-полей не принимает (дизайн db-m-8) — строка «только .fit» пишется Insert + Update (как sync, errata m02).
  4. Устройство в .fit: garmin_product у тестового файла декодируется в null, фактическое устройство — числом в product (Fenix6sAsia = 3513) — device пишет идентификатор как есть.
  5. external_id пакета уникален глобально (З-35): один пакет (program_id) назначается одному атлету — повтор тому же атлету даёт новую версию, повтор другому — UNIQUE-ошибку (файл остаётся, лог; формат program-import-format.md §3.4 соблюдён).
  6. Sport в TCX — атрибут Activity[@Sport], не элемент.