diff --git a/Distribution/Migrations/20260916083241_AddOrderInvoiceLifecycle.cs b/Distribution/Migrations/20260916083241_AddOrderInvoiceLifecycle.cs
new file mode 100644
index 0000000..bee5750
--- /dev/null
+++ b/Distribution/Migrations/20260916083241_AddOrderInvoiceLifecycle.cs
@@ -0,0 +1,306 @@
+using System;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
+
+namespace Distribution.Migrations
+{
+ ///
+ public partial class AddOrderInvoiceLifecycle : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ // Must run before DropPrimaryKey below: OrderItems.FK_OrderId has a foreign key to
+ // Orders, and MySQL requires a supporting index on that column at all times. The old
+ // composite PK (FK_OrderId, FK_ItemId) was providing that support; without this index
+ // created first, dropping the PK leaves FK_OrderId's constraint without an index and
+ // MySQL rejects the DROP PRIMARY KEY (errno 150).
+ migrationBuilder.CreateIndex(
+ name: "IX_OrderItems_FK_OrderId",
+ table: "OrderItems",
+ column: "FK_OrderId");
+
+ migrationBuilder.DropPrimaryKey(
+ name: "PK_OrderItems",
+ table: "OrderItems");
+
+ migrationBuilder.DeleteData(
+ table: "OrderItems",
+ keyColumns: new[] { "FK_ItemId", "FK_OrderId" },
+ keyValues: new object[] { new Guid("23000000-0000-0000-0000-000000000001"), new Guid("33000000-0000-0000-0000-000000000001") });
+
+ migrationBuilder.DeleteData(
+ table: "OrderItems",
+ keyColumns: new[] { "FK_ItemId", "FK_OrderId" },
+ keyValues: new object[] { new Guid("23000000-0000-0000-0000-000000000003"), new Guid("33000000-0000-0000-0000-000000000001") });
+
+ migrationBuilder.DeleteData(
+ table: "OrderItems",
+ keyColumns: new[] { "FK_ItemId", "FK_OrderId" },
+ keyValues: new object[] { new Guid("23000000-0000-0000-0000-000000000002"), new Guid("33000000-0000-0000-0000-000000000002") });
+
+ migrationBuilder.AlterColumn(
+ name: "FK_SaleId",
+ table: "Orders",
+ type: "char(36)",
+ nullable: true,
+ collation: "ascii_general_ci",
+ oldClrType: typeof(Guid),
+ oldType: "char(36)")
+ .OldAnnotation("Relational:Collation", "ascii_general_ci");
+
+ migrationBuilder.AddColumn(
+ name: "ConfirmedAt",
+ table: "Orders",
+ type: "datetime(6)",
+ nullable: true);
+
+ migrationBuilder.AddColumn(
+ name: "ConfirmedByUserId",
+ table: "Orders",
+ type: "char(36)",
+ nullable: true,
+ collation: "ascii_general_ci");
+
+ migrationBuilder.AddColumn(
+ name: "CreatedByUserId",
+ table: "Orders",
+ type: "char(36)",
+ nullable: false,
+ defaultValue: new Guid("00000000-0000-0000-0000-000000000000"),
+ collation: "ascii_general_ci");
+
+ // Backfill every existing Order's new CreatedByUserId from its linked Sale (Order.FK_SaleId
+ // was required until this migration, so every pre-existing row has one). Covers every
+ // row generically, not just the two rows seeded via HasData below — otherwise any Order
+ // created outside the EF seed data would keep the temporary AddColumn default
+ // (Guid.Empty) and fail the FK_Orders_Users_CreatedByUserId constraint added at the end
+ // of this migration.
+ migrationBuilder.Sql(@"
+ UPDATE `Orders` o
+ INNER JOIN `Sales` s ON s.`Id` = o.`FK_SaleId`
+ SET o.`CreatedByUserId` = s.`CreatedByUserId`
+ WHERE o.`FK_SaleId` IS NOT NULL;");
+
+ migrationBuilder.AddColumn(
+ name: "InvoiceId",
+ table: "Orders",
+ type: "char(36)",
+ nullable: true,
+ collation: "ascii_general_ci");
+
+ migrationBuilder.AddPrimaryKey(
+ name: "PK_OrderItems",
+ table: "OrderItems",
+ column: "Id");
+
+ migrationBuilder.CreateTable(
+ name: "Invoices",
+ columns: table => new
+ {
+ Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+ FK_OrderId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+ Status = table.Column(type: "int", nullable: false),
+ CreatedByUserId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+ PrintedAt = table.Column(type: "datetime(6)", nullable: true),
+ PrintedByUserId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
+ FinalizedAt = table.Column(type: "datetime(6)", nullable: true),
+ FinalizedByUserId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
+ TotalAmount = table.Column(type: "decimal(65,30)", nullable: false),
+ CreatedAt = table.Column(type: "datetime(6)", nullable: false),
+ IsActive = table.Column(type: "tinyint(1)", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Invoices", x => x.Id);
+ table.ForeignKey(
+ name: "FK_Invoices_Orders_FK_OrderId",
+ column: x => x.FK_OrderId,
+ principalTable: "Orders",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Restrict);
+ table.ForeignKey(
+ name: "FK_Invoices_Users_CreatedByUserId",
+ column: x => x.CreatedByUserId,
+ principalTable: "Users",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Restrict);
+ table.ForeignKey(
+ name: "FK_Invoices_Users_FinalizedByUserId",
+ column: x => x.FinalizedByUserId,
+ principalTable: "Users",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Restrict);
+ table.ForeignKey(
+ name: "FK_Invoices_Users_PrintedByUserId",
+ column: x => x.PrintedByUserId,
+ principalTable: "Users",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Restrict);
+ })
+ .Annotation("MySql:CharSet", "utf8mb4");
+
+ migrationBuilder.InsertData(
+ table: "OrderItems",
+ columns: new[] { "Id", "CreatedAt", "FK_ItemId", "FK_OrderId", "IsActive", "Quantity", "QuantityFulfilled", "UnitPrice" },
+ values: new object[,]
+ {
+ { new Guid("34000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), new Guid("23000000-0000-0000-0000-000000000001"), new Guid("33000000-0000-0000-0000-000000000001"), true, 30, 30, 60m },
+ { new Guid("34000000-0000-0000-0000-000000000002"), new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), new Guid("23000000-0000-0000-0000-000000000003"), new Guid("33000000-0000-0000-0000-000000000001"), true, 24, 24, 50m },
+ { new Guid("34000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), new Guid("23000000-0000-0000-0000-000000000002"), new Guid("33000000-0000-0000-0000-000000000002"), true, 10, 0, 120m }
+ });
+
+ migrationBuilder.UpdateData(
+ table: "Orders",
+ keyColumn: "Id",
+ keyValue: new Guid("33000000-0000-0000-0000-000000000001"),
+ columns: new[] { "ConfirmedAt", "ConfirmedByUserId", "CreatedByUserId", "InvoiceId" },
+ values: new object[] { null, null, new Guid("29000000-0000-0000-0000-000000000002"), null });
+
+ migrationBuilder.UpdateData(
+ table: "Orders",
+ keyColumn: "Id",
+ keyValue: new Guid("33000000-0000-0000-0000-000000000002"),
+ columns: new[] { "ConfirmedAt", "ConfirmedByUserId", "CreatedByUserId", "InvoiceId" },
+ values: new object[] { null, null, new Guid("29000000-0000-0000-0000-000000000003"), null });
+
+ migrationBuilder.CreateIndex(
+ name: "IX_Orders_ConfirmedByUserId",
+ table: "Orders",
+ column: "ConfirmedByUserId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_Orders_CreatedByUserId",
+ table: "Orders",
+ column: "CreatedByUserId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_Invoices_CreatedByUserId",
+ table: "Invoices",
+ column: "CreatedByUserId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_Invoices_FinalizedByUserId",
+ table: "Invoices",
+ column: "FinalizedByUserId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_Invoices_FK_OrderId",
+ table: "Invoices",
+ column: "FK_OrderId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_Invoices_PrintedByUserId",
+ table: "Invoices",
+ column: "PrintedByUserId");
+
+ migrationBuilder.AddForeignKey(
+ name: "FK_Orders_Users_ConfirmedByUserId",
+ table: "Orders",
+ column: "ConfirmedByUserId",
+ principalTable: "Users",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Restrict);
+
+ migrationBuilder.AddForeignKey(
+ name: "FK_Orders_Users_CreatedByUserId",
+ table: "Orders",
+ column: "CreatedByUserId",
+ principalTable: "Users",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Restrict);
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropForeignKey(
+ name: "FK_Orders_Users_ConfirmedByUserId",
+ table: "Orders");
+
+ migrationBuilder.DropForeignKey(
+ name: "FK_Orders_Users_CreatedByUserId",
+ table: "Orders");
+
+ migrationBuilder.DropTable(
+ name: "Invoices");
+
+ migrationBuilder.DropIndex(
+ name: "IX_Orders_ConfirmedByUserId",
+ table: "Orders");
+
+ migrationBuilder.DropIndex(
+ name: "IX_Orders_CreatedByUserId",
+ table: "Orders");
+
+ migrationBuilder.DropPrimaryKey(
+ name: "PK_OrderItems",
+ table: "OrderItems");
+
+ migrationBuilder.DropIndex(
+ name: "IX_OrderItems_FK_OrderId",
+ table: "OrderItems");
+
+ migrationBuilder.DeleteData(
+ table: "OrderItems",
+ keyColumn: "Id",
+ keyValue: new Guid("34000000-0000-0000-0000-000000000001"));
+
+ migrationBuilder.DeleteData(
+ table: "OrderItems",
+ keyColumn: "Id",
+ keyValue: new Guid("34000000-0000-0000-0000-000000000002"));
+
+ migrationBuilder.DeleteData(
+ table: "OrderItems",
+ keyColumn: "Id",
+ keyValue: new Guid("34000000-0000-0000-0000-000000000003"));
+
+ migrationBuilder.DropColumn(
+ name: "ConfirmedAt",
+ table: "Orders");
+
+ migrationBuilder.DropColumn(
+ name: "ConfirmedByUserId",
+ table: "Orders");
+
+ migrationBuilder.DropColumn(
+ name: "CreatedByUserId",
+ table: "Orders");
+
+ migrationBuilder.DropColumn(
+ name: "InvoiceId",
+ table: "Orders");
+
+ migrationBuilder.AlterColumn(
+ name: "FK_SaleId",
+ table: "Orders",
+ type: "char(36)",
+ nullable: false,
+ defaultValue: new Guid("00000000-0000-0000-0000-000000000000"),
+ collation: "ascii_general_ci",
+ oldClrType: typeof(Guid),
+ oldType: "char(36)",
+ oldNullable: true)
+ .OldAnnotation("Relational:Collation", "ascii_general_ci");
+
+ migrationBuilder.AddPrimaryKey(
+ name: "PK_OrderItems",
+ table: "OrderItems",
+ columns: new[] { "FK_OrderId", "FK_ItemId" });
+
+ migrationBuilder.InsertData(
+ table: "OrderItems",
+ columns: new[] { "FK_ItemId", "FK_OrderId", "CreatedAt", "Id", "IsActive", "Quantity", "QuantityFulfilled", "UnitPrice" },
+ values: new object[,]
+ {
+ { new Guid("23000000-0000-0000-0000-000000000001"), new Guid("33000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), new Guid("34000000-0000-0000-0000-000000000001"), true, 30, 30, 60m },
+ { new Guid("23000000-0000-0000-0000-000000000003"), new Guid("33000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), new Guid("34000000-0000-0000-0000-000000000002"), true, 24, 24, 50m },
+ { new Guid("23000000-0000-0000-0000-000000000002"), new Guid("33000000-0000-0000-0000-000000000002"), new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), new Guid("34000000-0000-0000-0000-000000000003"), true, 10, 0, 120m }
+ });
+ }
+ }
+}