-- +goose Up -- --------------------------------------------------------------------------- -- Extensions -- --------------------------------------------------------------------------- CREATE EXTENSION IF NOT EXISTS pgcrypto; CREATE EXTENSION IF NOT EXISTS pg_trgm; -- --------------------------------------------------------------------------- -- UUID v7 generator (time-ordered, millisecond precision). -- Structure: 48-bit unix_ts_ms | 4-bit version (0111) | 12-bit rand_a | 2-bit variant (10) | 62-bit rand_b -- --------------------------------------------------------------------------- -- +goose StatementBegin CREATE OR REPLACE FUNCTION uuid_generate_v7() RETURNS uuid AS $$ DECLARE unix_ts_ms bytea; uuid_bytes bytea; BEGIN -- 48-bit Unix timestamp in milliseconds. -- int8send produces 8 big-endian bytes; skip the first 2 zero bytes to get 6. unix_ts_ms = substring(int8send(floor(extract(epoch from clock_timestamp()) * 1000)::bigint) from 3); -- Use a random v4 UUID as the source of random bits for rand_a and rand_b. uuid_bytes = uuid_send(gen_random_uuid()); -- Overwrite bytes 0-5 with the timestamp (positions 1-6 in 1-indexed bytea). uuid_bytes = overlay(uuid_bytes placing unix_ts_ms from 1 for 6); -- Set version nibble (bits 48-51) to 0111 (7). uuid_bytes = set_bit(uuid_bytes, 48, 0); uuid_bytes = set_bit(uuid_bytes, 49, 1); uuid_bytes = set_bit(uuid_bytes, 50, 1); uuid_bytes = set_bit(uuid_bytes, 51, 1); -- Variant bits (64-65) stay at 10 as inherited from gen_random_uuid(). RETURN encode(uuid_bytes, 'hex')::uuid; END $$ LANGUAGE plpgsql VOLATILE; -- +goose StatementEnd -- --------------------------------------------------------------------------- -- Enums -- --------------------------------------------------------------------------- CREATE TYPE user_plan AS ENUM ('free', 'paid'); CREATE TYPE user_gender AS ENUM ('male', 'female'); CREATE TYPE user_goal AS ENUM ('lose', 'maintain', 'gain'); CREATE TYPE activity_level AS ENUM ('low', 'moderate', 'high'); CREATE TYPE recipe_source AS ENUM ('spoonacular', 'ai', 'user'); CREATE TYPE recipe_difficulty AS ENUM ('easy', 'medium', 'hard'); -- --------------------------------------------------------------------------- -- users -- --------------------------------------------------------------------------- CREATE TABLE users ( id UUID PRIMARY KEY DEFAULT uuid_generate_v7(), firebase_uid VARCHAR(128) NOT NULL UNIQUE, email VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL DEFAULT '', avatar_url TEXT, height_cm SMALLINT, weight_kg DECIMAL(5,2), date_of_birth DATE, gender user_gender, activity activity_level, goal user_goal, daily_calories INTEGER, plan user_plan NOT NULL DEFAULT 'free', preferences JSONB NOT NULL DEFAULT '{}'::jsonb, refresh_token TEXT, token_expires_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE INDEX idx_users_firebase_uid ON users (firebase_uid); CREATE INDEX idx_users_email ON users (email); -- --------------------------------------------------------------------------- -- languages -- --------------------------------------------------------------------------- CREATE TABLE languages ( code VARCHAR(10) PRIMARY KEY, native_name TEXT NOT NULL, english_name TEXT NOT NULL, is_active BOOLEAN NOT NULL DEFAULT true, sort_order SMALLINT NOT NULL DEFAULT 0 ); -- --------------------------------------------------------------------------- -- units + unit_translations -- --------------------------------------------------------------------------- CREATE TABLE units ( code VARCHAR(20) PRIMARY KEY, sort_order SMALLINT NOT NULL DEFAULT 0 ); CREATE TABLE unit_translations ( unit_code VARCHAR(20) NOT NULL REFERENCES units(code) ON DELETE CASCADE, lang VARCHAR(10) NOT NULL, name TEXT NOT NULL, PRIMARY KEY (unit_code, lang) ); -- --------------------------------------------------------------------------- -- product_categories + product_category_translations -- --------------------------------------------------------------------------- CREATE TABLE product_categories ( slug VARCHAR(50) PRIMARY KEY, name TEXT NOT NULL, sort_order SMALLINT NOT NULL DEFAULT 0 ); CREATE TABLE product_category_translations ( product_category_slug VARCHAR(50) NOT NULL REFERENCES product_categories(slug) ON DELETE CASCADE, lang VARCHAR(10) NOT NULL, name TEXT NOT NULL, PRIMARY KEY (product_category_slug, lang) ); -- --------------------------------------------------------------------------- -- products (canonical catalog) -- --------------------------------------------------------------------------- CREATE TABLE products ( id UUID PRIMARY KEY DEFAULT uuid_generate_v7(), canonical_name VARCHAR(255) NOT NULL, category VARCHAR(50) REFERENCES product_categories(slug), default_unit VARCHAR(20) REFERENCES units(code), barcode TEXT UNIQUE, calories_per_100g DECIMAL(8,2), protein_per_100g DECIMAL(8,2), fat_per_100g DECIMAL(8,2), carbs_per_100g DECIMAL(8,2), fiber_per_100g DECIMAL(8,2), storage_days INTEGER, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), CONSTRAINT uq_product_canonical_name UNIQUE (canonical_name) ); CREATE INDEX idx_products_canonical_name ON products (canonical_name); CREATE INDEX idx_products_category ON products (category); CREATE INDEX idx_products_barcode ON products (barcode) WHERE barcode IS NOT NULL; CREATE INDEX idx_products_fts ON products USING GIN (to_tsvector('english', canonical_name)); -- --------------------------------------------------------------------------- -- product_aliases -- --------------------------------------------------------------------------- CREATE TABLE product_aliases ( product_id UUID NOT NULL REFERENCES products(id) ON DELETE CASCADE, lang VARCHAR(10) NOT NULL, alias TEXT NOT NULL, PRIMARY KEY (product_id, lang, alias) ); CREATE INDEX idx_product_aliases_lookup ON product_aliases (product_id, lang); CREATE INDEX idx_product_aliases_trgm ON product_aliases USING GIN (alias gin_trgm_ops); CREATE INDEX idx_product_aliases_fts ON product_aliases USING GIN (to_tsvector('simple', alias)); -- --------------------------------------------------------------------------- -- cuisines + cuisine_translations -- --------------------------------------------------------------------------- CREATE TABLE cuisines ( slug VARCHAR(50) PRIMARY KEY, name TEXT NOT NULL, sort_order SMALLINT NOT NULL DEFAULT 0 ); CREATE TABLE cuisine_translations ( cuisine_slug VARCHAR(50) NOT NULL REFERENCES cuisines(slug) ON DELETE CASCADE, lang VARCHAR(10) NOT NULL, name TEXT NOT NULL, PRIMARY KEY (cuisine_slug, lang) ); -- --------------------------------------------------------------------------- -- tags + tag_translations -- --------------------------------------------------------------------------- CREATE TABLE tags ( slug VARCHAR(100) PRIMARY KEY, name TEXT NOT NULL, sort_order SMALLINT NOT NULL DEFAULT 0 ); CREATE TABLE tag_translations ( tag_slug VARCHAR(100) NOT NULL REFERENCES tags(slug) ON DELETE CASCADE, lang VARCHAR(10) NOT NULL, name TEXT NOT NULL, PRIMARY KEY (tag_slug, lang) ); -- --------------------------------------------------------------------------- -- dish_categories + dish_category_translations -- --------------------------------------------------------------------------- CREATE TABLE dish_categories ( slug VARCHAR(50) PRIMARY KEY, name TEXT NOT NULL, sort_order SMALLINT NOT NULL DEFAULT 0 ); CREATE TABLE dish_category_translations ( category_slug VARCHAR(50) NOT NULL REFERENCES dish_categories(slug) ON DELETE CASCADE, lang VARCHAR(10) NOT NULL, name TEXT NOT NULL, PRIMARY KEY (category_slug, lang) ); -- --------------------------------------------------------------------------- -- dishes + dish_translations + dish_tags -- --------------------------------------------------------------------------- CREATE TABLE dishes ( id UUID PRIMARY KEY DEFAULT uuid_generate_v7(), cuisine_slug VARCHAR(50) REFERENCES cuisines(slug) ON DELETE SET NULL, category_slug VARCHAR(50) REFERENCES dish_categories(slug) ON DELETE SET NULL, name TEXT NOT NULL, description TEXT, image_url TEXT, avg_rating DECIMAL(3,2) NOT NULL DEFAULT 0.0, review_count INTEGER NOT NULL DEFAULT 0, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE INDEX idx_dishes_cuisine ON dishes (cuisine_slug); CREATE INDEX idx_dishes_category ON dishes (category_slug); CREATE INDEX idx_dishes_rating ON dishes (avg_rating DESC); CREATE INDEX idx_dishes_name_fts ON dishes USING GIN (to_tsvector('english', name)); CREATE INDEX idx_dishes_name_trgm ON dishes USING GIN (name gin_trgm_ops); CREATE TABLE dish_translations ( dish_id UUID NOT NULL REFERENCES dishes(id) ON DELETE CASCADE, lang VARCHAR(10) NOT NULL, name TEXT NOT NULL, description TEXT, PRIMARY KEY (dish_id, lang) ); CREATE INDEX idx_dish_translations_name_fts ON dish_translations USING GIN (to_tsvector('simple', name)); CREATE INDEX idx_dish_translations_name_trgm ON dish_translations USING GIN (name gin_trgm_ops); CREATE TABLE dish_tags ( dish_id UUID NOT NULL REFERENCES dishes(id) ON DELETE CASCADE, tag_slug VARCHAR(100) NOT NULL REFERENCES tags(slug) ON DELETE CASCADE, PRIMARY KEY (dish_id, tag_slug) ); -- --------------------------------------------------------------------------- -- recipes (one cooking variant of a dish) -- --------------------------------------------------------------------------- CREATE TABLE recipes ( id UUID PRIMARY KEY DEFAULT uuid_generate_v7(), dish_id UUID NOT NULL REFERENCES dishes(id) ON DELETE CASCADE, source recipe_source NOT NULL DEFAULT 'ai', difficulty recipe_difficulty, prep_time_min INTEGER, cook_time_min INTEGER, servings SMALLINT, calories_per_serving DECIMAL(8,2), protein_per_serving DECIMAL(8,2), fat_per_serving DECIMAL(8,2), carbs_per_serving DECIMAL(8,2), fiber_per_serving DECIMAL(8,2), created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE INDEX idx_recipes_dish_id ON recipes (dish_id); CREATE INDEX idx_recipes_difficulty ON recipes (difficulty); CREATE INDEX idx_recipes_prep_time ON recipes (prep_time_min); CREATE INDEX idx_recipes_calories ON recipes (calories_per_serving); CREATE INDEX idx_recipes_source ON recipes (source); -- --------------------------------------------------------------------------- -- recipe_translations -- --------------------------------------------------------------------------- CREATE TABLE recipe_translations ( recipe_id UUID NOT NULL REFERENCES recipes(id) ON DELETE CASCADE, lang VARCHAR(10) NOT NULL, notes TEXT, PRIMARY KEY (recipe_id, lang) ); -- --------------------------------------------------------------------------- -- recipe_products + recipe_product_translations -- --------------------------------------------------------------------------- CREATE TABLE recipe_products ( id UUID PRIMARY KEY DEFAULT uuid_generate_v7(), recipe_id UUID NOT NULL REFERENCES recipes(id) ON DELETE CASCADE, product_id UUID REFERENCES products(id) ON DELETE SET NULL, name TEXT NOT NULL, amount DECIMAL(10,2) NOT NULL DEFAULT 0, unit_code VARCHAR(20), is_optional BOOLEAN NOT NULL DEFAULT false, sort_order SMALLINT NOT NULL DEFAULT 0 ); CREATE INDEX idx_recipe_products_recipe_id ON recipe_products (recipe_id); CREATE TABLE recipe_product_translations ( ri_id UUID NOT NULL REFERENCES recipe_products(id) ON DELETE CASCADE, lang VARCHAR(10) NOT NULL, name TEXT NOT NULL, PRIMARY KEY (ri_id, lang) ); -- --------------------------------------------------------------------------- -- recipe_steps + recipe_step_translations -- --------------------------------------------------------------------------- CREATE TABLE recipe_steps ( id UUID PRIMARY KEY DEFAULT uuid_generate_v7(), recipe_id UUID NOT NULL REFERENCES recipes(id) ON DELETE CASCADE, step_number SMALLINT NOT NULL, timer_seconds INTEGER, image_url TEXT, description TEXT NOT NULL, UNIQUE (recipe_id, step_number) ); CREATE INDEX idx_recipe_steps_recipe_id ON recipe_steps (recipe_id); CREATE TABLE recipe_step_translations ( step_id UUID NOT NULL REFERENCES recipe_steps(id) ON DELETE CASCADE, lang VARCHAR(10) NOT NULL, description TEXT NOT NULL, PRIMARY KEY (step_id, lang) ); -- --------------------------------------------------------------------------- -- user_products (user fridge / pantry items) -- --------------------------------------------------------------------------- CREATE TABLE user_products ( id UUID PRIMARY KEY DEFAULT uuid_generate_v7(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, primary_product_id UUID REFERENCES products(id), name TEXT NOT NULL, quantity DECIMAL(10,2) NOT NULL DEFAULT 1, unit TEXT NOT NULL DEFAULT 'pcs' REFERENCES units(code), category TEXT, storage_days INT NOT NULL DEFAULT 7, added_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE INDEX idx_user_products_user_id ON user_products (user_id); -- --------------------------------------------------------------------------- -- user_product_components (M2M: composite user product ↔ catalog products) -- --------------------------------------------------------------------------- CREATE TABLE user_product_components ( user_product_id UUID NOT NULL REFERENCES user_products(id) ON DELETE CASCADE, product_id UUID NOT NULL REFERENCES products(id) ON DELETE CASCADE, amount_per_100g DECIMAL(10,2), PRIMARY KEY (user_product_id, product_id) ); -- --------------------------------------------------------------------------- -- user_saved_recipes -- --------------------------------------------------------------------------- CREATE TABLE user_saved_recipes ( id UUID PRIMARY KEY DEFAULT uuid_generate_v7(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, recipe_id UUID NOT NULL REFERENCES recipes(id) ON DELETE CASCADE, saved_at TIMESTAMPTZ NOT NULL DEFAULT now(), UNIQUE (user_id, recipe_id) ); CREATE INDEX idx_user_saved_recipes_user_id ON user_saved_recipes (user_id, saved_at DESC); -- --------------------------------------------------------------------------- -- menu_plans + menu_items + shopping_lists -- --------------------------------------------------------------------------- CREATE TABLE menu_plans ( id UUID PRIMARY KEY DEFAULT uuid_generate_v7(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, week_start DATE NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), UNIQUE (user_id, week_start) ); CREATE TABLE menu_items ( id UUID PRIMARY KEY DEFAULT uuid_generate_v7(), menu_plan_id UUID NOT NULL REFERENCES menu_plans(id) ON DELETE CASCADE, day_of_week INT NOT NULL CHECK (day_of_week BETWEEN 1 AND 7), meal_type TEXT NOT NULL CHECK (meal_type IN ('breakfast','lunch','dinner')), recipe_id UUID REFERENCES recipes(id) ON DELETE SET NULL, dish_id UUID REFERENCES dishes(id) ON DELETE SET NULL, recipe_data JSONB, UNIQUE (menu_plan_id, day_of_week, meal_type) ); CREATE TABLE shopping_lists ( id UUID PRIMARY KEY DEFAULT uuid_generate_v7(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, menu_plan_id UUID REFERENCES menu_plans(id) ON DELETE CASCADE, items JSONB NOT NULL DEFAULT '[]', generated_at TIMESTAMPTZ NOT NULL DEFAULT now(), UNIQUE (user_id, menu_plan_id) ); -- --------------------------------------------------------------------------- -- dish_recognition_jobs -- --------------------------------------------------------------------------- CREATE TABLE dish_recognition_jobs ( id UUID PRIMARY KEY DEFAULT uuid_generate_v7(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, user_plan TEXT NOT NULL, image_base64 TEXT NOT NULL, mime_type TEXT NOT NULL DEFAULT 'image/jpeg', lang TEXT NOT NULL DEFAULT 'en', target_date DATE, target_meal_type TEXT, status TEXT NOT NULL DEFAULT 'pending', -- pending | processing | done | failed result JSONB, error TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), started_at TIMESTAMPTZ, completed_at TIMESTAMPTZ ); CREATE INDEX idx_dish_recognition_jobs_user ON dish_recognition_jobs (user_id, created_at DESC); CREATE INDEX idx_dish_recognition_jobs_pending ON dish_recognition_jobs (status, user_plan, created_at ASC); -- --------------------------------------------------------------------------- -- meal_diary -- --------------------------------------------------------------------------- CREATE TABLE meal_diary ( id UUID PRIMARY KEY DEFAULT uuid_generate_v7(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, date DATE NOT NULL, meal_type TEXT NOT NULL, portions DECIMAL(5,2) NOT NULL DEFAULT 1, source TEXT NOT NULL DEFAULT 'manual', dish_id UUID REFERENCES dishes(id) ON DELETE RESTRICT, product_id UUID REFERENCES products(id) ON DELETE RESTRICT, recipe_id UUID REFERENCES recipes(id) ON DELETE SET NULL, portion_g DECIMAL(10,2), job_id UUID REFERENCES dish_recognition_jobs(id) ON DELETE SET NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), CONSTRAINT chk_meal_entry_source CHECK (num_nonnulls(dish_id, product_id) = 1) ); CREATE INDEX idx_meal_diary_user_date ON meal_diary (user_id, date); CREATE INDEX idx_meal_diary_job_id ON meal_diary (job_id) WHERE job_id IS NOT NULL; -- --------------------------------------------------------------------------- -- Seed data: languages -- --------------------------------------------------------------------------- INSERT INTO languages (code, native_name, english_name, sort_order) VALUES ('en', 'English', 'English', 1), ('ru', 'Русский', 'Russian', 2), ('es', 'Español', 'Spanish', 3), ('de', 'Deutsch', 'German', 4), ('fr', 'Français', 'French', 5), ('it', 'Italiano', 'Italian', 6), ('pt', 'Português', 'Portuguese', 7), ('zh', '中文', 'Chinese (Simplified)', 8), ('ja', '日本語', 'Japanese', 9), ('ko', '한국어', 'Korean', 10), ('ar', 'العربية', 'Arabic', 11), ('hi', 'हिन्दी', 'Hindi', 12); -- --------------------------------------------------------------------------- -- Seed data: units + unit_translations -- --------------------------------------------------------------------------- INSERT INTO units (code, sort_order) VALUES ('g', 1), ('kg', 2), ('ml', 3), ('l', 4), ('pcs', 5), ('pack', 6); INSERT INTO unit_translations (unit_code, lang, name) VALUES ('g', 'ru', 'г'), ('kg', 'ru', 'кг'), ('ml', 'ru', 'мл'), ('l', 'ru', 'л'), ('pcs', 'ru', 'шт'), ('pack', 'ru', 'уп'); -- --------------------------------------------------------------------------- -- Seed data: product_categories + product_category_translations -- --------------------------------------------------------------------------- INSERT INTO product_categories (slug, name, sort_order) VALUES ('dairy', 'Dairy', 1), ('meat', 'Meat', 2), ('produce', 'Produce', 3), ('bakery', 'Bakery', 4), ('frozen', 'Frozen', 5), ('beverages', 'Beverages', 6), ('other', 'Other', 7); INSERT INTO product_category_translations (product_category_slug, lang, name) VALUES ('dairy', 'ru', 'Молочные продукты'), ('meat', 'ru', 'Мясо и птица'), ('produce', 'ru', 'Овощи и фрукты'), ('bakery', 'ru', 'Выпечка и хлеб'), ('frozen', 'ru', 'Замороженные'), ('beverages', 'ru', 'Напитки'), ('other', 'ru', 'Прочее'); -- --------------------------------------------------------------------------- -- Seed data: cuisines + cuisine_translations -- --------------------------------------------------------------------------- INSERT INTO cuisines (slug, name, sort_order) VALUES ('italian', 'Italian', 1), ('french', 'French', 2), ('russian', 'Russian', 3), ('chinese', 'Chinese', 4), ('japanese', 'Japanese', 5), ('korean', 'Korean', 6), ('mexican', 'Mexican', 7), ('mediterranean', 'Mediterranean', 8), ('indian', 'Indian', 9), ('thai', 'Thai', 10), ('american', 'American', 11), ('georgian', 'Georgian', 12), ('spanish', 'Spanish', 13), ('german', 'German', 14), ('middle_eastern', 'Middle Eastern', 15), ('turkish', 'Turkish', 16), ('greek', 'Greek', 17), ('vietnamese', 'Vietnamese', 18), ('other', 'Other', 19); INSERT INTO cuisine_translations (cuisine_slug, lang, name) VALUES ('italian', 'ru', 'Итальянская'), ('french', 'ru', 'Французская'), ('russian', 'ru', 'Русская'), ('chinese', 'ru', 'Китайская'), ('japanese', 'ru', 'Японская'), ('korean', 'ru', 'Корейская'), ('mexican', 'ru', 'Мексиканская'), ('mediterranean', 'ru', 'Средиземноморская'), ('indian', 'ru', 'Индийская'), ('thai', 'ru', 'Тайская'), ('american', 'ru', 'Американская'), ('georgian', 'ru', 'Грузинская'), ('spanish', 'ru', 'Испанская'), ('german', 'ru', 'Немецкая'), ('middle_eastern', 'ru', 'Ближневосточная'), ('turkish', 'ru', 'Турецкая'), ('greek', 'ru', 'Греческая'), ('vietnamese', 'ru', 'Вьетнамская'), ('other', 'ru', 'Другая'); -- --------------------------------------------------------------------------- -- Seed data: tags + tag_translations -- --------------------------------------------------------------------------- INSERT INTO tags (slug, name, sort_order) VALUES ('vegan', 'Vegan', 1), ('vegetarian', 'Vegetarian', 2), ('gluten_free', 'Gluten-Free', 3), ('dairy_free', 'Dairy-Free', 4), ('healthy', 'Healthy', 5), ('quick', 'Quick', 6), ('spicy', 'Spicy', 7), ('sweet', 'Sweet', 8), ('soup', 'Soup', 9), ('salad', 'Salad', 10), ('main_course', 'Main Course', 11), ('appetizer', 'Appetizer', 12), ('breakfast', 'Breakfast', 13), ('dessert', 'Dessert', 14), ('grilled', 'Grilled', 15), ('baked', 'Baked', 16), ('fried', 'Fried', 17), ('raw', 'Raw', 18), ('fermented', 'Fermented', 19); INSERT INTO tag_translations (tag_slug, lang, name) VALUES ('vegan', 'ru', 'Веганское'), ('vegetarian', 'ru', 'Вегетарианское'), ('gluten_free', 'ru', 'Без глютена'), ('dairy_free', 'ru', 'Без молока'), ('healthy', 'ru', 'Здоровое'), ('quick', 'ru', 'Быстрое'), ('spicy', 'ru', 'Острое'), ('sweet', 'ru', 'Сладкое'), ('soup', 'ru', 'Суп'), ('salad', 'ru', 'Салат'), ('main_course', 'ru', 'Основное блюдо'), ('appetizer', 'ru', 'Закуска'), ('breakfast', 'ru', 'Завтрак'), ('dessert', 'ru', 'Десерт'), ('grilled', 'ru', 'Жареное на гриле'), ('baked', 'ru', 'Запечённое'), ('fried', 'ru', 'Жареное'), ('raw', 'ru', 'Сырое'), ('fermented', 'ru', 'Ферментированное'); -- --------------------------------------------------------------------------- -- Seed data: dish_categories + dish_category_translations -- --------------------------------------------------------------------------- INSERT INTO dish_categories (slug, name, sort_order) VALUES ('soup', 'Soup', 1), ('salad', 'Salad', 2), ('main_course', 'Main Course', 3), ('side_dish', 'Side Dish', 4), ('appetizer', 'Appetizer', 5), ('dessert', 'Dessert', 6), ('breakfast', 'Breakfast', 7), ('drink', 'Drink', 8), ('bread', 'Bread', 9), ('sauce', 'Sauce', 10), ('snack', 'Snack', 11); INSERT INTO dish_category_translations (category_slug, lang, name) VALUES ('soup', 'ru', 'Суп'), ('salad', 'ru', 'Салат'), ('main_course', 'ru', 'Основное блюдо'), ('side_dish', 'ru', 'Гарнир'), ('appetizer', 'ru', 'Закуска'), ('dessert', 'ru', 'Десерт'), ('breakfast', 'ru', 'Завтрак'), ('drink', 'ru', 'Напиток'), ('bread', 'ru', 'Выпечка'), ('sauce', 'ru', 'Соус'), ('snack', 'ru', 'Снэк'); -- +goose Down DROP TABLE IF EXISTS meal_diary; DROP TABLE IF EXISTS dish_recognition_jobs; DROP TABLE IF EXISTS shopping_lists; DROP TABLE IF EXISTS menu_items; DROP TABLE IF EXISTS menu_plans; DROP TABLE IF EXISTS user_saved_recipes; DROP TABLE IF EXISTS user_product_components; DROP TABLE IF EXISTS user_products; DROP TABLE IF EXISTS recipe_step_translations; DROP TABLE IF EXISTS recipe_steps; DROP TABLE IF EXISTS recipe_product_translations; DROP TABLE IF EXISTS recipe_products; DROP TABLE IF EXISTS recipe_translations; DROP TABLE IF EXISTS recipes; DROP TABLE IF EXISTS dish_tags; DROP TABLE IF EXISTS dish_translations; DROP TABLE IF EXISTS dishes; DROP TABLE IF EXISTS dish_category_translations; DROP TABLE IF EXISTS dish_categories; DROP TABLE IF EXISTS tag_translations; DROP TABLE IF EXISTS tags; DROP TABLE IF EXISTS cuisine_translations; DROP TABLE IF EXISTS cuisines; DROP TABLE IF EXISTS product_aliases; DROP TABLE IF EXISTS products; DROP TABLE IF EXISTS product_category_translations; DROP TABLE IF EXISTS product_categories; DROP TABLE IF EXISTS unit_translations; DROP TABLE IF EXISTS units; DROP TABLE IF EXISTS languages; DROP TABLE IF EXISTS users; DROP TYPE IF EXISTS recipe_difficulty; DROP TYPE IF EXISTS recipe_source; DROP TYPE IF EXISTS activity_level; DROP TYPE IF EXISTS user_goal; DROP TYPE IF EXISTS user_gender; DROP TYPE IF EXISTS user_plan; DROP FUNCTION IF EXISTS uuid_generate_v7(); DROP EXTENSION IF EXISTS pg_trgm; DROP EXTENSION IF EXISTS pgcrypto;