Přeskočit na obsah

Datový model

Stav dokumentu: Hotovo jako referenční popis schématu — při migraci aktualizovat text tak, aby odpovídal migrations/*.sql.

i18n a veřejné čtení (Fáze 6)

  • Veřejné stránky (/cs/..., /en/...) mají číst lokalizované názvy a slugy z tabulek *_translations podle locale (herb_translations, topic_translations, processing_method_translations, region_translations, spiritual_guide_translations, plant_part_translations, storage_method_translations). Master tabulky (herbs, topics, …) drží stabilní id, vazby, enumy a historicky české textové sloupce používané jako zdroj pro migrace / seed a pro tooling.
  • DROP textových sloupců z master tabulek se nedělá v téže migraci jako přepnutí read modelu — až po auditu a samostatné migraci (viz docs/tasks/i18n-vicjazycnost-a-hreflang.md, Fáze 6).
  • Známé výjimky bez překladové tabulky (veřejný text zatím z masteru, typicky česky): žádné v okruhu veřejně renderovaného obsahu karty byliny — všechny redakční volnotextové sloupce mají dedikovanou *_translations tabulku. Hybridní pole na harvest_periods (growth_phase, best_time_of_day, weather_notes) zatím nejsou v public renderu používané; pokud začnou, doplní se buď enumy nebo do harvest_period_translations.
  • Lokalizované labely entit (Fáze 5–6): herb_translations, topic_translations, processing_method_translations, region_translations, spiritual_guide_translations (Fáze 5; migrace 0082/0083), plant_part_translations (0085), storage_method_translations (0086), recipe_translations (0090 — title, notes, steps_json, science_rationale receptů; CS seed kopíruje master herb_method_recipes; 0093 — EN katalogové titulky tam, kde existuje EN bylina + metoda), spiritual_use_translations + scientific_evidence_translations + safety_warning_translations (0091 — redakční texty kontentových bloků na kartě byliny; enumy a citační metadata zůstávají v masteru), harvest_period_translations (0092 — překlad harvest_notes u řádků sběru; master harvest_periods drží faktické signály locale-neutral). Rozšířený EN seed bylin/témat: migrace 0084 (~id % 5 = 1) a 0088 (~lichá id bez existujícího EN).

1. herbs

CREATE TABLE herbs (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  slug TEXT NOT NULL UNIQUE,
  local_name TEXT NOT NULL,
  latin_name TEXT NOT NULL,
  family TEXT,
  plant_type TEXT,
  short_description TEXT,
  full_description TEXT,
  identification_notes TEXT,
  confusion_risk_notes TEXT,
  safety_level TEXT DEFAULT 'unknown',
  beginner_friendly INTEGER DEFAULT 0,
  is_published INTEGER DEFAULT 0,
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL
);

Migrace 0007_herb_similar_and_safety_notes.sql doplňuje na herbs volitelné sloupce drug_interactions_note, phototoxicity_note (souhrnné texty 12-katalog-a-karta-byliny §1.11) a vytváří tabulku herb_similar (odkazy na podobné publikované byliny).

2. herb_names

CREATE TABLE herb_names (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  herb_id INTEGER NOT NULL,
  name TEXT NOT NULL,
  language TEXT,
  region_id INTEGER,
  type TEXT,
  FOREIGN KEY (herb_id) REFERENCES herbs(id),
  FOREIGN KEY (region_id) REFERENCES regions(id)
);

3. regions

CREATE TABLE regions (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  slug TEXT NOT NULL UNIQUE,
  name TEXT NOT NULL,
  type TEXT NOT NULL,
  parent_region_id INTEGER,
  country_code TEXT,
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL,
  FOREIGN KEY (parent_region_id) REFERENCES regions(id)
);

4. herb_regions

CREATE TABLE herb_regions (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  herb_id INTEGER NOT NULL,
  region_id INTEGER NOT NULL,
  occurrence_status TEXT DEFAULT 'unknown',
  notes TEXT,
  FOREIGN KEY (herb_id) REFERENCES herbs(id),
  FOREIGN KEY (region_id) REFERENCES regions(id)
);

5. habitats

CREATE TABLE habitats (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  slug TEXT NOT NULL UNIQUE,
  name TEXT NOT NULL,
  description TEXT
);

6. plant_parts

CREATE TABLE plant_parts (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  slug TEXT NOT NULL UNIQUE,
  name TEXT NOT NULL,
  description TEXT
);

7. harvest_periods

CREATE TABLE harvest_periods (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  herb_id INTEGER NOT NULL,
  plant_part_id INTEGER NOT NULL,
  region_id INTEGER,
  month_from INTEGER NOT NULL,
  month_to INTEGER NOT NULL,
  season TEXT,
  growth_phase TEXT,
  best_time_of_day TEXT,
  weather_notes TEXT,
  harvest_notes TEXT,
  FOREIGN KEY (herb_id) REFERENCES herbs(id),
  FOREIGN KEY (plant_part_id) REFERENCES plant_parts(id),
  FOREIGN KEY (region_id) REFERENCES regions(id)
);

Lokalizace volnotextového sloupce harvest_notes běží přes harvest_period_translations (migrace 0092_harvest_period_translations.sql) — tabulka má (harvest_period_id, locale) UNIQUE a překládá harvest_notes. CS seed kopíruje master; read model v app/db/herb-detail.server.ts používá LEFT JOIN harvest_period_translations hpt … COALESCE(hpt.harvest_notes, hp.harvest_notes) aby měl fallback na master, dokud EN řádek neexistuje. Master sloupec harvest_notes zůstává jako zdroj pro seed/tooling; DROP přijde v samostatné migraci po přepnutí admina.

8. processing_methods

CREATE TABLE processing_methods (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  slug TEXT NOT NULL UNIQUE,
  name TEXT NOT NULL,
  short_description TEXT,
  full_description TEXT,
  difficulty_level TEXT,
  required_equipment TEXT,
  safety_notes TEXT,
  typical_prep_note TEXT,
  safety_summary TEXT,
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL
);

Veřejná část webu načítá katalog z této tabulky na /zpracovani a /zpracovani/:slug; na kartě byliny se k vazbám z herb_processing_methods přidávají i short_description / full_description příslušné metody. Ukázkové delší texty pro prvních pět metod z seedu doplňuje migrace 0008_processing_method_encyclopedia.sql. Úplný výčet způsobů podle produktové specifikace (10-product-spec.md §7) zřizuje migrace 0009_processing_methods_product_spec.sql (u nových řádků je zatím obvykle jen krátký popis). Delší encyklopedické texty, obtížnost, vybavení a bezpečnostní poznámky doplňuje migrace 0019_catalog_topic_recipes_processing.sql; orientační čas přípravy a jednovětý bezpečnostní souhrn u vybraných metod — migrace 0024_processing_method_prep_safety_summary.sql.

8.1. Slugy katalogu (processing_methods.slug)

SlugNázev (UI)Odpovídá §7 produktovky
cajČajčaj / nálev
odvarOdvarodvar
macerat-studenyMacerát za studenamacerát za studena
tinkturaTinkturatinktura
glyceritGlyceritglycerit
olejBylinný olejbylinný olej
mastMastmast
balzamBalzámbalzám
sirupSirupsirup
medMedbylinný med
ocetBylinný ocetbylinný ocet
vinoBylinné vínobylinné víno
likerBylinný likérbylinný likér
vykurovadloVykuřovadlovykuřovadlo
svazekBylinný svazekbylinný svazek
koupelKoupelkoupel
obkladObkladobklad
inhalaceInhalaceinhalace
prasekPrášekprášek
kapsleKapslekapsle
esenceEsenceesence
hydrolatHydroláthydrolát
esencialni-olejEsenciální olejesenciální olej
fermentaceFermentacefermentace
kulinarskeKulinářské použitíkulinářské použití
salatSalátnavíc v datech (syrová příprava); obecné kulinářské užití má slug kulinarske

Filtr katalogu bylin: query param pm=<slug> (viz 23-api-and-routes.md).

9. herb_processing_methods

CREATE TABLE herb_processing_methods (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  herb_id INTEGER NOT NULL,
  processing_method_id INTEGER NOT NULL,
  plant_part_id INTEGER,
  suitability TEXT DEFAULT 'unknown',
  purpose TEXT,
  traditional_use INTEGER DEFAULT 0,
  scientific_use INTEGER DEFAULT 0,
  safety_notes TEXT,
  recipe_notes TEXT,
  FOREIGN KEY (herb_id) REFERENCES herbs(id),
  FOREIGN KEY (processing_method_id) REFERENCES processing_methods(id),
  FOREIGN KEY (plant_part_id) REFERENCES plant_parts(id)
);

9.1 herb_method_recipes

Editorský recept / postup krok za krokem u konkrétního řádku vazby bylina ↔ způsob (herb_processing_methods.id). Migrace 0015_herb_method_recipes.sql.

CREATE TABLE herb_method_recipes (
	id INTEGER PRIMARY KEY AUTOINCREMENT,
	herb_processing_method_id INTEGER NOT NULL UNIQUE,
	title TEXT NOT NULL,
	steps_json TEXT NOT NULL,
	time_min INTEGER,
	difficulty TEXT,
	notes TEXT,
	is_published INTEGER NOT NULL DEFAULT 0,
	created_at TEXT NOT NULL,
	updated_at TEXT NOT NULL,
	FOREIGN KEY (herb_processing_method_id) REFERENCES herb_processing_methods(id) ON DELETE CASCADE
);

Sloupec steps_json ukládá JSON pole řetězců (jednotlivé kroky). Veřejný web zobrazuje jen řádky s is_published = 1.

Lokalizace textových polí běží přes recipe_translations (migrace 0090_recipe_translations.sql) — tabulka má (herb_method_recipe_id, locale) UNIQUE a překlady title, notes, steps_json, science_rationale. CS seed kopíruje master; migrace 0093 doplňuje EN řádky s anglickým titulkem (z EN herb_translations / processing_method_translations / plant_part_translations), kroky a rationale zatím často z CS / masteru — plný EN text se dohrává ručně; read modely (recipes.server.ts, herb-detail.server.ts, processing-methods.server.ts) používají LEFT JOIN recipe_translations rt … COALESCE(rt.*, hmr.*) aby měly fallback na master, dokud EN řádek neexistuje. Master sloupce title, notes, steps_json, science_rationale_cs zůstávají jako zdroj pro seed/tooling; DROP přijde v samostatné migraci po přepnutí admina.

10. topics

CREATE TABLE topics (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  slug TEXT NOT NULL UNIQUE,
  name TEXT NOT NULL,
  type TEXT NOT NULL,
  parent_topic_id INTEGER,
  description TEXT,
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL,
  FOREIGN KEY (parent_topic_id) REFERENCES topics(id)
);

11. herb_topic_links

CREATE TABLE herb_topic_links (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  herb_id INTEGER NOT NULL,
  topic_id INTEGER NOT NULL,
  link_type TEXT NOT NULL,
  evidence_level TEXT DEFAULT 'unknown',
  source_type TEXT,
  notes TEXT,
  FOREIGN KEY (herb_id) REFERENCES herbs(id),
  FOREIGN KEY (topic_id) REFERENCES topics(id)
);

Tabulka a základní seed témat / vazeb jsou v migraci 0011_herb_topic_links_seed.sql; vědecké vazby 0012_…, 0013_…; ukázkové typy kulináře / kosmetika / aromaterapie 0014_herb_topic_lifestyle_links.sql.

12. spiritual_uses

CREATE TABLE spiritual_uses (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  herb_id INTEGER NOT NULL,
  title TEXT NOT NULL,
  category TEXT,
  description TEXT NOT NULL,
  cultural_context TEXT,
  use_form TEXT,
  related_topic_id INTEGER,
  claim_strength TEXT,
  source_note TEXT,
  claim_nature TEXT,
  facets TEXT,
  is_published INTEGER DEFAULT 0,
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL,
  FOREIGN KEY (herb_id) REFERENCES herbs(id),
  FOREIGN KEY (related_topic_id) REFERENCES topics(id)
);

Sloupce claim_nature (typ tvrzení dle §1) a facets (JSON pole slugů podtypů dle §2) přidává migrace 0010_spiritual_nature_facets.sql. Povolené hodnoty a české popisky: app/lib/spiritual-content-labels.ts (návrhová povaha záznamu) a app/lib/claim-labels.ts (síla tvrzení / legacy claim_strength, vazby téma–bylina, vědecké řádky v UI).

13. scientific_evidence

CREATE TABLE scientific_evidence (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  herb_id INTEGER NOT NULL,
  plant_part_id INTEGER,
  topic_id INTEGER,
  active_compound TEXT,
  claim_summary TEXT NOT NULL,
  evidence_level TEXT NOT NULL,
  study_type TEXT NOT NULL,
  source_title TEXT,
  source_url TEXT,
  doi TEXT,
  publication_year INTEGER,
  authors TEXT,
  journal TEXT,
  limitations TEXT,
  dosage_notes TEXT,
  preparation_form TEXT,
  is_published INTEGER DEFAULT 0,
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL,
  FOREIGN KEY (herb_id) REFERENCES herbs(id),
  FOREIGN KEY (plant_part_id) REFERENCES plant_parts(id),
  FOREIGN KEY (topic_id) REFERENCES topics(id)
);

14. images

CREATE TABLE images (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  herb_id INTEGER,
  r2_key TEXT NOT NULL,
  public_url TEXT,
  image_type TEXT NOT NULL,
  alt_text TEXT,
  caption TEXT,
  photographer TEXT,
  license TEXT,
  source_url TEXT,
  width INTEGER,
  height INTEGER,
  sort_order INTEGER DEFAULT 0,
  created_at TEXT NOT NULL,
  FOREIGN KEY (herb_id) REFERENCES herbs(id)
);

Veřejné zobrazení: má-li řádek vyplněné public_url, použije se přímo (externí host). Jinak Worker servíruje objekt z R2 podle r2_key na cestě /media/<r2_key> (složky v klíči musí odpovídat objektům v bucketu). Pro čistě externí obrázky může r2_key sloužit jen jako stabilní identifikátor (např. prefix external/…), viz seed v migraci 0002. První sadu skutečných objektů v R2 pro tři byliny přidává migrace 0022_catalog_r2_seed_three_herbs.sql a skripty r2:seed-catalog-starter:* v kořenovém package.json — postup v tasks/obrazky-katalog-r2-seed.md.

15. safety_warnings

CREATE TABLE safety_warnings (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  herb_id INTEGER NOT NULL,
  warning_type TEXT NOT NULL,
  severity TEXT NOT NULL,
  title TEXT NOT NULL,
  description TEXT NOT NULL,
  source_url TEXT,
  created_at TEXT NOT NULL,
  FOREIGN KEY (herb_id) REFERENCES herbs(id)
);

16. storage_methods a herb_storage (skladování, 12-katalog-a-karta-byliny §1.5)

Katalog typických postupů uchování a vazba na bylinu (doplněno v migraci 0003_storage.sql). Migrace 0086_storage_method_translations.sql přidává storage_method_translations (sdílený slug v masteru; překládá se name a short_description) — read modely v herb-detail.server.ts čtou přes LEFT JOIN s COALESCE na master jako fallback.

CREATE TABLE storage_methods (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  slug TEXT NOT NULL UNIQUE,
  name TEXT NOT NULL,
  short_description TEXT,
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL
);

CREATE TABLE herb_storage (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  herb_id INTEGER NOT NULL,
  storage_method_id INTEGER NOT NULL,
  plant_part_id INTEGER,
  shelf_life_note TEXT,
  light_sensitivity TEXT,
  moisture_sensitivity TEXT,
  safety_note TEXT,
  sort_order INTEGER DEFAULT 0,
  FOREIGN KEY (herb_id) REFERENCES herbs(id),
  FOREIGN KEY (storage_method_id) REFERENCES storage_methods(id),
  FOREIGN KEY (plant_part_id) REFERENCES plant_parts(id)
);

17. herb_similar (podobné byliny, 12-katalog-a-karta-byliny §1.2)

Navázání publikovaných bylin navzájem; na kartě se zobrazí jen cílové byliny s is_published = 1. Migrace: 0007_herb_similar_and_safety_notes.sql.

CREATE TABLE herb_similar (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  herb_id INTEGER NOT NULL,
  related_herb_id INTEGER NOT NULL,
  sort_order INTEGER NOT NULL DEFAULT 0,
  note TEXT,
  FOREIGN KEY (herb_id) REFERENCES herbs(id),
  FOREIGN KEY (related_herb_id) REFERENCES herbs(id),
  UNIQUE (herb_id, related_herb_id)
);

18. spiritual_guides

Strukturované rituální / spirituální návody mimo volné záznamy spiritual_uses na kartě byliny. Migrace 0016_spiritual_guides.sql.

CREATE TABLE spiritual_guides (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  slug TEXT NOT NULL UNIQUE,
  title TEXT NOT NULL,
  intent TEXT,
  category TEXT,
  intro TEXT NOT NULL,
  steps_json TEXT NOT NULL,
  materials_json TEXT,
  safety_notes TEXT,
  references_note TEXT,
  herb_id INTEGER,
  is_published INTEGER NOT NULL DEFAULT 0,
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL,
  FOREIGN KEY (herb_id) REFERENCES herbs(id) ON DELETE SET NULL
);

steps_json a materials_json — JSON pole řetězců. Veřejný web zobrazuje jen is_published = 1 (/ritualy, /ritualy/:slug).