-- +goose Up CREATE TABLE IF NOT EXISTS b2b_language ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, created_at DATETIME(6) NOT NULL, updated_at DATETIME(6) NULL, deleted_at DATETIME(6) NULL, name VARCHAR(128) NOT NULL, iso_code VARCHAR(2) NOT NULL, lang_code VARCHAR(5) NOT NULL, date_format VARCHAR(32) NOT NULL, date_format_short VARCHAR(32) NOT NULL, rtl TINYINT(1) NOT NULL DEFAULT 0, is_default TINYINT(1) NOT NULL DEFAULT 0, active TINYINT(1) NOT NULL DEFAULT 1, flag VARCHAR(16) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE INDEX IF NOT EXISTS idx_language_deleted_at ON b2b_language (deleted_at); CREATE TABLE IF NOT EXISTS b2b_components ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255) NOT NULL ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; CREATE UNIQUE INDEX IF NOT EXISTS uk_components_name ON b2b_components (name, id); -- scopes CREATE TABLE IF NOT EXISTS b2b_scopes ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255) NOT NULL ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; CREATE UNIQUE INDEX IF NOT EXISTS uk_scopes_name ON b2b_scopes (name); -- translations CREATE TABLE IF NOT EXISTS b2b_translations ( lang_id INT UNSIGNED NOT NULL, scope_id INT UNSIGNED NOT NULL, component_id INT UNSIGNED NOT NULL, `key` VARCHAR(255) NOT NULL, data TEXT NULL, PRIMARY KEY (lang_id, scope_id, component_id, `key`), CONSTRAINT fk_translations_language FOREIGN KEY (lang_id) REFERENCES b2b_language(id) ON DELETE RESTRICT ON UPDATE RESTRICT, CONSTRAINT fk_translations_scope FOREIGN KEY (scope_id) REFERENCES b2b_scopes(id) ON DELETE RESTRICT ON UPDATE RESTRICT, CONSTRAINT fk_translations_component FOREIGN KEY (component_id) REFERENCES b2b_components(id) ON DELETE RESTRICT ON UPDATE RESTRICT ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; -- customers CREATE TABLE IF NOT EXISTS b2b_customers ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, email VARCHAR(255) NOT NULL, password VARCHAR(255) NULL, first_name VARCHAR(100) NULL, last_name VARCHAR(100) NULL, role VARCHAR(20) NULL DEFAULT 'user', provider VARCHAR(20) NULL DEFAULT 'local', provider_id VARCHAR(255) NULL, avatar_url VARCHAR(500) NULL, is_active TINYINT(1) NULL DEFAULT 1, email_verified TINYINT(1) NULL DEFAULT 0, email_verification_token VARCHAR(255) NULL, email_verification_expires DATETIME(6) NULL, password_reset_token VARCHAR(255) NULL, password_reset_expires DATETIME(6) NULL, last_password_reset_request DATETIME(6) NULL, last_login_at DATETIME(6) NULL, lang_id INT NULL DEFAULT 2, country_id INT NULL DEFAULT 2, created_at DATETIME(6) NULL, updated_at DATETIME(6) NULL, deleted_at DATETIME(6) NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE UNIQUE INDEX IF NOT EXISTS idx_customers_email ON b2b_customers (email); CREATE INDEX IF NOT EXISTS idx_customers_deleted_at ON b2b_customers (deleted_at); -- customer_carts CREATE TABLE IF NOT EXISTS b2b_customer_carts ( cart_id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, user_id BIGINT UNSIGNED NOT NULL, name VARCHAR(255) NULL, CONSTRAINT fk_customer_carts_customers FOREIGN KEY (user_id) REFERENCES b2b_customers(id) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; CREATE INDEX IF NOT EXISTS idx_customer_carts_user_id ON b2b_customer_carts (user_id); -- carts_products CREATE TABLE IF NOT EXISTS b2b_carts_products ( id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, cart_id INT UNSIGNED NOT NULL, product_id INT UNSIGNED NOT NULL, product_attribute_id INT NULL, amount INT UNSIGNED NOT NULL, CONSTRAINT fk_carts_products_customer_carts FOREIGN KEY (cart_id) REFERENCES b2b_customer_carts (cart_id) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT fk_carts_products_product FOREIGN KEY (product_id) REFERENCES ps_product (id_product) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; CREATE INDEX IF NOT EXISTS idx_carts_products_cart_id ON b2b_carts_products (cart_id); -- refresh_tokens CREATE TABLE IF NOT EXISTS b2b_refresh_tokens ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, customer_id BIGINT UNSIGNED NOT NULL, token_hash VARCHAR(64) NOT NULL, expires_at DATETIME(6) NOT NULL, created_at DATETIME(6) NOT NULL, CONSTRAINT fk_refresh_tokens_customer FOREIGN KEY (customer_id) REFERENCES b2b_customers(id) ON DELETE CASCADE ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; CREATE UNIQUE INDEX IF NOT EXISTS uk_refresh_tokens_token_hash ON b2b_refresh_tokens (token_hash); CREATE INDEX IF NOT EXISTS idx_refresh_tokens_customer_id ON b2b_refresh_tokens (customer_id); CREATE TABLE `b2b_currencies` ( `id` BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, `ps_id_currency` INT UNSIGNED NOT NULL, `is_default` TINYINT NOT NULL, `is_active` TINYINT NOT NULL, PRIMARY KEY (`id`) ) ENGINE = InnoDB; ALTER TABLE `b2b_currencies` ADD CONSTRAINT `FK_b2b_currencies_ps_id_currency` FOREIGN KEY (`ps_id_currency`) REFERENCES `ps_currency` (`id_currency`) ON DELETE CASCADE ON UPDATE CASCADE; CREATE INDEX `fk_b2b_currencies_ps_currency` ON `b2b_currencies` ( `ps_id_currency` ASC ); CREATE TABLE `b2b_currency_rates` ( `id` BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, `b2b_id_currency` BIGINT UNSIGNED NOT NULL, `created_at` DATETIME NOT NULL, `conversion_rate` DECIMAL(13,6) NULL DEFAULT NULL , PRIMARY KEY (`id`) ) ENGINE = InnoDB; ALTER TABLE `b2b_currency_rates` ADD CONSTRAINT `FK_b2b_currency_rates_b2b_id_currency` FOREIGN KEY (`b2b_id_currency`) REFERENCES `b2b_currencies` (`id`) ON DELETE CASCADE ON UPDATE CASCADE; CREATE INDEX `fk_b2b_currency_rates_b2b_currencies` ON `b2b_currency_rates` ( `b2b_id_currency` ASC ); -- countries CREATE TABLE IF NOT EXISTS b2b_countries ( `id` BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, `flag` VARCHAR(16) NOT NULL, `ps_id_country` INT UNSIGNED NOT NULL, `b2b_id_currency` BIGINT UNSIGNED NOT NULL, PRIMARY KEY (`id`), CONSTRAINT `fk_b2b_countries_ps_country` FOREIGN KEY (`ps_id_country`) REFERENCES `ps_country` (`id_country`) ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT `FK_b2b_countries_b2b_id_currency` FOREIGN KEY (`b2b_id_currency`) REFERENCES `b2b_currencies` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION ) ENGINE = InnoDB; CREATE INDEX `fk_b2b_countries_ps_country` ON `b2b_countries` ( `ps_id_country` ASC ); CREATE TABLE b2b_specific_price ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255) NOT NULL, created_at DATETIME NULL, updated_at DATETIME NULL, deleted_at DATETIME NULL, scope ENUM('shop', 'category', 'product') NOT NULL, valid_from DATETIME NULL, valid_till DATETIME NULL, has_expiration_date BOOLEAN DEFAULT FALSE, reduction_type ENUM('amount', 'percentage') NOT NULL, price DECIMAL(10, 2) NULL, b2b_id_currency BIGINT UNSIGNED NULL, -- specifies which currency is used for the price percentage_reduction DECIMAL(5, 2) NULL, from_quantity INT UNSIGNED DEFAULT 1, is_active BOOLEAN DEFAULT TRUE, CONSTRAINT fk_b2b_specific_price_country FOREIGN KEY (b2b_id_country) REFERENCES b2b_countries(id) ON DELETE SET NULL ON UPDATE CASCADE, CONSTRAINT fk_b2b_specific_price_customer FOREIGN KEY (b2b_id_customer) REFERENCES b2b_customers(id) ON DELETE SET NULL ON UPDATE CASCADE, CONSTRAINT fk_b2b_specific_price_currency FOREIGN KEY (b2b_id_currency) REFERENCES b2b_currencies(id) ON DELETE SET NULL ON UPDATE CASCADE ) ENGINE = InnoDB; CREATE INDEX idx_b2b_scope ON b2b_specific_price(scope); CREATE INDEX idx_b2b_customer ON b2b_specific_price(b2b_id_customer); CREATE INDEX idx_b2b_country ON b2b_specific_price(b2b_id_country); CREATE INDEX idx_b2b_active_dates ON b2b_specific_price(is_active, valid_from, valid_till); CREATE INDEX idx_b2b_lookup ON b2b_specific_price ( scope, is_active, b2b_id_customer, b2b_id_country, from_quantity ); CREATE TABLE b2b_specific_price_product ( b2b_specific_price_id BIGINT UNSIGNED, id_product INT UNSIGNED, PRIMARY KEY (b2b_specific_price_id, id_product), FOREIGN KEY (b2b_specific_price_id) REFERENCES b2b_specific_price(id) ON DELETE CASCADE, FOREIGN KEY (id_product) REFERENCES ps_product(id_product) ON DELETE CASCADE ); CREATE TABLE b2b_specific_price_category ( b2b_specific_price_id BIGINT UNSIGNED, id_category INT UNSIGNED, PRIMARY KEY (b2b_specific_price_id, id_category), FOREIGN KEY (b2b_specific_price_id) REFERENCES b2b_specific_price(id) ON DELETE CASCADE, FOREIGN KEY (id_category) REFERENCES ps_category(id_category) ON DELETE CASCADE ); CREATE TABLE b2b_specific_price_product_attribute ( b2b_specific_price_id BIGINT UNSIGNED, id_product_attribute INT UNSIGNED, PRIMARY KEY (b2b_specific_price_id, id_product_attribute), FOREIGN KEY (b2b_specific_price_id) REFERENCES b2b_specific_price(id) ON DELETE CASCADE, FOREIGN KEY (id_product_attribute) REFERENCES ps_product_attribute(id_product_attribute) ON DELETE CASCADE ); CREATE TABLE b2b_specific_price_customer ( b2b_specific_price_id BIGINT UNSIGNED, b2b_id_customer BIGINT UNSIGNED, PRIMARY KEY (b2b_specific_price_id, b2b_id_customer), FOREIGN KEY (b2b_specific_price_id) REFERENCES b2b_specific_price(id) ON DELETE CASCADE, FOREIGN KEY (b2b_id_customer) REFERENCES b2b_customers(id) ON DELETE CASCADE ); CREATE TABLE b2b_specific_price_country ( b2b_specific_price_id BIGINT UNSIGNED, b2b_id_country BIGINT UNSIGNED, PRIMARY KEY (b2b_specific_price_id, b2b_id_country), FOREIGN KEY (b2b_specific_price_id) REFERENCES b2b_specific_price(id) ON DELETE CASCADE, FOREIGN KEY (b2b_id_country) REFERENCES b2b_countries(id) ON DELETE CASCADE ); CREATE INDEX idx_b2b_product_rel ON b2b_specific_price_product (id_product); CREATE INDEX idx_b2b_category_rel ON b2b_specific_price_category (id_category); CREATE INDEX idx_b2b_product_attribute_rel ON b2b_specific_price_product_attribute (id_product_attribute); CREATE INDEX idx_bsp_customer ON b2b_specific_price_customer (b2b_specific_price_id, b2b_id_customer); CREATE INDEX idx_bsp_country ON b2b_specific_price_country (b2b_specific_price_id, b2b_id_country); -- +goose Down DROP TABLE IF EXISTS b2b_countries; DROP TABLE IF EXISTS b2b_language; DROP TABLE IF EXISTS b2b_components; DROP TABLE IF EXISTS b2b_scopes; DROP TABLE IF EXISTS b2b_translations; DROP TABLE IF EXISTS b2b_customers; DROP TABLE IF EXISTS b2b_refresh_tokens; DROP TABLE IF EXISTS b2b_currencies; DROP TABLE IF EXISTS b2b_currency_rates; DROP TABLE IF EXISTS b2b_specific_price; DROP TABLE IF EXISTS b2b_specific_price_product; DROP TABLE IF EXISTS b2b_specific_price_category; DROP TABLE IF EXISTS b2b_specific_price_product_attribute;