-- RybStock database schema -- MariaDB/MySQL, charset utf8mb4 SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; DROP TABLE IF EXISTS order_status_history; DROP TABLE IF EXISTS order_items; DROP TABLE IF EXISTS orders; DROP TABLE IF EXISTS delivery_calculations; DROP TABLE IF EXISTS promocode_targets; DROP TABLE IF EXISTS promocodes; DROP TABLE IF EXISTS product_search_terms; DROP TABLE IF EXISTS product_images; DROP TABLE IF EXISTS product_variants; DROP TABLE IF EXISTS popular_products; DROP TABLE IF EXISTS promo_block_items; DROP TABLE IF EXISTS products; DROP TABLE IF EXISTS categories; DROP TABLE IF EXISTS reviews; DROP TABLE IF EXISTS customer_login_codes; DROP TABLE IF EXISTS customer_email_tokens; DROP TABLE IF EXISTS site_settings; DROP TABLE IF EXISTS holidays; DROP TABLE IF EXISTS admins; CREATE TABLE admins ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, name VARCHAR(120) NOT NULL, email VARCHAR(190) NOT NULL, password_hash VARCHAR(255) NOT NULL, role ENUM('owner', 'manager', 'content') NOT NULL DEFAULT 'owner', is_active TINYINT(1) NOT NULL DEFAULT 1, last_login_at DATETIME NULL, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uq_admins_email (email) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE categories ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, parent_id BIGINT UNSIGNED NULL, name VARCHAR(190) NOT NULL, slug VARCHAR(220) NOT NULL, description TEXT NULL, seo_title VARCHAR(255) NULL, seo_description TEXT NULL, image_path VARCHAR(255) NULL, sort_order INT NOT NULL DEFAULT 100, is_active TINYINT(1) NOT NULL DEFAULT 1, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uq_categories_slug (slug), KEY idx_categories_parent (parent_id), KEY idx_categories_active_sort (is_active, sort_order), CONSTRAINT fk_categories_parent FOREIGN KEY (parent_id) REFERENCES categories(id) ON DELETE SET NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE products ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, category_id BIGINT UNSIGNED NULL, name VARCHAR(220) NOT NULL, slug VARCHAR(240) NOT NULL, sku VARCHAR(100) NULL, short_description TEXT NULL, description MEDIUMTEXT NULL, product_info MEDIUMTEXT NULL, main_image_path VARCHAR(255) NULL, base_unit ENUM('kg', 'g', 'l', 'ml', 'pcs', 'pack') NOT NULL DEFAULT 'kg', package_display_mode ENUM('auto', 'base_and_package', 'package_only') NOT NULL DEFAULT 'auto', is_weight_product TINYINT(1) NOT NULL DEFAULT 1, is_published TINYINT(1) NOT NULL DEFAULT 0, is_available TINYINT(1) NOT NULL DEFAULT 1, is_new TINYINT(1) NOT NULL DEFAULT 0, is_hit TINYINT(1) NOT NULL DEFAULT 0, is_promo TINYINT(1) NOT NULL DEFAULT 0, sort_order INT NOT NULL DEFAULT 100, sales_count INT UNSIGNED NOT NULL DEFAULT 0, last_sold_at DATETIME NULL, published_at DATETIME NULL, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uq_products_slug (slug), UNIQUE KEY uq_products_sku (sku), KEY idx_products_category (category_id), KEY idx_products_public (is_published, is_available, sort_order), KEY idx_products_sales (sales_count, last_sold_at), FULLTEXT KEY ft_products_text (name, short_description, description, product_info), CONSTRAINT fk_products_category FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE SET NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE product_variants ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, product_id BIGINT UNSIGNED NOT NULL, name VARCHAR(190) NOT NULL, unit ENUM('kg', 'g', 'l', 'ml', 'pcs', 'pack') NOT NULL DEFAULT 'kg', package_quantity DECIMAL(10,3) NOT NULL DEFAULT 1.000, step_quantity DECIMAL(10,3) NOT NULL DEFAULT 1.000, price_per_unit DECIMAL(12,2) NULL, package_price DECIMAL(12,2) NOT NULL, old_package_price DECIMAL(12,2) NULL, min_order_quantity DECIMAL(10,3) NOT NULL DEFAULT 1.000, stock_quantity DECIMAL(12,3) NULL, is_default TINYINT(1) NOT NULL DEFAULT 0, is_published TINYINT(1) NOT NULL DEFAULT 1, is_available TINYINT(1) NOT NULL DEFAULT 1, sort_order INT NOT NULL DEFAULT 100, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_variants_product (product_id), KEY idx_variants_public (product_id, is_published, is_available, sort_order), CONSTRAINT fk_variants_product FOREIGN KEY (product_id) REFERENCES products(id) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE product_images ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, product_id BIGINT UNSIGNED NOT NULL, path VARCHAR(255) NOT NULL, alt VARCHAR(255) NULL, sort_order INT NOT NULL DEFAULT 100, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_product_images_product (product_id, sort_order), CONSTRAINT fk_product_images_product FOREIGN KEY (product_id) REFERENCES products(id) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE product_search_terms ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, product_id BIGINT UNSIGNED NOT NULL, term VARCHAR(190) NOT NULL, weight TINYINT UNSIGNED NOT NULL DEFAULT 5, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_search_terms_term (term), KEY idx_search_terms_product (product_id), CONSTRAINT fk_search_terms_product FOREIGN KEY (product_id) REFERENCES products(id) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE promocodes ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, code VARCHAR(80) NOT NULL, title VARCHAR(190) NOT NULL, discount_type ENUM('fixed', 'percent') NOT NULL, discount_value DECIMAL(12,2) NOT NULL, min_order_amount DECIMAL(12,2) NOT NULL DEFAULT 0.00, applies_to ENUM('order', 'category', 'product') NOT NULL DEFAULT 'order', payment_note VARCHAR(255) NULL DEFAULT 'Действует при наличном расчете', starts_at DATETIME NULL, ends_at DATETIME NULL, usage_limit INT UNSIGNED NULL, used_count INT UNSIGNED NOT NULL DEFAULT 0, is_active TINYINT(1) NOT NULL DEFAULT 1, is_featured TINYINT(1) NOT NULL DEFAULT 0, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uq_promocodes_code (code), KEY idx_promocodes_active (is_active, starts_at, ends_at) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE promocode_targets ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, promocode_id BIGINT UNSIGNED NOT NULL, target_type ENUM('category', 'product') NOT NULL, target_id BIGINT UNSIGNED NOT NULL, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uq_promocode_target (promocode_id, target_type, target_id), KEY idx_promocode_targets_lookup (target_type, target_id), CONSTRAINT fk_promocode_targets_promocode FOREIGN KEY (promocode_id) REFERENCES promocodes(id) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE delivery_calculations ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, delivery_type ENUM('inside_mkad', 'outside_mkad', 'pickup') NOT NULL, address VARCHAR(500) NULL, order_amount DECIMAL(12,2) NOT NULL DEFAULT 0.00, distance_from_mkad_km DECIMAL(8,2) NULL, free_delivery_threshold DECIMAL(12,2) NULL, delivery_price DECIMAL(12,2) NOT NULL DEFAULT 0.00, lift_price DECIMAL(12,2) NOT NULL DEFAULT 0.00, total_delivery_price DECIMAL(12,2) NOT NULL DEFAULT 0.00, provider VARCHAR(80) NULL, provider_payload MEDIUMTEXT NULL, explanation TEXT NULL, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_delivery_type_created (delivery_type, created_at) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE orders ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, order_number VARCHAR(40) NOT NULL, customer_name VARCHAR(120) NOT NULL, phone VARCHAR(40) NOT NULL, email VARCHAR(190) NULL, delivery_type ENUM('inside_mkad', 'outside_mkad', 'pickup') NOT NULL, address VARCHAR(500) NULL, desired_date DATE NULL, customer_comment TEXT NULL, admin_comment TEXT NULL, status ENUM('new', 'confirmed', 'assembling', 'ready', 'delivering', 'completed', 'cancelled') NOT NULL DEFAULT 'new', subtotal_amount DECIMAL(12,2) NOT NULL DEFAULT 0.00, discount_amount DECIMAL(12,2) NOT NULL DEFAULT 0.00, delivery_amount DECIMAL(12,2) NOT NULL DEFAULT 0.00, total_amount DECIMAL(12,2) NOT NULL DEFAULT 0.00, promocode_id BIGINT UNSIGNED NULL, promocode_code VARCHAR(80) NULL, delivery_calculation_id BIGINT UNSIGNED NULL, client_ip VARCHAR(45) NULL, user_agent VARCHAR(255) NULL, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uq_orders_number (order_number), KEY idx_orders_status_created (status, created_at), KEY idx_orders_email (email), KEY idx_orders_phone (phone), CONSTRAINT fk_orders_promocode FOREIGN KEY (promocode_id) REFERENCES promocodes(id) ON DELETE SET NULL, CONSTRAINT fk_orders_delivery_calculation FOREIGN KEY (delivery_calculation_id) REFERENCES delivery_calculations(id) ON DELETE SET NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE order_items ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, order_id BIGINT UNSIGNED NOT NULL, product_id BIGINT UNSIGNED NULL, variant_id BIGINT UNSIGNED NULL, product_name VARCHAR(220) NOT NULL, variant_name VARCHAR(190) NOT NULL, unit VARCHAR(20) NOT NULL, package_quantity DECIMAL(10,3) NOT NULL, quantity DECIMAL(10,3) NOT NULL, price_per_unit DECIMAL(12,2) NULL, package_price DECIMAL(12,2) NOT NULL, line_total DECIMAL(12,2) NOT NULL, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_order_items_order (order_id), KEY idx_order_items_product (product_id), CONSTRAINT fk_order_items_order FOREIGN KEY (order_id) REFERENCES orders(id) ON DELETE CASCADE, CONSTRAINT fk_order_items_product FOREIGN KEY (product_id) REFERENCES products(id) ON DELETE SET NULL, CONSTRAINT fk_order_items_variant FOREIGN KEY (variant_id) REFERENCES product_variants(id) ON DELETE SET NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE order_status_history ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, order_id BIGINT UNSIGNED NOT NULL, old_status VARCHAR(40) NULL, new_status VARCHAR(40) NOT NULL, comment TEXT NULL, admin_id BIGINT UNSIGNED NULL, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_status_history_order (order_id, created_at), CONSTRAINT fk_status_history_order FOREIGN KEY (order_id) REFERENCES orders(id) ON DELETE CASCADE, CONSTRAINT fk_status_history_admin FOREIGN KEY (admin_id) REFERENCES admins(id) ON DELETE SET NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE customer_login_codes ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, email VARCHAR(190) NOT NULL, code_hash VARCHAR(255) NOT NULL, expires_at DATETIME NOT NULL, used_at DATETIME NULL, attempts TINYINT UNSIGNED NOT NULL DEFAULT 0, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_customer_codes_email (email), KEY idx_customer_codes_expires (expires_at) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE reviews ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, source ENUM('yandex', 'manual') NOT NULL DEFAULT 'manual', author_name VARCHAR(160) NOT NULL, rating TINYINT UNSIGNED NOT NULL DEFAULT 5, text TEXT NOT NULL, external_url VARCHAR(500) NULL, reviewed_at DATE NULL, is_published TINYINT(1) NOT NULL DEFAULT 1, sort_order INT NOT NULL DEFAULT 100, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_reviews_public (is_published, rating, sort_order), CONSTRAINT chk_reviews_rating CHECK (rating BETWEEN 1 AND 5) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE promo_block_items ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, product_id BIGINT UNSIGNED NOT NULL, title VARCHAR(190) NULL, is_active TINYINT(1) NOT NULL DEFAULT 1, sort_order INT NOT NULL DEFAULT 100, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_promo_block_active (is_active, sort_order), CONSTRAINT fk_promo_block_product FOREIGN KEY (product_id) REFERENCES products(id) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE popular_products ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, product_id BIGINT UNSIGNED NOT NULL, mode ENUM('manual', 'pinned') NOT NULL DEFAULT 'manual', is_active TINYINT(1) NOT NULL DEFAULT 1, sort_order INT NOT NULL DEFAULT 100, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uq_popular_product (product_id), KEY idx_popular_products_active (is_active, sort_order), CONSTRAINT fk_popular_product FOREIGN KEY (product_id) REFERENCES products(id) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE site_settings ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, setting_key VARCHAR(120) NOT NULL, setting_value MEDIUMTEXT NULL, value_type ENUM('string', 'text', 'number', 'bool', 'json') NOT NULL DEFAULT 'string', group_name VARCHAR(80) NOT NULL DEFAULT 'general', created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uq_site_settings_key (setting_key), KEY idx_site_settings_group (group_name) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE holidays ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, holiday_date DATE NOT NULL, title VARCHAR(190) NOT NULL, is_working_day TINYINT(1) NOT NULL DEFAULT 0, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uq_holidays_date (holiday_date) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; SET FOREIGN_KEY_CHECKS = 1;