Files
Cibello-app/docs/07-datamodell.md
2026-08-05 19:21:11 +07:00

59 lines
8.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Del 7 Datamodell
Källa: `packages/database/src/schema/` (Drizzle). Genererad SQL:
`infrastructure/migrations/0000_*.sql` **54 tabeller**, 38 enums, FK:er och index.
Kör: `pnpm db:generate` (ny migration ur schemat), `pnpm db:migrate`, `pnpm db:seed`.
## Domänöversikt (tabeller per fil)
| Fil | Tabeller | Nyckelidéer |
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| users.ts | users, user_credentials, refresh_tokens, user_health_profiles, user_preferences, user_consents | Hälsodata i EGEN tabell, exponeras aldrig via hushålls-API (§7/§56). Refresh-tokens hashade med familje-id → stöldskydd. Samtycken som (user, kind)-PK med tidsstämplar (§33). |
| households.ts | households, household_members, storage_locations | invite_code unik. portion_factor per medlem (§7). Platser = kyl/frys/skafferi/…/custom med sublocations[] (§8). |
| ingredients.ts | canonical_ingredients, substitutions | Navet för normalisering (§9). Näring per 100 med provenance-JSON (aldrig AI-påhitt). Diet-/allergiflaggor för deterministisk filtrering. shelf_life_guidance per platstyp (§13). |
| products.ts | products | Versionshantering: (gtin, version) unik, aktuell rad = valid_to IS NULL (§11, §61.12). |
| inventory.ts | inventory_items, inventory_transactions | Transaktioner är sanningen (§8): typade (+purchase/cook_use/discard/…), value_minor på discard → svinnvärde (§26). Saldo cachas på posten. Index på (household, best_before). |
| recipes.ts | recipe_source_registry, recipes, recipe_ingredients, recipe_steps, recipe_ratings, recipe_favorites, recipe_cooks, recipe_similarities | Source registry för juridik (§15). DNA som jsonb (§16). variant_of/forked_from (§16/§35). Status-flöde §35. Similarity-klassning §36. Steg med timer/temperatur för Cooking Mode. |
| meals.ts | meals, meal_boxes | Näring som snapshot-jsonb (historik ändras inte när recept ändras). Estimatintervall för tallriksfoto (§22). Matlådor med portions_remaining + recommended_use_by (§24). |
| planning.ts | week_plans, week_plan_entries, shopping_lists, shopping_list_items | Planpost kan peka på recept ELLER matlåda. reschedule_reason_sv för dynamisk omplanering (§25). Lista: store_section, origin (plan/manual/…) (§27). |
| receipts.ts | receipts, receipt_lines, price_observations | Kvittorader med confidence + verified (§12). Prishistorik → budget/prognoser. |
| scans.ts | scan_jobs, ai_corrections | Jobbstatus inkl. awaiting_confirmation. Korrigeringar med consent_snapshot → träningsdata endast med samtycke (§33). model/prompt_version på allt (§9). |
| memory.ts | memory_items, taste_signals, food_memories | Minnestyper §32, origin user_stated/observed/ai_inferred (§30), paused/verified per post. |
| seasons.ts | season_events | Datadrivna datumregler (fixed/range/computed: midsommar/påsk/advent) (§28). |
| subscriptions.ts | subscriptions, subscription_events, store_transactions, store_notifications, trials, ai_usage_counters | Backend source of truth (§47). (provider, original_transaction_id) unik → idempotent verifiering. Månadskvot för fair use (§4546). |
| platform.ts | domain_events, feature_flags, audit_logs, idempotency_keys, notifications, push_tokens, creator_stats, creator_follows, ai_eval_cases, ai_eval_runs, waste_summaries | Outbox-mönster (§55). Flaggor med rollout-procent. Audit (§56). Evals (§34). |
## Viktiga constraints & index (urval)
Unika: users.email; households.invite_code; recipes.slug; (recipe,user) i ratings;
(provider, original_transaction_id) i subscriptions (partial, NOT NULL); (gtin, version)
i products (partial); (user, month) i ai_usage_counters; refresh_tokens.token_hash.
Prestanda: inventory(household, best_before) för utgångslistan; meals(user, date) för
Min dag; domain_events(published_at, occurred_at) för outbox; scan_jobs(status);
recipes(status), (cuisine), (total_time).
## Regler för ändringar (spec §63)
1. Ändra schema i `packages/database/src/schema/``pnpm db:generate` → granska SQL:en.
2. Ingen destruktiv ändring utan: backup (deploy.sh tar dump), migration, dokumenterad
rollback, kontroll efteråt.
3. Logga varje migration i tabellen nedan.
## Migrationslogg
| # | Fil | Datum | Innehåll | Rollback |
| ---- | ------------------------------- | ---------- | --------------------------------------------------------- | --------------------------- |
| 0000 | 0000_dusty_lady_deathstrike.sql | 2026-08-02 | Initialt schema: 54 tabeller, 38 enums, samtliga index/FK | Drop databasen (pre-launch) |
## i18n-tillägg (M1M6)
- `households.currency_code` char(3) NOT NULL DEFAULT 'SEK' pengagränsen går vid hushållet.
- Alla pengakolumner är `integer` i minor units (`*_minor`).
- `ingredient_translations` (ingredient_id, language_tag, name, aliases[], source, status) unik per (ingrediens, språk).
- `unit_translations` (unit_code, language_tag, abbreviation, name) PK (kod, språk).
- `recipe_translations` (recipe_id, language_tag, title, description, storage_guidance, status draft_ai|in_review|published, source, verification jsonb).
- `recipe_step_translations` (recipe_id, language_tag, step_number, instruction, tip) PK (recept, språk, steg).
- `nutrition_display_profiles` (region_code PK, energy_display kcal|kj|both, salt_display salt|sodium, energy_label_key).
- `allergen_market_rules` (region_code, allergen, must_highlight) PK (region, allergen).
- Trigramindex (pg_trgm) på canonical_ingredients.name_sv, ingredient_translations.name, recipes.title_sv; unaccent för accentokänslig sök.