feat: composizione corporea, deficit dinamico, condizioni mediche (PRD §5.1)
Tre leve per migliorare l'accuratezza del piano oltre Mifflin-St Jeor.
1. Composizione corporea (US Navy + Katch-McArdle)
- Profile: neckCm/waistCm/hipsCm opzionali in input
- bodyFatPct calcolato lato server con la formula US Navy metrica
(Hodgdon-Beckett 1984) e cifrato at-rest come dato sanitario
- BMR usa Katch-McArdle (FFM-based) quando bodyFatPct è noto, Mifflin
altrimenti — più accurato del 5-10% sui casi fuori-norma
- Test: estimateBodyFatPercentageUSNavy + calculateBmrKatchMcArdle
2. Deficit dinamico
- Profile.targetWeeklyLossKg (kg/settimana, opzionale)
- computeDailyKcalTarget calcola il deficit da kg/sett ×7700/7 con due cap
di sicurezza: 30% TDEE (Schoenfeld 2014) e 1% peso/sett (Helms 2014)
- plan.routes lo usa al posto del -500/-200 hard-coded
- Test: 6 casi (mantenimento, transizione, intensiva, cap peso, cap TDEE,
default mancante)
3. Condizioni mediche strutturate
- Profile.medicalConditions (array JSON cifrato)
- 11 condizioni: 7 adattabili (tiroide → BMR -10%, diabete II, IBS,
dislipidemia, ipertensione, reni → cap proteine 0.8 g/kg, fegato →
1.0 g/kg) + 4 escludenti (gravidanza, allattamento, diabete I, disturbi
alimentari)
- PATCH /me/profile/conditions per salvataggio mirato dall'onboarding
- hasExcludingCondition: plan.routes restituisce 409 medical_block se
attiva una condizione incompatibile
Onboarding allargato a 6 step: aggiunto "Condizioni mediche" tra Profile
e Preferences. Step labels e numeri rinumerati.
Schema migration 20260429203451_add_profile_health_fields.
44/44 unit test verdi.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
feb54c1f9a
commit
9401497f03
15 files changed
+744
-26
No files matched your search
@@ -0,0 +1,4 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "profiles" ADD COLUMN "body_fat_pct" TEXT,
|
||||
ADD COLUMN "medical_conditions" TEXT,
|
||||
ADD COLUMN "target_weekly_loss_kg" DOUBLE PRECISION;
|
||||
@@ -169,6 +169,18 @@ model Profile {
|
||||
activityLevel ActivityLevel @map("activity_level")
|
||||
/// @encrypted
|
||||
targetDate String? @map("target_date")
|
||||
// PRD §5.1 — velocità desiderata di calo peso (kg/settimana). Determina il
|
||||
// deficit calorico in modo dinamico al posto del valore hard-coded.
|
||||
targetWeeklyLossKg Float? @map("target_weekly_loss_kg")
|
||||
// PRD §14.3 — condizioni mediche dichiarate dall'utente. Filtrano ricette,
|
||||
// modulano deficit/macros, e bloccano l'app se "escludenti" (gravidanza,
|
||||
// allattamento, diabete tipo 1, disturbi alimentari). Cifrate at-rest come
|
||||
// dato sanitario (art. 9 GDPR — vedi ADR 0002).
|
||||
/// @encrypted
|
||||
medicalConditions String? @map("medical_conditions")
|
||||
// PRD §5.1 — % grasso corporeo stimata (US Navy) per BMR Katch-McArdle.
|
||||
/// @encrypted
|
||||
bodyFatPct String? @map("body_fat_pct")
|
||||
currentPhase Phase @default(INTENSIVE) @map("current_phase")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
Reference in new issue
Block a user