| | | 1 | | using Microsoft.EntityFrameworkCore.Infrastructure; |
| | | 2 | | using Microsoft.EntityFrameworkCore.Migrations; |
| | | 3 | | |
| | | 4 | | #nullable disable |
| | | 5 | | |
| | | 6 | | namespace OzonRepositories.Migrations |
| | | 7 | | { |
| | | 8 | | /// <summary> |
| | | 9 | | /// Догоняет боевую БД до baseline. |
| | | 10 | | /// |
| | | 11 | | /// Схема ST2 годами велась руками, поэтому в нескольких местах она оказалась слабее |
| | | 12 | | /// модели: не хватало индексов и внешних ключей, часть колонок допускала NULL, |
| | | 13 | | /// таймстемпы были объявлены типом TIMESTAMP. Baseline на проде только штампуется |
| | | 14 | | /// (таблицы там уже есть), а реальные расхождения закрывает эта миграция. |
| | | 15 | | /// |
| | | 16 | | /// Все операции идемпотентны за счёт IF EXISTS / IF NOT EXISTS (MariaDB) — на чистой |
| | | 17 | | /// базе, где baseline отработал полностью, миграция ничего не меняет. |
| | | 18 | | /// </summary> |
| | | 19 | | [DbContext(typeof(Context.ApplicationDbContext))] |
| | | 20 | | [Migration("20260908110300_ReconcileProdSchema")] |
| | | 21 | | public partial class ReconcileProdSchema : Migration |
| | | 22 | | { |
| | | 23 | | /// <inheritdoc /> |
| | | 24 | | protected override void Up(MigrationBuilder migrationBuilder) |
| | | 25 | | { |
| | | 26 | | // --- Колонки, которые в БД допускали NULL, хотя данных с NULL нет --- |
| | 0 | 27 | | migrationBuilder.Sql("ALTER TABLE `ExcelMappings` MODIFY COLUMN `CreatedBy` varchar(255) CHARACTER SET utf8m |
| | 0 | 28 | | migrationBuilder.Sql("ALTER TABLE `FileUploadRecords` MODIFY COLUMN `Result` text CHARACTER SET utf8mb4 NOT |
| | 0 | 29 | | migrationBuilder.Sql("ALTER TABLE `PriceHistories` MODIFY COLUMN `RegistrationPrice` decimal(18,2) NOT NULL; |
| | | 30 | | |
| | | 31 | | // --- StatusTransitions / StatusTransitionHistory: TIMESTAMP → datetime(6), |
| | | 32 | | // беззнаковый ключ → знаковый, обязательные флаги --- |
| | 0 | 33 | | migrationBuilder.Sql("ALTER TABLE `StatusTransitions` MODIFY COLUMN `IsActive` tinyint(1) NOT NULL DEFAULT 1 |
| | 0 | 34 | | migrationBuilder.Sql("ALTER TABLE `StatusTransitions` MODIFY COLUMN `IsRepeatable` tinyint(1) NOT NULL DEFAU |
| | 0 | 35 | | migrationBuilder.Sql("ALTER TABLE `StatusTransitions` MODIFY COLUMN `CreatedAt` datetime(6) NOT NULL;"); |
| | 0 | 36 | | migrationBuilder.Sql("ALTER TABLE `StatusTransitions` MODIFY COLUMN `UpdatedAt` datetime(6) NULL;"); |
| | 0 | 37 | | migrationBuilder.Sql("ALTER TABLE `StatusTransitionHistory` MODIFY COLUMN `PerformedAt` datetime(6) NOT NULL |
| | 0 | 38 | | migrationBuilder.Sql("ALTER TABLE `StatusTransitionHistory` MODIFY COLUMN `Id` bigint NOT NULL AUTO_INCREMEN |
| | 0 | 39 | | migrationBuilder.Sql("ALTER TABLE `order_extensions` MODIFY COLUMN `Id` int NOT NULL AUTO_INCREMENT;"); |
| | | 40 | | |
| | | 41 | | // --- Индексы, которых на проде не было --- |
| | 0 | 42 | | migrationBuilder.Sql("CREATE INDEX IF NOT EXISTS `IX_BitrixStockAutoSchedules_OzonClientId` ON `BitrixStockA |
| | 0 | 43 | | migrationBuilder.Sql("CREATE INDEX IF NOT EXISTS `IX_OrderItems_StudioOrderId` ON `OrderItems` (`StudioOrder |
| | 0 | 44 | | migrationBuilder.Sql("CREATE INDEX IF NOT EXISTS `IX_OrderShipmentTotals_OrderId` ON `OrderShipmentTotals` ( |
| | 0 | 45 | | migrationBuilder.Sql("CREATE INDEX IF NOT EXISTS `IX_Orders_EtProducerId` ON `Orders` (`EtProducerId`);"); |
| | 0 | 46 | | migrationBuilder.Sql("CREATE INDEX IF NOT EXISTS `IX_OzonChatOrders_ChatId` ON `OzonChatOrders` (`ChatId`);" |
| | 0 | 47 | | migrationBuilder.Sql("CREATE INDEX IF NOT EXISTS `IX_OzonChatOrders_ChatId_OrderId` ON `OzonChatOrders` (`Ch |
| | 0 | 48 | | migrationBuilder.Sql("CREATE INDEX IF NOT EXISTS `IX_OzonChatOrders_IsActive_ClientId` ON `OzonChatOrders` ( |
| | 0 | 49 | | migrationBuilder.Sql("CREATE INDEX IF NOT EXISTS `IX_OzonChatOrders_PostingNumber` ON `OzonChatOrders` (`Pos |
| | 0 | 50 | | migrationBuilder.Sql("CREATE INDEX IF NOT EXISTS `IX_Products_ReplacementProductId` ON `Products` (`Replacem |
| | | 51 | | |
| | | 52 | | // --- Избыточные индексы: левый префикс уже покрыт составным / уникальным --- |
| | 0 | 53 | | migrationBuilder.Sql("ALTER TABLE `Orders` DROP INDEX IF EXISTS `IX_Orders_AppStatusId`;"); |
| | 0 | 54 | | migrationBuilder.Sql("ALTER TABLE `OrderArchives` DROP INDEX IF EXISTS `IX_OrderArchives_OrderId`;"); |
| | | 55 | | |
| | | 56 | | // --- Внешние ключи join-таблицы прав указывали на легаси-таблицы *V2 --- |
| | 0 | 57 | | migrationBuilder.Sql("ALTER TABLE `AccessProfileDataScopeSets` DROP FOREIGN KEY IF EXISTS `FK_AccessProfileD |
| | 0 | 58 | | migrationBuilder.Sql("ALTER TABLE `AccessProfileDataScopeSets` DROP FOREIGN KEY IF EXISTS `FK_AccessProfileD |
| | | 59 | | |
| | | 60 | | // 59 строк OrderItems ссылались на давно удалённые заказы — с такой ссылкой |
| | | 61 | | // внешний ключ не создать. Сами строки сохраняем, обнуляем только ссылку. |
| | 0 | 62 | | migrationBuilder.Sql(@"UPDATE `OrderItems` c |
| | 0 | 63 | | LEFT JOIN `Orders` p ON p.`Id` = c.`StudioOrderId` |
| | 0 | 64 | | SET c.`StudioOrderId` = NULL |
| | 0 | 65 | | WHERE c.`StudioOrderId` IS NOT NULL AND p.`Id` IS NULL;"); |
| | | 66 | | |
| | | 67 | | // --- Внешние ключи, которых на проде не было --- |
| | 0 | 68 | | migrationBuilder.Sql(@"ALTER TABLE `AccessProfileDataScopeSets` |
| | 0 | 69 | | ADD CONSTRAINT `FK_AccessProfileDataScopeSets_AccessProfiles_AccessProfilesId` |
| | 0 | 70 | | FOREIGN KEY IF NOT EXISTS (`AccessProfilesId`) REFERENCES `AccessProfiles` (`Id`) ON DELETE CASCADE;"); |
| | 0 | 71 | | migrationBuilder.Sql(@"ALTER TABLE `AccessProfileDataScopeSets` |
| | 0 | 72 | | ADD CONSTRAINT `FK_AccessProfileDataScopeSets_DataScopeSets_DataScopeSetsId` |
| | 0 | 73 | | FOREIGN KEY IF NOT EXISTS (`DataScopeSetsId`) REFERENCES `DataScopeSets` (`Id`) ON DELETE CASCADE;"); |
| | 0 | 74 | | migrationBuilder.Sql(@"ALTER TABLE `AssemblyListRunItems` |
| | 0 | 75 | | ADD CONSTRAINT `FK_AssemblyListRunItems_AssemblyListRuns_RunId` |
| | 0 | 76 | | FOREIGN KEY IF NOT EXISTS (`RunId`) REFERENCES `AssemblyListRuns` (`Id`) ON DELETE CASCADE;"); |
| | 0 | 77 | | migrationBuilder.Sql(@"ALTER TABLE `BitrixStockAutoSchedules` |
| | 0 | 78 | | ADD CONSTRAINT `FK_BitrixStockAutoSchedules_OzonClients_OzonClientId` |
| | 0 | 79 | | FOREIGN KEY IF NOT EXISTS (`OzonClientId`) REFERENCES `OzonClients` (`Id`) ON DELETE CASCADE;"); |
| | 0 | 80 | | migrationBuilder.Sql(@"ALTER TABLE `OrderItems` |
| | 0 | 81 | | ADD CONSTRAINT `FK_OrderItems_Orders_StudioOrderId` |
| | 0 | 82 | | FOREIGN KEY IF NOT EXISTS (`StudioOrderId`) REFERENCES `Orders` (`Id`) ON DELETE RESTRICT;"); |
| | 0 | 83 | | migrationBuilder.Sql(@"ALTER TABLE `Orders` |
| | 0 | 84 | | ADD CONSTRAINT `FK_Orders_et_producers_EtProducerId` |
| | 0 | 85 | | FOREIGN KEY IF NOT EXISTS (`EtProducerId`) REFERENCES `et_producers` (`id`) ON DELETE RESTRICT;"); |
| | 0 | 86 | | migrationBuilder.Sql(@"ALTER TABLE `OzonChatResponseTimes` |
| | 0 | 87 | | ADD CONSTRAINT `FK_OzonChatResponseTimes_OzonClients_ClientId` |
| | 0 | 88 | | FOREIGN KEY IF NOT EXISTS (`ClientId`) REFERENCES `OzonClients` (`Id`) ON DELETE CASCADE;"); |
| | 0 | 89 | | migrationBuilder.Sql(@"ALTER TABLE `Products` |
| | 0 | 90 | | ADD CONSTRAINT `FK_Products_Products_ReplacementProductId` |
| | 0 | 91 | | FOREIGN KEY IF NOT EXISTS (`ReplacementProductId`) REFERENCES `Products` (`Id`) ON DELETE RESTRICT;"); |
| | 0 | 92 | | } |
| | | 93 | | |
| | | 94 | | /// <inheritdoc /> |
| | | 95 | | protected override void Down(MigrationBuilder migrationBuilder) |
| | | 96 | | { |
| | 0 | 97 | | migrationBuilder.Sql("ALTER TABLE `Products` DROP FOREIGN KEY IF EXISTS `FK_Products_Products_ReplacementPro |
| | 0 | 98 | | migrationBuilder.Sql("ALTER TABLE `OzonChatResponseTimes` DROP FOREIGN KEY IF EXISTS `FK_OzonChatResponseTim |
| | 0 | 99 | | migrationBuilder.Sql("ALTER TABLE `Orders` DROP FOREIGN KEY IF EXISTS `FK_Orders_et_producers_EtProducerId`; |
| | 0 | 100 | | migrationBuilder.Sql("ALTER TABLE `OrderItems` DROP FOREIGN KEY IF EXISTS `FK_OrderItems_Orders_StudioOrderI |
| | 0 | 101 | | migrationBuilder.Sql("ALTER TABLE `BitrixStockAutoSchedules` DROP FOREIGN KEY IF EXISTS `FK_BitrixStockAutoS |
| | 0 | 102 | | migrationBuilder.Sql("ALTER TABLE `AssemblyListRunItems` DROP FOREIGN KEY IF EXISTS `FK_AssemblyListRunItems |
| | 0 | 103 | | migrationBuilder.Sql("ALTER TABLE `AccessProfileDataScopeSets` DROP FOREIGN KEY IF EXISTS `FK_AccessProfileD |
| | 0 | 104 | | migrationBuilder.Sql("ALTER TABLE `AccessProfileDataScopeSets` DROP FOREIGN KEY IF EXISTS `FK_AccessProfileD |
| | | 105 | | |
| | 0 | 106 | | migrationBuilder.Sql("CREATE INDEX IF NOT EXISTS `IX_OrderArchives_OrderId` ON `OrderArchives` (`OrderId`);" |
| | 0 | 107 | | migrationBuilder.Sql("CREATE INDEX IF NOT EXISTS `IX_Orders_AppStatusId` ON `Orders` (`AppStatusId`);"); |
| | | 108 | | |
| | 0 | 109 | | migrationBuilder.Sql("ALTER TABLE `Products` DROP INDEX IF EXISTS `IX_Products_ReplacementProductId`;"); |
| | 0 | 110 | | migrationBuilder.Sql("ALTER TABLE `OzonChatOrders` DROP INDEX IF EXISTS `IX_OzonChatOrders_PostingNumber`;") |
| | 0 | 111 | | migrationBuilder.Sql("ALTER TABLE `OzonChatOrders` DROP INDEX IF EXISTS `IX_OzonChatOrders_IsActive_ClientId |
| | 0 | 112 | | migrationBuilder.Sql("ALTER TABLE `OzonChatOrders` DROP INDEX IF EXISTS `IX_OzonChatOrders_ChatId_OrderId`;" |
| | 0 | 113 | | migrationBuilder.Sql("ALTER TABLE `OzonChatOrders` DROP INDEX IF EXISTS `IX_OzonChatOrders_ChatId`;"); |
| | 0 | 114 | | migrationBuilder.Sql("ALTER TABLE `Orders` DROP INDEX IF EXISTS `IX_Orders_EtProducerId`;"); |
| | 0 | 115 | | migrationBuilder.Sql("ALTER TABLE `OrderShipmentTotals` DROP INDEX IF EXISTS `IX_OrderShipmentTotals_OrderId |
| | 0 | 116 | | migrationBuilder.Sql("ALTER TABLE `OrderItems` DROP INDEX IF EXISTS `IX_OrderItems_StudioOrderId`;"); |
| | 0 | 117 | | migrationBuilder.Sql("ALTER TABLE `BitrixStockAutoSchedules` DROP INDEX IF EXISTS `IX_BitrixStockAutoSchedul |
| | | 118 | | |
| | 0 | 119 | | migrationBuilder.Sql("ALTER TABLE `order_extensions` MODIFY COLUMN `Id` int unsigned NOT NULL AUTO_INCREMENT |
| | 0 | 120 | | migrationBuilder.Sql("ALTER TABLE `StatusTransitionHistory` MODIFY COLUMN `Id` bigint unsigned NOT NULL AUTO |
| | 0 | 121 | | migrationBuilder.Sql("ALTER TABLE `StatusTransitionHistory` MODIFY COLUMN `PerformedAt` timestamp NULL DEFAU |
| | 0 | 122 | | migrationBuilder.Sql("ALTER TABLE `StatusTransitions` MODIFY COLUMN `UpdatedAt` timestamp NULL DEFAULT NULL |
| | 0 | 123 | | migrationBuilder.Sql("ALTER TABLE `StatusTransitions` MODIFY COLUMN `CreatedAt` timestamp NULL DEFAULT curre |
| | 0 | 124 | | migrationBuilder.Sql("ALTER TABLE `StatusTransitions` MODIFY COLUMN `IsRepeatable` tinyint(1) NULL DEFAULT 0 |
| | 0 | 125 | | migrationBuilder.Sql("ALTER TABLE `StatusTransitions` MODIFY COLUMN `IsActive` tinyint(1) NULL DEFAULT 1;"); |
| | | 126 | | |
| | 0 | 127 | | migrationBuilder.Sql("ALTER TABLE `PriceHistories` MODIFY COLUMN `RegistrationPrice` decimal(18,2) NULL;"); |
| | 0 | 128 | | migrationBuilder.Sql("ALTER TABLE `FileUploadRecords` MODIFY COLUMN `Result` text CHARACTER SET utf8mb4 NULL |
| | 0 | 129 | | migrationBuilder.Sql("ALTER TABLE `ExcelMappings` MODIFY COLUMN `CreatedBy` varchar(255) CHARACTER SET utf8m |
| | 0 | 130 | | } |
| | | 131 | | } |
| | | 132 | | } |