diff --git a/database/sql/_helpers/safe_add_column.sql b/database/sql/_helpers/safe_add_column.sql new file mode 100644 index 0000000..18a7486 --- /dev/null +++ b/database/sql/_helpers/safe_add_column.sql @@ -0,0 +1,34 @@ +-- ============================================================================= +-- الگوی copy/paste برای اضافه کردن امن یک ستون +-- ============================================================================= +-- 1) USE دیتابیس +-- 2) @table_name و @column_name و @alter_sql را عوض کنید +-- 3) @after_column اختیاری است — اگر خالی باشد بدون AFTER اضافه می‌شود +-- ============================================================================= + +SET @db = DATABASE(); +SET @table_name = 'products'; +SET @column_name = 'show_in_assets'; +SET @after_column = 'show'; +SET @column_def = 'TINYINT(1) NOT NULL DEFAULT 1 COMMENT ''نمایش در صفحه دارایی‌ها'''; + +SET @sql = IF( + (SELECT COUNT(*) FROM information_schema.TABLES + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = @table_name) = 0, + CONCAT('SELECT ''skip: table '', @table_name, '' not found'' AS info'), + IF( + (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = @table_name AND COLUMN_NAME = @column_name) > 0, + CONCAT('SELECT ''skip: column '', @column_name, '' exists'' AS info'), + IF( + @after_column IS NOT NULL AND @after_column <> '' + AND (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = @table_name AND COLUMN_NAME = @after_column) > 0, + CONCAT('ALTER TABLE `', @table_name, '` ADD COLUMN `', @column_name, '` ', @column_def, ' AFTER `', @after_column, '`'), + CONCAT('ALTER TABLE `', @table_name, '` ADD COLUMN `', @column_name, '` ', @column_def) + ) + ) +); +PREPARE stmt FROM @sql; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; diff --git a/database/sql/add_product_show_in_assets.sql b/database/sql/add_product_show_in_assets.sql index 2238559..6a99b09 100644 --- a/database/sql/add_product_show_in_assets.sql +++ b/database/sql/add_product_show_in_assets.sql @@ -1,13 +1,24 @@ -- نمایش موجودی محصول در صفحه دارایی‌ها +-- امن برای اجرای مجدد — جزئیات کامل: deploy_safe_schema.sql -- USE دیتابیس_خودتان; SET @db = DATABASE(); SET @sql = IF( - (SELECT COUNT(*) FROM information_schema.COLUMNS - WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'products' AND COLUMN_NAME = 'show_in_assets') = 0, - 'ALTER TABLE `products` ADD COLUMN `show_in_assets` TINYINT(1) NOT NULL DEFAULT 1 COMMENT ''نمایش در صفحه دارایی‌ها'' AFTER `show`', - 'SELECT 1' + (SELECT COUNT(*) FROM information_schema.TABLES + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'products') = 0, + 'SELECT ''skip: products table not found'' AS info', + IF( + (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'products' AND COLUMN_NAME = 'show_in_assets') > 0, + 'SELECT ''skip: show_in_assets exists'' AS info', + IF( + (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'products' AND COLUMN_NAME = 'show') > 0, + 'ALTER TABLE `products` ADD COLUMN `show_in_assets` TINYINT(1) NOT NULL DEFAULT 1 COMMENT ''نمایش در صفحه دارایی‌ها'' AFTER `show`', + 'ALTER TABLE `products` ADD COLUMN `show_in_assets` TINYINT(1) NOT NULL DEFAULT 1 COMMENT ''نمایش در صفحه دارایی‌ها''' + ) + ) ); PREPARE stmt FROM @sql; EXECUTE stmt; diff --git a/database/sql/deploy_safe_schema.sql b/database/sql/deploy_safe_schema.sql new file mode 100644 index 0000000..21a3d57 --- /dev/null +++ b/database/sql/deploy_safe_schema.sql @@ -0,0 +1,258 @@ +-- ============================================================================= +-- اسکریپت امن deploy — چند بار قابل اجرا؛ اگر ستون/جدول باشد خطا نمی‌دهد +-- ============================================================================= +-- قبل از اجرا: +-- USE `نام_دیتابیس`; +-- (اختیاری) mysqldump بکاپ +-- +-- الگو: فقط وقتی جدول هست و ستون نیست → ALTER +-- ============================================================================= + +SET @db = DATABASE(); + +-- --------------------------------------------------------------------------- +-- products.show_in_assets (صفحه دارایی‌ها) +-- --------------------------------------------------------------------------- +SET @sql = IF( + (SELECT COUNT(*) FROM information_schema.TABLES + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'products') > 0 + AND (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'products' AND COLUMN_NAME = 'show_in_assets') = 0, + IF( + (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'products' AND COLUMN_NAME = 'show') > 0, + 'ALTER TABLE `products` ADD COLUMN `show_in_assets` TINYINT(1) NOT NULL DEFAULT 1 COMMENT ''نمایش در صفحه دارایی‌ها'' AFTER `show`', + 'ALTER TABLE `products` ADD COLUMN `show_in_assets` TINYINT(1) NOT NULL DEFAULT 1 COMMENT ''نمایش در صفحه دارایی‌ها''' + ), + 'SELECT ''skip products.show_in_assets'' AS info' +); +PREPARE stmt FROM @sql; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +-- --------------------------------------------------------------------------- +-- products — محدودیت مبلغ سفارش +-- --------------------------------------------------------------------------- +SET @sql = IF( + (SELECT COUNT(*) FROM information_schema.TABLES + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'products') > 0 + AND (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'products' AND COLUMN_NAME = 'order_limit_enabled') = 0, + IF( + (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'products' AND COLUMN_NAME = 'percent_fee_buy') > 0, + 'ALTER TABLE `products` ADD COLUMN `order_limit_enabled` TINYINT(1) NOT NULL DEFAULT 0 AFTER `percent_fee_buy`', + 'ALTER TABLE `products` ADD COLUMN `order_limit_enabled` TINYINT(1) NOT NULL DEFAULT 0' + ), + 'SELECT ''skip products.order_limit_enabled'' AS info' +); +PREPARE stmt FROM @sql; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +SET @sql = IF( + (SELECT COUNT(*) FROM information_schema.TABLES + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'products') > 0 + AND (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'products' AND COLUMN_NAME = 'min_order_cash') = 0, + IF( + (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'products' AND COLUMN_NAME = 'order_limit_enabled') > 0, + 'ALTER TABLE `products` ADD COLUMN `min_order_cash` BIGINT UNSIGNED NULL DEFAULT NULL AFTER `order_limit_enabled`', + 'ALTER TABLE `products` ADD COLUMN `min_order_cash` BIGINT UNSIGNED NULL DEFAULT NULL' + ), + 'SELECT ''skip products.min_order_cash'' AS info' +); +PREPARE stmt FROM @sql; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +SET @sql = IF( + (SELECT COUNT(*) FROM information_schema.TABLES + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'products') > 0 + AND (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'products' AND COLUMN_NAME = 'max_order_cash') = 0, + IF( + (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'products' AND COLUMN_NAME = 'min_order_cash') > 0, + 'ALTER TABLE `products` ADD COLUMN `max_order_cash` BIGINT UNSIGNED NULL DEFAULT NULL AFTER `min_order_cash`', + 'ALTER TABLE `products` ADD COLUMN `max_order_cash` BIGINT UNSIGNED NULL DEFAULT NULL' + ), + 'SELECT ''skip products.max_order_cash'' AS info' +); +PREPARE stmt FROM @sql; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +-- --------------------------------------------------------------------------- +-- products.price_offset_percent +-- --------------------------------------------------------------------------- +SET @sql = IF( + (SELECT COUNT(*) FROM information_schema.TABLES + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'products') > 0 + AND (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'products' AND COLUMN_NAME = 'price_offset_percent') = 0, + IF( + (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'products' AND COLUMN_NAME = 'price_profit') > 0, + 'ALTER TABLE `products` ADD COLUMN `price_offset_percent` DECIMAL(8,2) NOT NULL DEFAULT 0 AFTER `price_profit`', + 'ALTER TABLE `products` ADD COLUMN `price_offset_percent` DECIMAL(8,2) NOT NULL DEFAULT 0' + ), + 'SELECT ''skip products.price_offset_percent'' AS info' +); +PREPARE stmt FROM @sql; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +-- --------------------------------------------------------------------------- +-- customers.total_referrals +-- --------------------------------------------------------------------------- +SET @sql = IF( + (SELECT COUNT(*) FROM information_schema.TABLES + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'customers') > 0 + AND (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'customers' AND COLUMN_NAME = 'total_referrals') = 0, + IF( + (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'customers' AND COLUMN_NAME = 'referral_to_id') > 0, + 'ALTER TABLE `customers` ADD COLUMN `total_referrals` INT UNSIGNED NOT NULL DEFAULT 0 AFTER `referral_to_id`', + 'ALTER TABLE `customers` ADD COLUMN `total_referrals` INT UNSIGNED NOT NULL DEFAULT 0' + ), + 'SELECT ''skip customers.total_referrals'' AS info' +); +PREPARE stmt FROM @sql; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +-- --------------------------------------------------------------------------- +-- orders — فیلدهای provider (Montzar و ...) +-- --------------------------------------------------------------------------- +SET @sql = IF( + (SELECT COUNT(*) FROM information_schema.TABLES + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'orders') > 0 + AND (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'orders' AND COLUMN_NAME = 'provider_id') = 0, + 'ALTER TABLE `orders` ADD COLUMN `provider_id` BIGINT UNSIGNED NULL AFTER `id`, ADD INDEX `orders_provider_id_index` (`provider_id`)', + 'SELECT ''skip orders.provider_id'' AS info' +); +PREPARE stmt FROM @sql; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +SET @sql = IF( + (SELECT COUNT(*) FROM information_schema.TABLES + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'orders') > 0 + AND (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'orders' AND COLUMN_NAME = 'total_price_montzar') = 0, + IF( + (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'orders' AND COLUMN_NAME = 'total_price') > 0, + 'ALTER TABLE `orders` ADD COLUMN `total_price_montzar` DECIMAL(20,4) NULL DEFAULT NULL AFTER `total_price`', + 'ALTER TABLE `orders` ADD COLUMN `total_price_montzar` DECIMAL(20,4) NULL DEFAULT NULL' + ), + 'SELECT ''skip orders.total_price_montzar'' AS info' +); +PREPARE stmt FROM @sql; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +-- --------------------------------------------------------------------------- +-- withdraws — ستون‌های اختیاری (روی بعضی سرورها دستی اضافه شده) +-- --------------------------------------------------------------------------- +SET @sql = IF( + (SELECT COUNT(*) FROM information_schema.TABLES + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'withdraws') > 0 + AND (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'withdraws' AND COLUMN_NAME = 'type') = 0, + 'ALTER TABLE `withdraws` ADD COLUMN `type` TINYINT UNSIGNED NULL DEFAULT NULL', + 'SELECT ''skip withdraws.type'' AS info' +); +PREPARE stmt FROM @sql; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +SET @sql = IF( + (SELECT COUNT(*) FROM information_schema.TABLES + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'withdraws') > 0 + AND (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'withdraws' AND COLUMN_NAME = 'note') = 0, + 'ALTER TABLE `withdraws` ADD COLUMN `note` VARCHAR(255) NULL DEFAULT NULL', + 'SELECT ''skip withdraws.note'' AS info' +); +PREPARE stmt FROM @sql; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +SET @sql = IF( + (SELECT COUNT(*) FROM information_schema.TABLES + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'withdraws') > 0 + AND (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'withdraws' AND COLUMN_NAME = 'bank_account_id') = 0, + 'ALTER TABLE `withdraws` ADD COLUMN `bank_account_id` INT UNSIGNED NULL DEFAULT NULL', + 'SELECT ''skip withdraws.bank_account_id'' AS info' +); +PREPARE stmt FROM @sql; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +-- --------------------------------------------------------------------------- +-- logs.data → LONGTEXT (اگر جدول logs باشد) +-- --------------------------------------------------------------------------- +SET @sql = IF( + (SELECT COUNT(*) FROM information_schema.TABLES + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'logs') > 0 + AND (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'logs' AND COLUMN_NAME = 'data') > 0, + 'ALTER TABLE `logs` MODIFY COLUMN `data` LONGTEXT NULL', + 'SELECT ''skip logs.data'' AS info' +); +PREPARE stmt FROM @sql; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +-- --------------------------------------------------------------------------- +-- settings.type (پنل ادمین — نوع فیلد) +-- --------------------------------------------------------------------------- +SET @sql = IF( + (SELECT COUNT(*) FROM information_schema.TABLES + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'settings') > 0 + AND (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'settings' AND COLUMN_NAME = 'type') = 0, + IF( + (SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'settings' AND COLUMN_NAME = 'description') > 0, + 'ALTER TABLE `settings` ADD COLUMN `type` VARCHAR(64) NULL DEFAULT NULL COMMENT ''نوع فیلد در پنل ادمین'' AFTER `description`', + 'ALTER TABLE `settings` ADD COLUMN `type` VARCHAR(64) NULL DEFAULT NULL COMMENT ''نوع فیلد در پنل ادمین''' + ), + 'SELECT ''skip settings.type'' AS info' +); +PREPARE stmt FROM @sql; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +-- --------------------------------------------------------------------------- +-- settings — ردیف unit (بدون overwrite مقدار موجود) +-- --------------------------------------------------------------------------- +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT + 'unit', + '', + 'واحد وزن دارایی و معاملات', + 1, + 1, + 'واحد نمایش وزن فلز در دارایی‌ها، کیف پول و تراکنش‌ها|گرم,کیلوگرم', + 'select' +FROM DUAL +WHERE EXISTS ( + SELECT 1 FROM information_schema.TABLES + WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'settings' +) +AND NOT EXISTS ( + SELECT 1 FROM `settings` WHERE `key` = 'unit' LIMIT 1 +); + +-- --------------------------------------------------------------------------- +-- پایان — برای بورس‌مس (اختیاری، جدا اجرا کنید): +-- UPDATE `settings` SET `value` = 'کیلوگرم' WHERE `key` = 'unit'; +-- --------------------------------------------------------------------------- +SELECT 'deploy_safe_schema.sql finished' AS status;