using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using foodmarket.Infrastructure.Persistence; #nullable disable namespace foodmarket.Infrastructure.Persistence.Migrations { /// Phase39 — предупреждения об отрицательных остатках /// (negative_stock_alerts). Создаётся/обновляется автоматически при уходе /// остатка в минус, закрывается при возврате ≥ 0. Частичный уникальный индекс /// гарантирует максимум один ОТКРЫТЫЙ алерт на (org, store, product). Идемпотентно. [DbContext(typeof(AppDbContext))] [Migration("20261009010000_Phase39_NegativeStockAlerts")] public partial class Phase39_NegativeStockAlerts : Migration { protected override void Up(MigrationBuilder b) { b.Sql(@" CREATE TABLE IF NOT EXISTS public.negative_stock_alerts ( ""Id"" uuid PRIMARY KEY, ""OrganizationId"" uuid NOT NULL, ""StoreId"" uuid NOT NULL, ""ProductId"" uuid NOT NULL, ""Quantity"" numeric(18,4) NOT NULL, ""CauseDocType"" varchar(50), ""CauseDocId"" uuid, ""CauseDocNumber"" varchar(50), ""CauseUserId"" uuid, ""CauseAt"" timestamp with time zone, ""FirstDetectedAt"" timestamp with time zone NOT NULL, ""LastUpdatedAt"" timestamp with time zone NOT NULL, ""ResolvedAt"" timestamp with time zone, ""NotifiedAt"" timestamp with time zone, ""EscalatedAt"" timestamp with time zone, ""CreatedAt"" timestamp with time zone NOT NULL, ""UpdatedAt"" timestamp with time zone, CONSTRAINT ""FK_negative_stock_alerts_stores_StoreId"" FOREIGN KEY (""StoreId"") REFERENCES public.stores(""Id"") ON DELETE CASCADE, CONSTRAINT ""FK_negative_stock_alerts_products_ProductId"" FOREIGN KEY (""ProductId"") REFERENCES public.products(""Id"") ON DELETE CASCADE ); CREATE INDEX IF NOT EXISTS ""IX_negative_stock_alerts_OrganizationId_ResolvedAt"" ON public.negative_stock_alerts (""OrganizationId"", ""ResolvedAt""); CREATE INDEX IF NOT EXISTS ""IX_negative_stock_alerts_OrganizationId_StoreId_ProductId"" ON public.negative_stock_alerts (""OrganizationId"", ""StoreId"", ""ProductId""); -- Максимум один ОТКРЫТЫЙ алерт на (org, store, product). CREATE UNIQUE INDEX IF NOT EXISTS ""UX_negative_stock_alerts_open"" ON public.negative_stock_alerts (""OrganizationId"", ""StoreId"", ""ProductId"") WHERE ""ResolvedAt"" IS NULL; "); } protected override void Down(MigrationBuilder b) { b.Sql(@"DROP TABLE IF EXISTS public.negative_stock_alerts;"); } } }