SET time_zone = '+03:00';
CREATE TABLE
IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
image VARCHAR(255),
password VARCHAR(255),
bio TEXT,
location VARCHAR(255),
role ENUM (
'user',
'moderator',
'admin',
'designer',
'coder',
'tester',
'vip'
) DEFAULT 'user',
level INT DEFAULT 1 NOT NULL CHECK (level BETWEEN 0 AND 20),
balance DECIMAL(10, 2) DEFAULT 0 NOT NULL CHECK (balance >= 0),
is_verified BOOLEAN DEFAULT FALSE,
is_agreed_terms BOOLEAN DEFAULT FALSE,
status ENUM('active', 'banned') DEFAULT 'active' NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME ON UPDATE CURRENT_TIMESTAMP
);
CREATE TABLE
IF NOT EXISTS social_accounts (
social_account_id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
provider VARCHAR(50) NOT NULL,
provider_user_id VARCHAR(100) NOT NULL,
access_token VARCHAR(255),
refresh_token VARCHAR(255),
linked_at DATETIME DEFAULT CURRENT_TIMESTAMP,
UNIQUE (provider, provider_user_id),
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE
);
CREATE TABLE
IF NOT EXISTS files (
file_id INT AUTO_INCREMENT PRIMARY KEY,
file_path VARCHAR(255) NOT NULL,
file_type VARCHAR(50),
uploaded_by INT,
uploaded_at DATETIME DEFAULT CURRENT_TIMESTAMP,
file_size INT UNSIGNED DEFAULT NULL,
original_filename VARCHAR(255) NOT NULL,
FOREIGN KEY (uploaded_by) REFERENCES users (id) ON DELETE SET NULL
);
CREATE TABLE
IF NOT EXISTS products (
product_id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
description TEXT,
price DECIMAL(10, 2) NOT NULL,
category VARCHAR(50) NOT NULL,
author_id INT,
image_url VARCHAR(255),
popularity INT DEFAULT 0,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
download_file_path VARCHAR(255) NULL,
download_file_paths TEXT NULL,
has_downloadable_content TINYINT(1) DEFAULT 0,
is_active BOOLEAN DEFAULT TRUE,
is_featured BOOLEAN DEFAULT FALSE,
is_free BOOLEAN DEFAULT FALSE,
FOREIGN KEY (author_id) REFERENCES users (id) ON DELETE SET NULL
);
CREATE TABLE
IF NOT EXISTS product_ratings (
rating_id INT AUTO_INCREMENT PRIMARY KEY,
product_id INT NOT NULL,
user_id INT NOT NULL,
rating DECIMAL(3, 2) NOT NULL CHECK (rating BETWEEN 0 AND 6),
review TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (product_id) REFERENCES products (product_id) ON DELETE CASCADE,
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE,
UNIQUE KEY (product_id, user_id)
);
CREATE TABLE
IF NOT EXISTS product_images (
image_id INT AUTO_INCREMENT PRIMARY KEY,
product_id INT NOT NULL,
image_url VARCHAR(255) NOT NULL,
is_primary BOOLEAN DEFAULT FALSE,
display_order INT DEFAULT 0,
FOREIGN KEY (product_id) REFERENCES products (product_id) ON DELETE CASCADE
);
CREATE TABLE
IF NOT EXISTS user_settings (
setting_id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
profile_visibility ENUM ('all', 'authorized', 'followers', 'none') DEFAULT 'all',
followers_visibility ENUM ('all', 'authorized', 'followers', 'none') DEFAULT 'all',
activity_visibility ENUM ('all', 'authorized', 'followers', 'none') DEFAULT 'all',
anonymous_mode BOOLEAN DEFAULT FALSE,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE,
UNIQUE (user_id)
);
INSERT IGNORE INTO user_settings (
user_id,
profile_visibility,
followers_visibility,
activity_visibility,
anonymous_mode
)
SELECT
id,
'all',
'all',
'all',
FALSE
FROM
users;
CREATE TABLE
IF NOT EXISTS admin_logs (
log_id INT AUTO_INCREMENT PRIMARY KEY,
admin_id INT NOT NULL,
action TEXT NOT NULL,
log_time DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (admin_id) REFERENCES users (id) ON DELETE CASCADE
);
CREATE TABLE
IF NOT EXISTS cheat_injections (
injection_id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT,
injection_time DATETIME DEFAULT CURRENT_TIMESTAMP,
ip_address VARCHAR(45),
user_agent VARCHAR(255),
game_version VARCHAR(50),
status VARCHAR(20),
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE SET NULL
);
CREATE TABLE
IF NOT EXISTS loader_downloads (
download_id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT,
download_time DATETIME DEFAULT CURRENT_TIMESTAMP,
ip_address VARCHAR(45),
user_agent VARCHAR(255),
os_version VARCHAR(50),
download_source VARCHAR(100),
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE SET NULL
);
CREATE TABLE
IF NOT EXISTS marketplace_purchases (
purchase_id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
product_id INT NOT NULL,
original_price DECIMAL(10, 2) NOT NULL,
discount_price DECIMAL(10, 2) NOT NULL,
final_amount DECIMAL(10, 2) NOT NULL,
discount_applied BOOLEAN DEFAULT FALSE,
discount_code VARCHAR(50),
discount_amount DECIMAL(10, 2) DEFAULT 0,
transaction_id INT,
purchase_time DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE,
FOREIGN KEY (product_id) REFERENCES products (product_id) ON DELETE CASCADE,
INDEX (user_id),
INDEX (product_id),
INDEX (purchase_time)
);
CREATE TABLE
IF NOT EXISTS payment_methods (
payment_method_id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
description TEXT,
is_active BOOLEAN DEFAULT TRUE,
processor VARCHAR(50),
config JSON,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE
IF NOT EXISTS transactions (
transaction_id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
amount DECIMAL(10, 2) NOT NULL,
type VARCHAR(20) NOT NULL,
status VARCHAR(20) NOT NULL,
payment_method_id INT,
payment_reference VARCHAR(255),
details JSON,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE,
FOREIGN KEY (payment_method_id) REFERENCES payment_methods (payment_method_id) ON DELETE SET NULL
);
CREATE TABLE
IF NOT EXISTS auth_logs (
log_id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT,
provider VARCHAR(50) NOT NULL,
provider_user_id VARCHAR(100) NOT NULL,
ip_address VARCHAR(45),
user_agent VARCHAR(255),
login_time DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE SET NULL
);
CREATE TABLE
IF NOT EXISTS user_activities (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
type VARCHAR(50) NOT NULL,
details TEXT,
activity_date DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE
);
CREATE TABLE
IF NOT EXISTS user_followers (
follow_id INT AUTO_INCREMENT PRIMARY KEY,
follower_id INT NOT NULL,
followed_id INT NOT NULL,
followed_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (follower_id) REFERENCES users (id) ON DELETE CASCADE,
FOREIGN KEY (followed_id) REFERENCES users (id) ON DELETE CASCADE,
UNIQUE KEY (follower_id, followed_id)
);
CREATE TABLE
IF NOT EXISTS user_reviews (
review_id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
reviewer_id INT NOT NULL,
product_id INT NOT NULL,
content TEXT NOT NULL,
rating INT NOT NULL CHECK (rating BETWEEN 1 AND 5),
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE,
FOREIGN KEY (reviewer_id) REFERENCES users (id) ON DELETE CASCADE,
FOREIGN KEY (product_id) REFERENCES products (product_id) ON DELETE CASCADE,
UNIQUE KEY (reviewer_id, product_id, user_id)
);
CREATE TABLE
IF NOT EXISTS roles (
role_id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL UNIQUE,
description TEXT,
badge_color VARCHAR(20),
badge_icon VARCHAR(50),
display_order INT DEFAULT 0,
is_system BOOLEAN DEFAULT FALSE,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
INDEX (name),
INDEX (display_order)
);
CREATE TABLE
IF NOT EXISTS user_roles (
user_id INT NOT NULL,
role_id INT NOT NULL,
assigned_at DATETIME DEFAULT CURRENT_TIMESTAMP,
assigned_by INT,
PRIMARY KEY (user_id, role_id),
INDEX (role_id),
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE,
FOREIGN KEY (role_id) REFERENCES roles (role_id) ON DELETE CASCADE,
FOREIGN KEY (assigned_by) REFERENCES users (id) ON DELETE SET NULL
);
INSERT IGNORE INTO roles (
name,
description,
badge_color,
badge_icon,
display_order,
is_system
)
VALUES
(
'admin',
'Administrator with full access',
'white',
'ShieldCheckIcon',
1,
TRUE
),
(
'moderator',
'Content moderator',
'blue',
'ClipboardDocumentCheckIcon',
2,
TRUE
),
(
'vip',
'VIP user with special privileges',
'gold',
'SparklesIcon',
3,
FALSE
),
(
'designer',
'Interface designer',
'purple',
'PaintBrushIcon',
4,
FALSE
),
(
'coder',
'Developer and programmer',
'green',
'CodeBracketIcon',
5,
FALSE
),
(
'tester',
'Quality assurance specialist',
'orange',
'BugAntIcon',
6,
FALSE
),
(
'user',
'Regular user',
'gray',
'CheckCircleIcon',
99,
TRUE
);
INSERT IGNORE INTO payment_methods (name, description, is_active, processor, config)
VALUES
(
'Visa',
'Visa payment',
TRUE,
'visa_processor',
NULL
),
(
'Mastercard',
'Mastercard payment',
TRUE,
'mastercard_processor',
NULL
),
('Mir', 'Mir payment', TRUE, 'mir_processor', NULL),
(
'Tether USDT',
'Tether USDT payment',
TRUE,
'crypto_processor',
'{"coin":"usdt"}'
);
CREATE TABLE
IF NOT EXISTS download_logs (
log_id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
product_id INT NOT NULL,
download_time DATETIME DEFAULT CURRENT_TIMESTAMP,
ip_address VARCHAR(45),
user_agent VARCHAR(255),
original_file VARCHAR(255) NOT NULL,
password VARCHAR(50) NULL,
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE,
FOREIGN KEY (product_id) REFERENCES products (product_id) ON DELETE CASCADE
);
CREATE TABLE
IF NOT EXISTS product_discounts (
discount_id INT AUTO_INCREMENT PRIMARY KEY,
product_id INT,
discount_type ENUM('percentage', 'fixed_amount') NOT NULL,
discount_value DECIMAL(10, 2) NOT NULL,
start_date DATETIME NOT NULL,
end_date DATETIME NOT NULL,
is_active BOOLEAN DEFAULT TRUE,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (product_id) REFERENCES products (product_id) ON DELETE CASCADE,
INDEX (product_id),
INDEX (is_active),
INDEX (start_date, end_date)
);
CREATE TABLE
IF NOT EXISTS category_discounts (
discount_id INT AUTO_INCREMENT PRIMARY KEY,
category VARCHAR(50) NOT NULL,
discount_type ENUM('percentage', 'fixed_amount') NOT NULL,
discount_value DECIMAL(10, 2) NOT NULL,
start_date DATETIME NOT NULL,
end_date DATETIME NOT NULL,
is_active BOOLEAN DEFAULT TRUE,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
INDEX (category),
INDEX (is_active),
INDEX (start_date, end_date)
);
CREATE TABLE
IF NOT EXISTS gift_codes (
code_id INT AUTO_INCREMENT PRIMARY KEY,
code VARCHAR(50) UNIQUE NOT NULL,
code_type ENUM('discount', 'free_product', 'balance_add') NOT NULL,
discount_value DECIMAL(10, 2),
product_id INT,
balance_value DECIMAL(10, 2),
created_by INT,
is_used BOOLEAN DEFAULT FALSE,
used_by INT,
used_at DATETIME,
expires_at DATETIME,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (created_by) REFERENCES users (id) ON DELETE SET NULL,
FOREIGN KEY (used_by) REFERENCES users (id) ON DELETE SET NULL,
FOREIGN KEY (product_id) REFERENCES products (product_id) ON DELETE SET NULL,
INDEX (code),
INDEX (is_used),
INDEX (expires_at)
);
CREATE TABLE
IF NOT EXISTS product_price_history (
history_id INT AUTO_INCREMENT PRIMARY KEY,
product_id INT NOT NULL,
old_price DECIMAL(10, 2) NOT NULL,
new_price DECIMAL(10, 2) NOT NULL,
changed_by INT,
changed_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (product_id) REFERENCES products (product_id) ON DELETE CASCADE,
FOREIGN KEY (changed_by) REFERENCES users (id) ON DELETE SET NULL,
INDEX (product_id),
INDEX (changed_at)
);
-- Drop existing functions, triggers, and procedures to avoid conflicts
DROP FUNCTION IF EXISTS get_product_discounted_price;
DROP FUNCTION IF EXISTS get_product_discounted_price_wrapper;
DROP TRIGGER IF NOT EXISTS trg_product_price_update;
DROP PROCEDURE IF EXISTS generate_gift_code;
-- Set the delimiter to allow multiple statements in functions/procedures
DELIMITER $$
-- Create the main discount calculation function
CREATE FUNCTION get_product_discounted_price(
p_product_id INT,
p_user_id INT
)
RETURNS DECIMAL(10, 2)
DETERMINISTIC
BEGIN
DECLARE original_price DECIMAL(10, 2);
DECLARE discounted_price DECIMAL(10, 2);
DECLARE product_category VARCHAR(50);
DECLARE product_discount_pct DECIMAL(10, 2);
DECLARE product_discount_amt DECIMAL(10, 2);
DECLARE category_discount_pct DECIMAL(10, 2);
DECLARE category_discount_amt DECIMAL(10, 2);
DECLARE user_discount_pct DECIMAL(10, 2);
DECLARE user_discount_amt DECIMAL(10, 2);
SELECT price, category INTO original_price, product_category
FROM products
WHERE product_id = p_product_id;
SET discounted_price = original_price;
IF p_user_id IS NOT NULL THEN
SELECT discount_value INTO user_discount_pct
FROM user_discounts
WHERE user_id = p_user_id
AND discount_type = 'percentage'
AND is_active = TRUE
AND CURRENT_TIMESTAMP < expires_at
AND (product_id = p_product_id OR product_id IS NULL)
ORDER BY discount_value DESC
LIMIT 1;
IF user_discount_pct IS NOT NULL THEN
SET discounted_price = original_price * (1 - (user_discount_pct / 100));
RETURN ROUND(discounted_price, 2);
END IF;
SELECT discount_value INTO user_discount_amt
FROM user_discounts
WHERE user_id = p_user_id
AND discount_type = 'fixed_amount'
AND is_active = TRUE
AND CURRENT_TIMESTAMP < expires_at
AND (product_id = p_product_id OR product_id IS NULL)
ORDER BY discount_value DESC
LIMIT 1;
IF user_discount_amt IS NOT NULL THEN
SET discounted_price = GREATEST(0, original_price - user_discount_amt);
RETURN ROUND(discounted_price, 2);
END IF;
END IF;
SELECT discount_value INTO product_discount_pct
FROM product_discounts
WHERE product_id = p_product_id
AND discount_type = 'percentage'
AND is_active = TRUE
AND CURRENT_TIMESTAMP BETWEEN start_date AND end_date
ORDER BY discount_value DESC
LIMIT 1;
IF product_discount_pct IS NOT NULL THEN
SET discounted_price = original_price * (1 - (product_discount_pct / 100));
END IF;
SELECT discount_value INTO product_discount_amt
FROM product_discounts
WHERE product_id = p_product_id
AND discount_type = 'fixed_amount'
AND is_active = TRUE
AND CURRENT_TIMESTAMP BETWEEN start_date AND end_date
ORDER BY discount_value DESC
LIMIT 1;
IF product_discount_amt IS NOT NULL THEN
SET discounted_price = GREATEST(0, original_price - product_discount_amt);
END IF;
IF product_discount_pct IS NULL AND product_discount_amt IS NULL THEN
SELECT discount_value INTO category_discount_pct
FROM category_discounts
WHERE category = product_category
AND discount_type = 'percentage'
AND is_active = TRUE
AND CURRENT_TIMESTAMP BETWEEN start_date AND end_date
ORDER BY discount_value DESC
LIMIT 1;
IF category_discount_pct IS NOT NULL THEN
SET discounted_price = original_price * (1 - (category_discount_pct / 100));
END IF;
SELECT discount_value INTO category_discount_amt
FROM category_discounts
WHERE category = product_category
AND discount_type = 'fixed_amount'
AND is_active = TRUE
AND CURRENT_TIMESTAMP BETWEEN start_date AND end_date
ORDER BY discount_value DESC
LIMIT 1;
IF category_discount_amt IS NOT NULL THEN
SET discounted_price = GREATEST(0, original_price - category_discount_amt);
END IF;
END IF;
RETURN ROUND(discounted_price, 2);
END$$
-- Create the wrapper function
CREATE FUNCTION get_product_discounted_price_wrapper(
p_product_id INT,
p_user_id INT
)
RETURNS DECIMAL(10, 2)
DETERMINISTIC
BEGIN
RETURN get_product_discounted_price(p_product_id, p_user_id);
END$$
-- Create the price update trigger
CREATE TRIGGER trg_product_price_update
AFTER UPDATE ON products
FOR EACH ROW
BEGIN
IF OLD.price != NEW.price THEN
INSERT INTO product_price_history (product_id, old_price, new_price, changed_by)
VALUES (NEW.product_id, OLD.price, NEW.price, @current_user_id);
END IF;
END$$
-- Create the gift code generation procedure
CREATE PROCEDURE generate_gift_code(
IN p_code_type ENUM('discount', 'free_product', 'balance_add'),
IN p_discount_value DECIMAL(10, 2),
IN p_product_id INT,
IN p_balance_value DECIMAL(10, 2),
IN p_created_by INT,
IN p_expires_days INT,
OUT p_generated_code VARCHAR(50)
)
BEGIN
DECLARE code_exists INT;
SET p_generated_code = CONCAT(
SUBSTRING(MD5(RAND()), 1, 4), '-',
SUBSTRING(MD5(RAND()), 1, 4), '-',
SUBSTRING(MD5(RAND()), 1, 4), '-',
SUBSTRING(MD5(RAND()), 1, 4)
);
SELECT COUNT(*) INTO code_exists FROM gift_codes WHERE code = p_generated_code;
IF code_exists > 0 THEN
CALL generate_gift_code(p_code_type, p_discount_value, p_product_id, p_balance_value, p_created_by, p_expires_days, p_generated_code);
ELSE
INSERT INTO gift_codes (code, code_type, discount_value, product_id, balance_value, created_by, expires_at)
VALUES (
p_generated_code,
p_code_type,
p_discount_value,
p_product_id,
p_balance_value,
p_created_by,
DATE_ADD(CURRENT_TIMESTAMP, INTERVAL p_expires_days DAY)
);
END IF;
END$$
-- Reset delimiter
DELIMITER ;
CREATE TABLE IF NOT EXISTS temp_uploads (
id INT AUTO_INCREMENT PRIMARY KEY,
file_path VARCHAR(255) NOT NULL,
file_url VARCHAR(255) NOT NULL,
user_id INT,
original_filename VARCHAR(255) NOT NULL,
file_type VARCHAR(50) NOT NULL,
file_size INT UNSIGNED DEFAULT NULL,
product_id INT NULL,
temp_product_id VARCHAR(255) NULL,
upload_time DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE SET NULL,
FOREIGN KEY (product_id) REFERENCES products (product_id) ON DELETE SET NULL,
INDEX idx_temp_uploads_temp_product_id (temp_product_id)
);
CREATE TABLE
IF NOT EXISTS user_discounts (
discount_id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
discount_type ENUM('percentage', 'fixed_amount') NOT NULL,
discount_value DECIMAL(10, 2) NOT NULL,
product_id INT NULL,
category VARCHAR(50) NULL,
code VARCHAR(50) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
expires_at DATETIME NOT NULL,
is_active BOOLEAN DEFAULT TRUE,
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE,
FOREIGN KEY (product_id) REFERENCES products (product_id) ON DELETE CASCADE,
INDEX (user_id),
INDEX (code),
INDEX (expires_at)
);
CREATE TABLE IF NOT EXISTS site_settings (
setting_id INT AUTO_INCREMENT PRIMARY KEY,
setting_key VARCHAR(100) NOT NULL UNIQUE,
setting_value TEXT,
setting_type ENUM('boolean', 'string', 'number', 'json', 'datetime') NOT NULL DEFAULT 'string',
section VARCHAR(50) NOT NULL,
label VARCHAR(255) NOT NULL,
description TEXT,
is_public BOOLEAN DEFAULT FALSE,
order_index INT DEFAULT 0,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
updated_by INT,
FOREIGN KEY (updated_by) REFERENCES users (id) ON DELETE SET NULL,
INDEX (section),
INDEX (setting_key),
INDEX (is_public)
);
INSERT IGNORE INTO site_settings
(setting_key, setting_value, setting_type, section, label, description, is_public, order_index)
VALUES
('site_name', 'YeahNOT', 'string', 'general', 'ΠΠ°Π·Π²Π°Π½ΠΈΠ΅ ΡΠ°ΠΉΡΠ°', 'ΠΠ°Π·Π²Π°Π½ΠΈΠ΅ ΡΠ°ΠΉΡΠ°, ΠΎΡΠΎΠ±ΡΠ°ΠΆΠ°Π΅ΠΌΠΎΠ΅ Π² Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ΅ Π±ΡΠ°ΡΠ·Π΅ΡΠ°', TRUE, 10),
('site_description', 'YeahNOT - ΠΡΠΈΡΠΈΠ°Π»ΡΠ½ΡΠΉ ΠΏΡΠΎΠ΅ΠΊΡ', 'string', 'general', 'ΠΠΏΠΈΡΠ°Π½ΠΈΠ΅ ΡΠ°ΠΉΡΠ°', 'ΠΡΠ°ΡΠΊΠΎΠ΅ ΠΎΠΏΠΈΡΠ°Π½ΠΈΠ΅ ΡΠ°ΠΉΡΠ° Π΄Π»Ρ ΠΏΠΎΠΈΡΠΊΠΎΠ²ΡΡ
ΡΠΈΡΡΠ΅ΠΌ', TRUE, 20),
('contact_email', 'admin@example.com', 'string', 'general', 'ΠΠΎΠ½ΡΠ°ΠΊΡΠ½ΡΠΉ email', 'Email Π΄Π»Ρ ΡΠ²ΡΠ·ΠΈ Ρ Π°Π΄ΠΌΠΈΠ½ΠΈΡΡΡΠ°ΡΠΈΠ΅ΠΉ', TRUE, 30),
('default_language', 'ru', 'string', 'general', 'Π―Π·ΡΠΊ ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ', 'Π―Π·ΡΠΊ ΡΠ°ΠΉΡΠ° ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ', TRUE, 40),
('timezone', 'Europe/Moscow', 'string', 'general', 'Π§Π°ΡΠΎΠ²ΠΎΠΉ ΠΏΠΎΡΡ', 'Π§Π°ΡΠΎΠ²ΠΎΠΉ ΠΏΠΎΡΡ ΡΠ°ΠΉΡΠ°', FALSE, 50),
('maintenance_mode', 'false', 'boolean', 'maintenance', 'Π Π΅ΠΆΠΈΠΌ ΡΠ΅Ρ
Π½ΠΈΡΠ΅ΡΠΊΠΎΠ³ΠΎ ΠΎΠ±ΡΠ»ΡΠΆΠΈΠ²Π°Π½ΠΈΡ', 'ΠΡΠ»ΠΈ Π²ΠΊΠ»ΡΡΠ΅Π½ΠΎ, ΡΠ°ΠΉΡ Π±ΡΠ΄Π΅Ρ Π½Π΅Π΄ΠΎΡΡΡΠΏΠ΅Π½ Π΄Π»Ρ ΠΎΠ±ΡΡΠ½ΡΡ
ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Π΅ΠΉ', FALSE, 10),
('maintenance_message', 'Π‘Π°ΠΉΡ Π½Π°Ρ
ΠΎΠ΄ΠΈΡΡΡ Π½Π° ΡΠ΅Ρ
Π½ΠΈΡΠ΅ΡΠΊΠΎΠΌ ΠΎΠ±ΡΠ»ΡΠΆΠΈΠ²Π°Π½ΠΈΠΈ. ΠΠΎΠΆΠ°Π»ΡΠΉΡΡΠ°, Π·Π°ΠΉΠ΄ΠΈΡΠ΅ ΠΏΠΎΠ·ΠΆΠ΅.', 'string', 'maintenance', 'Π‘ΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠ΅ ΠΎ ΡΠ΅Ρ
ΠΎΠ±ΡΠ»ΡΠΆΠΈΠ²Π°Π½ΠΈΠΈ', 'Π‘ΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠ΅, ΠΎΡΠΎΠ±ΡΠ°ΠΆΠ°Π΅ΠΌΠΎΠ΅ Π²ΠΎ Π²ΡΠ΅ΠΌΡ ΡΠ΅Ρ
Π½ΠΈΡΠ΅ΡΠΊΠΎΠ³ΠΎ ΠΎΠ±ΡΠ»ΡΠΆΠΈΠ²Π°Π½ΠΈΡ', FALSE, 20),
('maintenance_allowed_ips', '127.0.0.1', 'string', 'maintenance', 'Π Π°Π·ΡΠ΅ΡΠ΅Π½Π½ΡΠ΅ IP-Π°Π΄ΡΠ΅ΡΠ°', 'Π‘ΠΏΠΈΡΠΎΠΊ IP-Π°Π΄ΡΠ΅ΡΠΎΠ², ΠΊΠΎΡΠΎΡΡΠΌ ΡΠ°Π·ΡΠ΅ΡΠ΅Π½ Π΄ΠΎΡΡΡΠΏ Π² ΡΠ΅ΠΆΠΈΠΌΠ΅ ΡΠ΅Ρ
ΠΎΠ±ΡΠ»ΡΠΆΠΈΠ²Π°Π½ΠΈΡ (ΡΠ΅ΡΠ΅Π· Π·Π°ΠΏΡΡΡΡ)', FALSE, 30),
('maintenance_end_time', NULL, 'datetime', 'maintenance', 'ΠΡΠ΅ΠΌΡ ΠΎΠΊΠΎΠ½ΡΠ°Π½ΠΈΡ ΡΠ΅Ρ
ΠΎΠ±ΡΠ»ΡΠΆΠΈΠ²Π°Π½ΠΈΡ', 'ΠΡΠ»ΠΈ ΡΠΊΠ°Π·Π°Π½ΠΎ, ΡΠ΅ΠΆΠΈΠΌ ΡΠ΅Ρ
ΠΎΠ±ΡΠ»ΡΠΆΠΈΠ²Π°Π½ΠΈΡ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΈ ΠΎΡΠΊΠ»ΡΡΠΈΡΡΡ ΠΏΠΎΡΠ»Π΅ ΡΡΠΎΠ³ΠΎ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ', FALSE, 40),
('enable_registration', 'true', 'boolean', 'registration', 'ΠΠΊΠ»ΡΡΠΈΡΡ ΡΠ΅Π³ΠΈΡΡΡΠ°ΡΠΈΡ', 'Π Π°Π·ΡΠ΅ΡΠΈΡΡ Π½ΠΎΠ²ΡΠΌ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»ΡΠΌ ΡΠ΅Π³ΠΈΡΡΡΠΈΡΠΎΠ²Π°ΡΡΡΡ Π½Π° ΡΠ°ΠΉΡΠ΅', FALSE, 10),
('require_email_verification', 'true', 'boolean', 'registration', 'Π’ΡΠ΅Π±ΠΎΠ²Π°ΡΡ ΠΏΠΎΠ΄ΡΠ²Π΅ΡΠΆΠ΄Π΅Π½ΠΈΠ΅ email', 'ΠΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»ΠΈ Π΄ΠΎΠ»ΠΆΠ½Ρ ΠΏΠΎΠ΄ΡΠ²Π΅ΡΠ΄ΠΈΡΡ ΡΠ²ΠΎΠΉ email ΠΏΠΎΡΠ»Π΅ ΡΠ΅Π³ΠΈΡΡΡΠ°ΡΠΈΠΈ', FALSE, 20),
('allowed_registration_providers', 'discord,telegram,vk,google', 'string', 'registration', 'Π Π°Π·ΡΠ΅ΡΠ΅Π½Π½ΡΠ΅ ΠΏΡΠΎΠ²Π°ΠΉΠ΄Π΅ΡΡ', 'Π‘ΠΏΠΈΡΠΎΠΊ ΡΠ°Π·ΡΠ΅ΡΠ΅Π½Π½ΡΡ
ΠΌΠ΅ΡΠΎΠ΄ΠΎΠ² ΡΠ΅Π³ΠΈΡΡΡΠ°ΡΠΈΠΈ (ΡΠ΅ΡΠ΅Π· Π·Π°ΠΏΡΡΡΡ)', FALSE, 30),
('default_user_role', 'user', 'string', 'registration', 'Π ΠΎΠ»Ρ ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ', 'Π ΠΎΠ»Ρ, Π½Π°Π·Π½Π°ΡΠ°Π΅ΠΌΠ°Ρ Π½ΠΎΠ²ΡΠΌ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»ΡΠΌ', FALSE, 40),
('min_password_length', '8', 'number', 'security', 'ΠΠΈΠ½ΠΈΠΌΠ°Π»ΡΠ½Π°Ρ Π΄Π»ΠΈΠ½Π° ΠΏΠ°ΡΠΎΠ»Ρ', 'ΠΠΈΠ½ΠΈΠΌΠ°Π»ΡΠ½ΠΎΠ΅ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΡΠΈΠΌΠ²ΠΎΠ»ΠΎΠ² Π² ΠΏΠ°ΡΠΎΠ»Π΅', FALSE, 10),
('password_requires_special', 'true', 'boolean', 'security', 'Π’ΡΠ΅Π±ΠΎΠ²Π°ΡΡ ΡΠΏΠ΅ΡΠΈΠ°Π»ΡΠ½ΡΠ΅ ΡΠΈΠΌΠ²ΠΎΠ»Ρ', 'Π’ΡΠ΅Π±ΠΎΠ²Π°ΡΡ Π½Π°Π»ΠΈΡΠΈΠ΅ ΡΠΏΠ΅ΡΠΈΠ°Π»ΡΠ½ΡΡ
ΡΠΈΠΌΠ²ΠΎΠ»ΠΎΠ² Π² ΠΏΠ°ΡΠΎΠ»Π΅', FALSE, 20),
('max_login_attempts', '5', 'number', 'security', 'ΠΠ°ΠΊΡΠΈΠΌΠ°Π»ΡΠ½ΠΎΠ΅ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΠΏΠΎΠΏΡΡΠΎΠΊ Π²Ρ
ΠΎΠ΄Π°', 'ΠΠ°ΠΊΡΠΈΠΌΠ°Π»ΡΠ½ΠΎΠ΅ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ Π½Π΅ΡΠ΄Π°ΡΠ½ΡΡ
ΠΏΠΎΠΏΡΡΠΎΠΊ Π²Ρ
ΠΎΠ΄Π° Π΄ΠΎ Π±Π»ΠΎΠΊΠΈΡΠΎΠ²ΠΊΠΈ', FALSE, 30),
('login_block_time', '30', 'number', 'security', 'ΠΡΠ΅ΠΌΡ Π±Π»ΠΎΠΊΠΈΡΠΎΠ²ΠΊΠΈ (ΠΌΠΈΠ½ΡΡΡ)', 'ΠΡΠ΅ΠΌΡ Π±Π»ΠΎΠΊΠΈΡΠΎΠ²ΠΊΠΈ ΠΏΠΎΡΠ»Π΅ ΠΏΡΠ΅Π²ΡΡΠ΅Π½ΠΈΡ Π»ΠΈΠΌΠΈΡΠ° Π½Π΅ΡΠ΄Π°ΡΠ½ΡΡ
ΠΏΠΎΠΏΡΡΠΎΠΊ Π²Ρ
ΠΎΠ΄Π°', FALSE, 40),
('session_lifetime', '1440', 'number', 'security', 'ΠΡΠ΅ΠΌΡ ΠΆΠΈΠ·Π½ΠΈ ΡΠ΅ΡΡΠΈΠΈ (ΠΌΠΈΠ½ΡΡΡ)', 'ΠΡΠ΅ΠΌΡ Π² ΠΌΠΈΠ½ΡΡΠ°Ρ
Π΄ΠΎ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΎΠ³ΠΎ Π²ΡΡ
ΠΎΠ΄Π° ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ ΠΈΠ· ΡΠΈΡΡΠ΅ΠΌΡ', FALSE, 50),
('marketplace_enabled', 'true', 'boolean', 'marketplace', 'ΠΠΊΠ»ΡΡΠΈΡΡ ΠΌΠ°ΡΠΊΠ΅ΡΠΏΠ»Π΅ΠΉΡ', 'ΠΠΊΠ»ΡΡΠΈΡΡ ΠΈΠ»ΠΈ ΠΎΡΠΊΠ»ΡΡΠΈΡΡ ΡΡΠ½ΠΊΡΠΈΠΎΠ½Π°Π» ΠΌΠ°ΡΠΊΠ΅ΡΠΏΠ»Π΅ΠΉΡΠ°', FALSE, 10),
('allow_free_products', 'true', 'boolean', 'marketplace', 'Π Π°Π·ΡΠ΅ΡΠΈΡΡ Π±Π΅ΡΠΏΠ»Π°ΡΠ½ΡΠ΅ ΡΠΎΠ²Π°ΡΡ', 'Π Π°Π·ΡΠ΅ΡΠΈΡΡ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»ΡΠΌ ΠΏΡΠ±Π»ΠΈΠΊΠΎΠ²Π°ΡΡ Π±Π΅ΡΠΏΠ»Π°ΡΠ½ΡΠ΅ ΡΠΎΠ²Π°ΡΡ', FALSE, 20),
('marketplace_commission', '10', 'number', 'marketplace', 'ΠΠΎΠΌΠΈΡΡΠΈΡ ΠΌΠ°ΡΠΊΠ΅ΡΠΏΠ»Π΅ΠΉΡΠ° (%)', 'ΠΡΠΎΡΠ΅Π½Ρ ΠΊΠΎΠΌΠΈΡΡΠΈΠΈ ΠΎΡ ΠΏΡΠΎΠ΄Π°ΠΆ Π½Π° ΠΌΠ°ΡΠΊΠ΅ΡΠΏΠ»Π΅ΠΉΡΠ΅', FALSE, 30),
('minimum_product_price', '50', 'number', 'marketplace', 'ΠΠΈΠ½ΠΈΠΌΠ°Π»ΡΠ½Π°Ρ ΡΠ΅Π½Π° ΡΠΎΠ²Π°ΡΠ° (β½)', 'ΠΠΈΠ½ΠΈΠΌΠ°Π»ΡΠ½Π°Ρ Π΄ΠΎΠΏΡΡΡΠΈΠΌΠ°Ρ ΡΠ΅Π½Π° Π΄Π»Ρ ΠΏΠ»Π°ΡΠ½ΡΡ
ΡΠΎΠ²Π°ΡΠΎΠ²', FALSE, 40),
('marketplace_categories', 'scripts,materials,menu,models_weapon,models_character', 'string', 'marketplace', 'ΠΠ°ΡΠ΅Π³ΠΎΡΠΈΠΈ ΡΠΎΠ²Π°ΡΠΎΠ²', 'Π‘ΠΏΠΈΡΠΎΠΊ Π΄ΠΎΡΡΡΠΏΠ½ΡΡ
ΠΊΠ°ΡΠ΅Π³ΠΎΡΠΈΠΉ ΡΠΎΠ²Π°ΡΠΎΠ² (ΡΠ΅ΡΠ΅Π· Π·Π°ΠΏΡΡΡΡ)', FALSE, 50),
('social_links', '{"discord":"https://discord.com","telegram":"https://t.me","vk":"https://vk.com"}', 'json', 'social', 'Π‘ΠΎΡΠΈΠ°Π»ΡΠ½ΡΠ΅ ΡΠ΅ΡΠΈ', 'Π‘ΡΡΠ»ΠΊΠΈ Π½Π° ΡΠΎΡΠΈΠ°Π»ΡΠ½ΡΠ΅ ΡΠ΅ΡΠΈ (JSON)', TRUE, 10),
('show_social_icons', 'true', 'boolean', 'social', 'ΠΠΎΠΊΠ°Π·ΡΠ²Π°ΡΡ ΠΈΠΊΠΎΠ½ΠΊΠΈ ΡΠΎΡΡΠ΅ΡΠ΅ΠΉ', 'ΠΡΠΎΠ±ΡΠ°ΠΆΠ°ΡΡ ΠΈΠΊΠΎΠ½ΠΊΠΈ ΡΠΎΡΠΈΠ°Π»ΡΠ½ΡΡ
ΡΠ΅ΡΠ΅ΠΉ Π² ΡΡΡΠ΅ΡΠ΅', TRUE, 20),
('logo_url', '/images/logo.png', 'string', 'appearance', 'URL Π»ΠΎΠ³ΠΎΡΠΈΠΏΠ°', 'URL Π»ΠΎΠ³ΠΎΡΠΈΠΏΠ° ΡΠ°ΠΉΡΠ°', TRUE, 10),
('favicon_url', '/favicon.ico', 'string', 'appearance', 'URL favicon', 'URL favicon ΡΠ°ΠΉΡΠ°', TRUE, 20),
('theme_color', '#ffffff', 'string', 'appearance', 'ΠΡΠ½ΠΎΠ²Π½ΠΎΠΉ ΡΠ²Π΅Ρ ΡΠ΅ΠΌΡ', 'ΠΡΠ½ΠΎΠ²Π½ΠΎΠΉ ΡΠ²Π΅Ρ ΡΠ΅ΠΌΡ ΡΠ°ΠΉΡΠ°', TRUE, 30),
('dark_mode_default', 'true', 'boolean', 'appearance', 'Π’Π΅ΠΌΠ½Π°Ρ ΡΠ΅ΠΌΠ° ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ', 'ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΡΠ΅ΠΌΠ½ΡΡ ΡΠ΅ΠΌΡ ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ', TRUE, 40),
('enable_analytics', 'false', 'boolean', 'analytics', 'ΠΠΊΠ»ΡΡΠΈΡΡ Π°Π½Π°Π»ΠΈΡΠΈΠΊΡ', 'ΠΠΊΠ»ΡΡΠΈΡΡ ΡΠ±ΠΎΡ Π°Π½Π°Π»ΠΈΡΠΈΠΊΠΈ Π½Π° ΡΠ°ΠΉΡΠ΅', FALSE, 10),
('analytics_provider', 'google', 'string', 'analytics', 'ΠΡΠΎΠ²Π°ΠΉΠ΄Π΅Ρ Π°Π½Π°Π»ΠΈΡΠΈΠΊΠΈ', 'Π‘Π΅ΡΠ²ΠΈΡ Π΄Π»Ρ ΡΠ±ΠΎΡΠ° Π°Π½Π°Π»ΠΈΡΠΈΠΊΠΈ', FALSE, 20),
('analytics_id', '', 'string', 'analytics', 'ID Π°Π½Π°Π»ΠΈΡΠΈΠΊΠΈ', 'ID ΠΈΠ»ΠΈ ΠΊΠ»ΡΡ ΡΠ΅ΡΠ²ΠΈΡΠ° Π°Π½Π°Π»ΠΈΡΠΈΠΊΠΈ', FALSE, 30);