Files
formulation/migrations/001_initial.sql
T
nicholas 816b28e179
Build & Deploy Formulation / Build & Push Image (push) Successful in 15s
Build & Deploy Formulation / deploy (push) Successful in 12s
build and deploy Formulation application
Consolidate the application, culinary data model, read-only runtime, and registry-backed deployment.
2026-08-13 18:08:25 -05:00

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);