using IBKRTrader.Core.Logging; namespace IBKRTrader.Core.Database.Migrations; /// /// Erstellt alle core_xxx-Tabellen idempotent (IF NOT EXISTS). /// Wird einmalig beim App-Start ausgeführt. /// public class CoreMigrations { private readonly DatabaseService _db; private readonly LoggingService _logger; public CoreMigrations(DatabaseService db, LoggingService logger) { _db = db; _logger = logger; } public async Task RunAsync() { _logger.Info("Core", "Starte Core-Datenbankmigrationen..."); await CreateCoreSettingsAsync(); await CreateCoreWorkerLogAsync(); await CreateCoreTradeHistoryAsync(); await CreateCoreBudgetAsync(); await CreateCorePositionAsync(); _logger.Info("Core", "Core-Migrationen abgeschlossen."); } // ─── Tabellen ───────────────────────────────────────────────────────────── private Task CreateCoreSettingsAsync() => _db.ExecuteAsync(@" CREATE TABLE IF NOT EXISTS `core_settings` ( `key` VARCHAR(100) NOT NULL PRIMARY KEY, `value` TEXT, `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;"); private Task CreateCoreWorkerLogAsync() => _db.ExecuteAsync(@" CREATE TABLE IF NOT EXISTS `core_worker_log` ( `id` BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, `worker_name` VARCHAR(100) NOT NULL, `module` VARCHAR(50) NOT NULL DEFAULT 'Core', `started_at` DATETIME, `finished_at` DATETIME, `status` ENUM('Running','Success','Error') DEFAULT 'Running', `message` TEXT, INDEX `idx_worker` (`worker_name`, `started_at`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;"); private Task CreateCoreTradeHistoryAsync() => _db.ExecuteAsync(@" CREATE TABLE IF NOT EXISTS `core_trade_history` ( `id` BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, `module` VARCHAR(50) NOT NULL, `symbol` VARCHAR(20) NOT NULL, `action` ENUM('BUY','SELL') NOT NULL, `quantity` DECIMAL(18,4), `price` DECIMAL(18,4), `total_value` DECIMAL(18,4), `traded_at` DATETIME, `ibkr_order_id` VARCHAR(100), `status` VARCHAR(50), `notes` TEXT, `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP, INDEX `idx_symbol` (`symbol`), INDEX `idx_module` (`module`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;"); private Task CreateCoreBudgetAsync() => _db.ExecuteAsync(@" CREATE TABLE IF NOT EXISTS `core_budget` ( `module` VARCHAR(50) NOT NULL PRIMARY KEY, `total_budget` DECIMAL(18,2) DEFAULT 0, `used_budget` DECIMAL(18,2) DEFAULT 0, `max_per_trade` DECIMAL(18,2) DEFAULT 0, `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;"); private Task CreateCorePositionAsync() => _db.ExecuteAsync(@" CREATE TABLE IF NOT EXISTS `core_position` ( `module` VARCHAR(50) NOT NULL, `symbol` VARCHAR(20) NOT NULL, `quantity` INT NOT NULL DEFAULT 0, `avg_price` DECIMAL(18,4) NOT NULL DEFAULT 0, `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`module`, `symbol`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;"); }