Consolidate the application, culinary data model, read-only runtime, and registry-backed deployment.
169 lines
7.1 KiB
SQL
169 lines
7.1 KiB
SQL
PRAGMA foreign_keys = ON;
|
|
|
|
CREATE TABLE units (
|
|
id TEXT PRIMARY KEY, name TEXT NOT NULL, symbol TEXT NOT NULL,
|
|
dimension TEXT NOT NULL, system TEXT NOT NULL,
|
|
base_unit_id TEXT REFERENCES units(id), factor REAL, offset REAL
|
|
);
|
|
|
|
CREATE TABLE ingredients (
|
|
id TEXT PRIMARY KEY, schema_version INTEGER NOT NULL, name TEXT NOT NULL,
|
|
status TEXT NOT NULL, categories_json TEXT NOT NULL DEFAULT '[]',
|
|
tags_json TEXT NOT NULL DEFAULT '[]', description TEXT,
|
|
source_json TEXT NOT NULL DEFAULT '{}', deleted_at TEXT
|
|
);
|
|
|
|
CREATE TABLE ingredient_aliases (
|
|
ingredient_id TEXT NOT NULL REFERENCES ingredients(id) ON DELETE CASCADE,
|
|
name TEXT NOT NULL, kind TEXT, PRIMARY KEY (ingredient_id, name)
|
|
);
|
|
|
|
CREATE TABLE equipment (
|
|
id TEXT PRIMARY KEY, name TEXT NOT NULL, category TEXT, notes TEXT
|
|
);
|
|
|
|
CREATE TABLE prep_actions (
|
|
id TEXT PRIMARY KEY, name TEXT NOT NULL, action_type TEXT NOT NULL,
|
|
default_yield_factor REAL CHECK(default_yield_factor > 0), notes TEXT
|
|
);
|
|
|
|
CREATE TABLE recipes (
|
|
id TEXT PRIMARY KEY, schema_version INTEGER NOT NULL,
|
|
save_version INTEGER NOT NULL DEFAULT 1, title TEXT NOT NULL, summary TEXT,
|
|
categories_json TEXT NOT NULL DEFAULT '[]', tags_json TEXT NOT NULL DEFAULT '[]',
|
|
yield_quantity REAL NOT NULL, yield_unit_id TEXT NOT NULL REFERENCES units(id),
|
|
yield_servings REAL, yield_basis TEXT, scaling_mode TEXT, scaling_basis_id TEXT,
|
|
scaling_basis_quantity REAL, scaling_basis_unit_id TEXT REFERENCES units(id),
|
|
notes_json TEXT NOT NULL DEFAULT '[]', source_json TEXT NOT NULL DEFAULT '{}',
|
|
auto_yield INTEGER NOT NULL DEFAULT 0, station TEXT, deleted_at TEXT,
|
|
cover_media_url TEXT
|
|
);
|
|
|
|
CREATE TABLE recipe_components (
|
|
recipe_id TEXT NOT NULL REFERENCES recipes(id) ON DELETE CASCADE,
|
|
id TEXT NOT NULL, position INTEGER NOT NULL, name TEXT NOT NULL,
|
|
notes_json TEXT NOT NULL DEFAULT '[]', PRIMARY KEY (recipe_id, id)
|
|
);
|
|
|
|
CREATE TABLE recipe_items (
|
|
recipe_id TEXT NOT NULL, component_id TEXT NOT NULL, id TEXT NOT NULL,
|
|
position INTEGER NOT NULL, ingredient_id TEXT REFERENCES ingredients(id),
|
|
subrecipe_id TEXT REFERENCES recipes(id), quantity REAL NOT NULL,
|
|
unit_id TEXT NOT NULL REFERENCES units(id), percentage REAL,
|
|
basis_member INTEGER NOT NULL DEFAULT 0, optional INTEGER NOT NULL DEFAULT 0,
|
|
notes TEXT, nutrition_retention_factor REAL NOT NULL DEFAULT 1
|
|
CHECK(nutrition_retention_factor >= 0 AND nutrition_retention_factor <= 1),
|
|
PRIMARY KEY (recipe_id, id),
|
|
FOREIGN KEY (recipe_id, component_id)
|
|
REFERENCES recipe_components(recipe_id, id) ON DELETE CASCADE,
|
|
CHECK ((ingredient_id IS NOT NULL) <> (subrecipe_id IS NOT NULL))
|
|
);
|
|
|
|
CREATE TABLE ingredient_prep_actions (
|
|
ingredient_id TEXT NOT NULL REFERENCES ingredients(id) ON DELETE CASCADE,
|
|
action_id TEXT NOT NULL REFERENCES prep_actions(id),
|
|
yield_factor REAL NOT NULL CHECK(yield_factor > 0), notes TEXT,
|
|
PRIMARY KEY (ingredient_id, action_id)
|
|
);
|
|
|
|
CREATE TABLE item_prep_actions (
|
|
recipe_id TEXT NOT NULL, item_id TEXT NOT NULL, position INTEGER NOT NULL,
|
|
action_id TEXT NOT NULL REFERENCES prep_actions(id),
|
|
yield_factor REAL CHECK(yield_factor > 0), notes TEXT,
|
|
PRIMARY KEY (recipe_id, item_id, position),
|
|
FOREIGN KEY (recipe_id, item_id) REFERENCES recipe_items(recipe_id, id) ON DELETE CASCADE
|
|
);
|
|
|
|
CREATE TABLE recipe_steps (
|
|
recipe_id TEXT NOT NULL REFERENCES recipes(id) ON DELETE CASCADE,
|
|
id TEXT NOT NULL, position INTEGER NOT NULL, instruction TEXT NOT NULL,
|
|
critical_control_point INTEGER NOT NULL DEFAULT 0,
|
|
PRIMARY KEY (recipe_id, id), UNIQUE (recipe_id, position)
|
|
);
|
|
|
|
CREATE TABLE recipe_equipment (
|
|
recipe_id TEXT NOT NULL REFERENCES recipes(id) ON DELETE CASCADE,
|
|
equipment_id TEXT NOT NULL REFERENCES equipment(id),
|
|
PRIMARY KEY (recipe_id, equipment_id)
|
|
);
|
|
|
|
CREATE TABLE step_equipment (
|
|
recipe_id TEXT NOT NULL, step_id TEXT NOT NULL,
|
|
equipment_id TEXT NOT NULL REFERENCES equipment(id),
|
|
PRIMARY KEY (recipe_id, step_id, equipment_id),
|
|
FOREIGN KEY (recipe_id, step_id) REFERENCES recipe_steps(recipe_id, id) ON DELETE CASCADE
|
|
);
|
|
|
|
CREATE TABLE ingredient_measure_conversions (
|
|
ingredient_id TEXT NOT NULL REFERENCES ingredients(id) ON DELETE CASCADE,
|
|
id TEXT NOT NULL, from_quantity REAL NOT NULL,
|
|
from_unit_id TEXT NOT NULL REFERENCES units(id), to_quantity REAL NOT NULL,
|
|
to_unit_id TEXT NOT NULL REFERENCES units(id), state TEXT,
|
|
source_json TEXT NOT NULL, PRIMARY KEY (ingredient_id, id)
|
|
);
|
|
|
|
CREATE TABLE ingredient_density_measurements (
|
|
ingredient_id TEXT NOT NULL REFERENCES ingredients(id) ON DELETE CASCADE,
|
|
id TEXT NOT NULL, mass_quantity REAL NOT NULL,
|
|
mass_unit_id TEXT NOT NULL REFERENCES units(id), volume_quantity REAL NOT NULL,
|
|
volume_unit_id TEXT NOT NULL REFERENCES units(id), temperature_c REAL,
|
|
state TEXT, source_json TEXT NOT NULL, PRIMARY KEY (ingredient_id, id)
|
|
);
|
|
|
|
CREATE TABLE recipe_measure_conversions (
|
|
recipe_id TEXT NOT NULL REFERENCES recipes(id) ON DELETE CASCADE,
|
|
id TEXT NOT NULL, from_quantity REAL NOT NULL CHECK(from_quantity > 0),
|
|
from_unit_id TEXT NOT NULL REFERENCES units(id),
|
|
to_quantity REAL NOT NULL CHECK(to_quantity > 0),
|
|
to_unit_id TEXT NOT NULL REFERENCES units(id), notes TEXT,
|
|
source_json TEXT NOT NULL DEFAULT '{}', PRIMARY KEY (recipe_id, id)
|
|
);
|
|
|
|
CREATE TABLE purchase_items (
|
|
id TEXT PRIMARY KEY, ingredient_id TEXT NOT NULL REFERENCES ingredients(id),
|
|
name TEXT NOT NULL, brand TEXT, supplier_id TEXT, supplier_sku TEXT,
|
|
status TEXT NOT NULL, package_quantity REAL NOT NULL,
|
|
package_unit_id TEXT NOT NULL REFERENCES units(id),
|
|
units_per_case INTEGER NOT NULL DEFAULT 1,
|
|
usable_yield_factor REAL NOT NULL DEFAULT 1
|
|
);
|
|
|
|
CREATE TABLE price_observations (
|
|
purchase_item_id TEXT NOT NULL REFERENCES purchase_items(id) ON DELETE CASCADE,
|
|
effective_at TEXT NOT NULL, currency TEXT NOT NULL, amount REAL NOT NULL,
|
|
source_json TEXT NOT NULL,
|
|
PRIMARY KEY (purchase_item_id, effective_at, currency)
|
|
);
|
|
|
|
CREATE TABLE source_mappings (
|
|
id TEXT PRIMARY KEY, subject_type TEXT NOT NULL, subject_id TEXT NOT NULL,
|
|
mapping_type TEXT NOT NULL, status TEXT NOT NULL,
|
|
source_json TEXT NOT NULL, nutrition_json TEXT
|
|
);
|
|
|
|
CREATE TABLE collections (
|
|
id TEXT PRIMARY KEY, name TEXT NOT NULL, description TEXT,
|
|
source_json TEXT NOT NULL, deleted_at TEXT
|
|
);
|
|
|
|
CREATE TABLE collection_recipes (
|
|
collection_id TEXT NOT NULL REFERENCES collections(id) ON DELETE CASCADE,
|
|
recipe_id TEXT NOT NULL REFERENCES recipes(id), position INTEGER NOT NULL,
|
|
PRIMARY KEY (collection_id, recipe_id)
|
|
);
|
|
|
|
CREATE TABLE recipe_media (
|
|
recipe_id TEXT NOT NULL REFERENCES recipes(id) ON DELETE CASCADE,
|
|
id TEXT NOT NULL, step_id TEXT, media_type TEXT NOT NULL
|
|
CHECK(media_type IN ('image', 'video')),
|
|
url TEXT NOT NULL, caption TEXT, position INTEGER NOT NULL,
|
|
PRIMARY KEY (recipe_id, id),
|
|
FOREIGN KEY (recipe_id, step_id) REFERENCES recipe_steps(recipe_id, id) ON DELETE CASCADE
|
|
);
|
|
|
|
CREATE INDEX recipe_items_ingredient_idx ON recipe_items(ingredient_id);
|
|
CREATE INDEX recipe_items_subrecipe_idx ON recipe_items(subrecipe_id);
|
|
CREATE INDEX purchase_items_ingredient_idx ON purchase_items(ingredient_id);
|
|
CREATE INDEX source_mappings_subject_idx ON source_mappings(subject_type, subject_id);
|
|
CREATE INDEX recipe_media_recipe_idx ON recipe_media(recipe_id, position);
|