price adjustment and stock adjustments

This commit is contained in:
2026-10-12 14:08:23 +05:30
committed by ImanThiyanga
parent a788349138
commit d0354ed169
166 changed files with 98818 additions and 252 deletions
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,336 @@
using System;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
namespace ERPCore.Migrations
{
/// <inheritdoc />
public partial class AddExpenseModule : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "expense_categories",
columns: table => new
{
ExpenseCategoryId = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Code = table.Column<string>(type: "varchar(30)", maxLength: 30, nullable: false, collation: "utf8mb4_unicode_ci"),
Name = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: false, collation: "utf8mb4_unicode_ci"),
IsSystem = table.Column<bool>(type: "tinyint(1)", nullable: false),
Status = table.Column<string>(type: "varchar(20)", maxLength: 20, nullable: false, defaultValue: "Active", collation: "utf8mb4_unicode_ci"),
SortOrder = table.Column<int>(type: "int", nullable: false),
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: true),
RowVersion = table.Column<uint>(type: "int unsigned", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_expense_categories", x => x.ExpenseCategoryId);
})
.Annotation("Relational:Collation", "utf8mb4_unicode_ci");
migrationBuilder.CreateTable(
name: "expense_titles",
columns: table => new
{
ExpenseTitleId = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
ExpenseCategoryId = table.Column<int>(type: "int", nullable: false),
Name = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: false, collation: "utf8mb4_unicode_ci"),
GlExpenseAccountCode = table.Column<string>(type: "varchar(20)", maxLength: 20, nullable: false, collation: "utf8mb4_unicode_ci"),
IsSystem = table.Column<bool>(type: "tinyint(1)", nullable: false),
Status = table.Column<string>(type: "varchar(20)", maxLength: 20, nullable: false, defaultValue: "Active", collation: "utf8mb4_unicode_ci"),
SortOrder = table.Column<int>(type: "int", nullable: false),
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: true),
RowVersion = table.Column<uint>(type: "int unsigned", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_expense_titles", x => x.ExpenseTitleId);
table.ForeignKey(
name: "FK_expense_titles_expense_categories_ExpenseCategoryId",
column: x => x.ExpenseCategoryId,
principalTable: "expense_categories",
principalColumn: "ExpenseCategoryId",
onDelete: ReferentialAction.Restrict);
})
.Annotation("Relational:Collation", "utf8mb4_unicode_ci");
migrationBuilder.CreateTable(
name: "expenses",
columns: table => new
{
ExpenseId = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
DocNo = table.Column<string>(type: "varchar(30)", maxLength: 30, nullable: false, collation: "utf8mb4_unicode_ci"),
BranchId = table.Column<int>(type: "int", nullable: false),
ExpenseDate = table.Column<DateOnly>(type: "date", nullable: false),
DueDate = table.Column<DateOnly>(type: "date", nullable: true),
ExpenseCategoryId = table.Column<int>(type: "int", nullable: false),
ExpenseTitleId = table.Column<int>(type: "int", nullable: false),
Payee = table.Column<string>(type: "varchar(150)", maxLength: 150, nullable: true, collation: "utf8mb4_unicode_ci"),
VendorId = table.Column<int>(type: "int", nullable: true),
BillReference = table.Column<string>(type: "varchar(50)", maxLength: 50, nullable: true, collation: "utf8mb4_unicode_ci"),
Description = table.Column<string>(type: "varchar(500)", maxLength: 500, nullable: true, collation: "utf8mb4_unicode_ci"),
PeriodMonth = table.Column<string>(type: "varchar(7)", maxLength: 7, nullable: true, collation: "utf8mb4_unicode_ci"),
Amount = table.Column<decimal>(type: "decimal(18,4)", precision: 18, scale: 4, nullable: false),
PaidAmount = table.Column<decimal>(type: "decimal(18,4)", precision: 18, scale: 4, nullable: false),
BalanceAmount = table.Column<decimal>(type: "decimal(18,4)", precision: 18, scale: 4, nullable: false),
Status = table.Column<string>(type: "varchar(20)", maxLength: 20, nullable: false, defaultValue: "Draft", collation: "utf8mb4_unicode_ci"),
PaymentStatus = table.Column<string>(type: "varchar(20)", maxLength: 20, nullable: false, defaultValue: "Unpaid", collation: "utf8mb4_unicode_ci"),
GlExpenseAccountCode = table.Column<string>(type: "varchar(20)", maxLength: 20, nullable: true, collation: "utf8mb4_unicode_ci"),
GlJournalNo = table.Column<string>(type: "varchar(30)", maxLength: 30, nullable: true, collation: "utf8mb4_unicode_ci"),
GlPostedAt = table.Column<DateTime>(type: "datetime(6)", nullable: true),
GlReversalJournalNo = table.Column<string>(type: "varchar(30)", maxLength: 30, nullable: true, collation: "utf8mb4_unicode_ci"),
CancelReason = table.Column<string>(type: "varchar(250)", maxLength: 250, nullable: true, collation: "utf8mb4_unicode_ci"),
CreatedBy = table.Column<int>(type: "int", nullable: false),
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: true),
RowVersion = table.Column<uint>(type: "int unsigned", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_expenses", x => x.ExpenseId);
table.CheckConstraint("ck_expenses_amount", "`Amount` > 0");
table.ForeignKey(
name: "FK_expenses_expense_categories_ExpenseCategoryId",
column: x => x.ExpenseCategoryId,
principalTable: "expense_categories",
principalColumn: "ExpenseCategoryId",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_expenses_expense_titles_ExpenseTitleId",
column: x => x.ExpenseTitleId,
principalTable: "expense_titles",
principalColumn: "ExpenseTitleId",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_expenses_hr_branches_BranchId",
column: x => x.BranchId,
principalTable: "hr_branches",
principalColumn: "BranchId",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_expenses_users_CreatedBy",
column: x => x.CreatedBy,
principalTable: "users",
principalColumn: "UserId",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_expenses_vendors_VendorId",
column: x => x.VendorId,
principalTable: "vendors",
principalColumn: "VendorId",
onDelete: ReferentialAction.Restrict);
})
.Annotation("Relational:Collation", "utf8mb4_unicode_ci");
migrationBuilder.CreateTable(
name: "expense_payments",
columns: table => new
{
ExpensePaymentId = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
ExpenseId = table.Column<int>(type: "int", nullable: false),
Amount = table.Column<decimal>(type: "decimal(18,4)", precision: 18, scale: 4, nullable: false),
PaymentDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
PaymentMethod = table.Column<string>(type: "varchar(20)", maxLength: 20, nullable: false, collation: "utf8mb4_unicode_ci"),
GlBankAccountId = table.Column<long>(type: "bigint", nullable: false),
BankAccountName = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: false, collation: "utf8mb4_unicode_ci"),
ChequeNo = table.Column<string>(type: "varchar(30)", maxLength: 30, nullable: true, collation: "utf8mb4_unicode_ci"),
Reference = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: true, collation: "utf8mb4_unicode_ci"),
GlJournalNo = table.Column<string>(type: "varchar(30)", maxLength: 30, nullable: true, collation: "utf8mb4_unicode_ci"),
CreatedBy = table.Column<int>(type: "int", nullable: false),
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_expense_payments", x => x.ExpensePaymentId);
table.ForeignKey(
name: "FK_expense_payments_expenses_ExpenseId",
column: x => x.ExpenseId,
principalTable: "expenses",
principalColumn: "ExpenseId",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_expense_payments_users_CreatedBy",
column: x => x.CreatedBy,
principalTable: "users",
principalColumn: "UserId",
onDelete: ReferentialAction.Restrict);
})
.Annotation("Relational:Collation", "utf8mb4_unicode_ci");
migrationBuilder.InsertData(
table: "expense_categories",
columns: new[] { "ExpenseCategoryId", "Code", "CreatedAt", "IsSystem", "Name", "RowVersion", "SortOrder", "UpdatedAt" },
values: new object[,]
{
{ 1, "UTILITY", new DateTime(2026, 10, 7, 0, 0, 0, 0, DateTimeKind.Utc), true, "Utility", 1u, 1, null },
{ 2, "RENTAL", new DateTime(2026, 10, 7, 0, 0, 0, 0, DateTimeKind.Utc), true, "Rental", 1u, 2, null },
{ 3, "SALARIES", new DateTime(2026, 10, 7, 0, 0, 0, 0, DateTimeKind.Utc), true, "Salaries", 1u, 3, null },
{ 4, "OTHER", new DateTime(2026, 10, 7, 0, 0, 0, 0, DateTimeKind.Utc), true, "Other", 1u, 4, null }
});
migrationBuilder.InsertData(
table: "sub_nav_items",
columns: new[] { "SubNavItemId", "Code", "Href", "Icon", "Label", "NavItemId", "SortOrder" },
values: new object[,]
{
{ 44, "accounts.expenses", "/dashboard/accounts/expenses", null, "Expenses", 12, 4 },
{ 45, "accounts.expense-setup", "/dashboard/accounts/expense-setup", null, "Expense Setup", 12, 5 }
});
migrationBuilder.InsertData(
table: "expense_titles",
columns: new[] { "ExpenseTitleId", "CreatedAt", "ExpenseCategoryId", "GlExpenseAccountCode", "IsSystem", "Name", "RowVersion", "SortOrder", "UpdatedAt" },
values: new object[,]
{
{ 1, new DateTime(2026, 10, 7, 0, 0, 0, 0, DateTimeKind.Utc), 1, "6100", true, "Electricity", 1u, 1, null },
{ 2, new DateTime(2026, 10, 7, 0, 0, 0, 0, DateTimeKind.Utc), 1, "6100", true, "Water", 1u, 2, null },
{ 3, new DateTime(2026, 10, 7, 0, 0, 0, 0, DateTimeKind.Utc), 1, "6100", true, "Telephone", 1u, 3, null },
{ 4, new DateTime(2026, 10, 7, 0, 0, 0, 0, DateTimeKind.Utc), 1, "6100", true, "Internet", 1u, 4, null },
{ 5, new DateTime(2026, 10, 7, 0, 0, 0, 0, DateTimeKind.Utc), 1, "6100", true, "Gas", 1u, 5, null },
{ 6, new DateTime(2026, 10, 7, 0, 0, 0, 0, DateTimeKind.Utc), 2, "6200", true, "Building Rent", 1u, 1, null },
{ 7, new DateTime(2026, 10, 7, 0, 0, 0, 0, DateTimeKind.Utc), 2, "6200", true, "Vehicle Rent", 1u, 2, null },
{ 8, new DateTime(2026, 10, 7, 0, 0, 0, 0, DateTimeKind.Utc), 2, "6200", true, "Equipment Rent", 1u, 3, null },
{ 9, new DateTime(2026, 10, 7, 0, 0, 0, 0, DateTimeKind.Utc), 3, "6300", true, "Staff Salaries", 1u, 1, null },
{ 10, new DateTime(2026, 10, 7, 0, 0, 0, 0, DateTimeKind.Utc), 3, "6300", true, "Wages", 1u, 2, null },
{ 11, new DateTime(2026, 10, 7, 0, 0, 0, 0, DateTimeKind.Utc), 3, "6300", true, "Overtime", 1u, 3, null },
{ 12, new DateTime(2026, 10, 7, 0, 0, 0, 0, DateTimeKind.Utc), 3, "6300", true, "Bonus", 1u, 4, null },
{ 13, new DateTime(2026, 10, 7, 0, 0, 0, 0, DateTimeKind.Utc), 3, "6300", true, "EPF / ETF Contribution", 1u, 5, null },
{ 14, new DateTime(2026, 10, 7, 0, 0, 0, 0, DateTimeKind.Utc), 4, "6900", true, "Stationery", 1u, 1, null },
{ 15, new DateTime(2026, 10, 7, 0, 0, 0, 0, DateTimeKind.Utc), 4, "6900", true, "Transport", 1u, 2, null },
{ 16, new DateTime(2026, 10, 7, 0, 0, 0, 0, DateTimeKind.Utc), 4, "6900", true, "Repairs & Maintenance", 1u, 3, null },
{ 17, new DateTime(2026, 10, 7, 0, 0, 0, 0, DateTimeKind.Utc), 4, "6900", true, "Cleaning", 1u, 4, null },
{ 18, new DateTime(2026, 10, 7, 0, 0, 0, 0, DateTimeKind.Utc), 4, "6900", true, "Miscellaneous", 1u, 5, null }
});
migrationBuilder.InsertData(
table: "permissions",
columns: new[] { "PermissionId", "Code", "NavItemId", "SubNavItemId" },
values: new object[,]
{
{ 54, "NAV:accounts.expenses", null, 44 },
{ 55, "NAV:accounts.expense-setup", null, 45 }
});
migrationBuilder.CreateIndex(
name: "IX_expense_categories_Code",
table: "expense_categories",
column: "Code",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_expense_categories_Name",
table: "expense_categories",
column: "Name",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_expense_payments_CreatedBy",
table: "expense_payments",
column: "CreatedBy");
migrationBuilder.CreateIndex(
name: "IX_expense_payments_ExpenseId",
table: "expense_payments",
column: "ExpenseId");
migrationBuilder.CreateIndex(
name: "IX_expense_titles_ExpenseCategoryId_Name",
table: "expense_titles",
columns: new[] { "ExpenseCategoryId", "Name" },
unique: true);
migrationBuilder.CreateIndex(
name: "IX_expenses_BranchId",
table: "expenses",
column: "BranchId");
migrationBuilder.CreateIndex(
name: "IX_expenses_CreatedBy",
table: "expenses",
column: "CreatedBy");
migrationBuilder.CreateIndex(
name: "IX_expenses_DocNo",
table: "expenses",
column: "DocNo",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_expenses_ExpenseCategoryId",
table: "expenses",
column: "ExpenseCategoryId");
migrationBuilder.CreateIndex(
name: "IX_expenses_ExpenseDate",
table: "expenses",
column: "ExpenseDate");
migrationBuilder.CreateIndex(
name: "IX_expenses_ExpenseTitleId",
table: "expenses",
column: "ExpenseTitleId");
migrationBuilder.CreateIndex(
name: "IX_expenses_PaymentStatus",
table: "expenses",
column: "PaymentStatus");
migrationBuilder.CreateIndex(
name: "IX_expenses_Status",
table: "expenses",
column: "Status");
migrationBuilder.CreateIndex(
name: "IX_expenses_VendorId",
table: "expenses",
column: "VendorId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "expense_payments");
migrationBuilder.DropTable(
name: "expenses");
migrationBuilder.DropTable(
name: "expense_titles");
migrationBuilder.DropTable(
name: "expense_categories");
migrationBuilder.DeleteData(
table: "permissions",
keyColumn: "PermissionId",
keyValue: 54);
migrationBuilder.DeleteData(
table: "permissions",
keyColumn: "PermissionId",
keyValue: 55);
migrationBuilder.DeleteData(
table: "sub_nav_items",
keyColumn: "SubNavItemId",
keyValue: 44);
migrationBuilder.DeleteData(
table: "sub_nav_items",
keyColumn: "SubNavItemId",
keyValue: 45);
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,37 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ERPCore.Migrations
{
/// <summary>
/// Data-only: grants the two new Accounts sub-items (NAV:accounts.expenses = 54,
/// NAV:accounts.expense-setup = 55, added by AddExpenseModule) to the Admin role and to every
/// role that already reaches Accounts (NAV:accounts 32, bank-accounts 26, cheque-books 33,
/// received-cheques 34). Without this no role — Admin included — has the codes in
/// /auth/me's navCodes, so the sidebar hides the screens. Admins can still revoke them per
/// role afterwards. INSERT IGNORE keeps it idempotent against grants made by hand.
/// </summary>
public partial class GrantExpensePermissions : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql("""
INSERT IGNORE INTO `role_permissions` (`RoleId`, `PermissionId`, `Actions`)
SELECT r.`RoleId`, p.`PermissionId`, 31
FROM `roles` r
CROSS JOIN (SELECT 54 AS `PermissionId` UNION ALL SELECT 55) p
WHERE LOWER(r.`Code`) = 'admin'
OR EXISTS (SELECT 1 FROM `role_permissions` rp
WHERE rp.`RoleId` = r.`RoleId` AND rp.`PermissionId` IN (26, 32, 33, 34));
""");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql("DELETE FROM `role_permissions` WHERE `PermissionId` IN (54, 55);");
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,270 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ERPCore.Migrations
{
/// <inheritdoc />
public partial class UpdateExpenseGlCodes : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.UpdateData(
table: "expense_titles",
keyColumn: "ExpenseTitleId",
keyValue: 1,
column: "GlExpenseAccountCode",
value: "5200-01");
migrationBuilder.UpdateData(
table: "expense_titles",
keyColumn: "ExpenseTitleId",
keyValue: 2,
column: "GlExpenseAccountCode",
value: "5200-01");
migrationBuilder.UpdateData(
table: "expense_titles",
keyColumn: "ExpenseTitleId",
keyValue: 3,
column: "GlExpenseAccountCode",
value: "5200-01");
migrationBuilder.UpdateData(
table: "expense_titles",
keyColumn: "ExpenseTitleId",
keyValue: 4,
column: "GlExpenseAccountCode",
value: "5200-01");
migrationBuilder.UpdateData(
table: "expense_titles",
keyColumn: "ExpenseTitleId",
keyValue: 5,
column: "GlExpenseAccountCode",
value: "5200-01");
migrationBuilder.UpdateData(
table: "expense_titles",
keyColumn: "ExpenseTitleId",
keyValue: 6,
column: "GlExpenseAccountCode",
value: "5200-02");
migrationBuilder.UpdateData(
table: "expense_titles",
keyColumn: "ExpenseTitleId",
keyValue: 7,
column: "GlExpenseAccountCode",
value: "5200-02");
migrationBuilder.UpdateData(
table: "expense_titles",
keyColumn: "ExpenseTitleId",
keyValue: 8,
column: "GlExpenseAccountCode",
value: "5200-02");
migrationBuilder.UpdateData(
table: "expense_titles",
keyColumn: "ExpenseTitleId",
keyValue: 9,
column: "GlExpenseAccountCode",
value: "5200-03");
migrationBuilder.UpdateData(
table: "expense_titles",
keyColumn: "ExpenseTitleId",
keyValue: 10,
column: "GlExpenseAccountCode",
value: "5200-03");
migrationBuilder.UpdateData(
table: "expense_titles",
keyColumn: "ExpenseTitleId",
keyValue: 11,
column: "GlExpenseAccountCode",
value: "5200-03");
migrationBuilder.UpdateData(
table: "expense_titles",
keyColumn: "ExpenseTitleId",
keyValue: 12,
column: "GlExpenseAccountCode",
value: "5200-03");
migrationBuilder.UpdateData(
table: "expense_titles",
keyColumn: "ExpenseTitleId",
keyValue: 13,
column: "GlExpenseAccountCode",
value: "5200-03");
migrationBuilder.UpdateData(
table: "expense_titles",
keyColumn: "ExpenseTitleId",
keyValue: 14,
column: "GlExpenseAccountCode",
value: "5200-04");
migrationBuilder.UpdateData(
table: "expense_titles",
keyColumn: "ExpenseTitleId",
keyValue: 15,
column: "GlExpenseAccountCode",
value: "5200-04");
migrationBuilder.UpdateData(
table: "expense_titles",
keyColumn: "ExpenseTitleId",
keyValue: 16,
column: "GlExpenseAccountCode",
value: "5200-04");
migrationBuilder.UpdateData(
table: "expense_titles",
keyColumn: "ExpenseTitleId",
keyValue: 17,
column: "GlExpenseAccountCode",
value: "5200-04");
migrationBuilder.UpdateData(
table: "expense_titles",
keyColumn: "ExpenseTitleId",
keyValue: 18,
column: "GlExpenseAccountCode",
value: "5200-04");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.UpdateData(
table: "expense_titles",
keyColumn: "ExpenseTitleId",
keyValue: 1,
column: "GlExpenseAccountCode",
value: "6100");
migrationBuilder.UpdateData(
table: "expense_titles",
keyColumn: "ExpenseTitleId",
keyValue: 2,
column: "GlExpenseAccountCode",
value: "6100");
migrationBuilder.UpdateData(
table: "expense_titles",
keyColumn: "ExpenseTitleId",
keyValue: 3,
column: "GlExpenseAccountCode",
value: "6100");
migrationBuilder.UpdateData(
table: "expense_titles",
keyColumn: "ExpenseTitleId",
keyValue: 4,
column: "GlExpenseAccountCode",
value: "6100");
migrationBuilder.UpdateData(
table: "expense_titles",
keyColumn: "ExpenseTitleId",
keyValue: 5,
column: "GlExpenseAccountCode",
value: "6100");
migrationBuilder.UpdateData(
table: "expense_titles",
keyColumn: "ExpenseTitleId",
keyValue: 6,
column: "GlExpenseAccountCode",
value: "6200");
migrationBuilder.UpdateData(
table: "expense_titles",
keyColumn: "ExpenseTitleId",
keyValue: 7,
column: "GlExpenseAccountCode",
value: "6200");
migrationBuilder.UpdateData(
table: "expense_titles",
keyColumn: "ExpenseTitleId",
keyValue: 8,
column: "GlExpenseAccountCode",
value: "6200");
migrationBuilder.UpdateData(
table: "expense_titles",
keyColumn: "ExpenseTitleId",
keyValue: 9,
column: "GlExpenseAccountCode",
value: "6300");
migrationBuilder.UpdateData(
table: "expense_titles",
keyColumn: "ExpenseTitleId",
keyValue: 10,
column: "GlExpenseAccountCode",
value: "6300");
migrationBuilder.UpdateData(
table: "expense_titles",
keyColumn: "ExpenseTitleId",
keyValue: 11,
column: "GlExpenseAccountCode",
value: "6300");
migrationBuilder.UpdateData(
table: "expense_titles",
keyColumn: "ExpenseTitleId",
keyValue: 12,
column: "GlExpenseAccountCode",
value: "6300");
migrationBuilder.UpdateData(
table: "expense_titles",
keyColumn: "ExpenseTitleId",
keyValue: 13,
column: "GlExpenseAccountCode",
value: "6300");
migrationBuilder.UpdateData(
table: "expense_titles",
keyColumn: "ExpenseTitleId",
keyValue: 14,
column: "GlExpenseAccountCode",
value: "6900");
migrationBuilder.UpdateData(
table: "expense_titles",
keyColumn: "ExpenseTitleId",
keyValue: 15,
column: "GlExpenseAccountCode",
value: "6900");
migrationBuilder.UpdateData(
table: "expense_titles",
keyColumn: "ExpenseTitleId",
keyValue: 16,
column: "GlExpenseAccountCode",
value: "6900");
migrationBuilder.UpdateData(
table: "expense_titles",
keyColumn: "ExpenseTitleId",
keyValue: 17,
column: "GlExpenseAccountCode",
value: "6900");
migrationBuilder.UpdateData(
table: "expense_titles",
keyColumn: "ExpenseTitleId",
keyValue: 18,
column: "GlExpenseAccountCode",
value: "6900");
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,32 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ERPCore.Migrations
{
/// <inheritdoc />
public partial class RenameDayEndToApprovedInvoices : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.UpdateData(
table: "sub_nav_items",
keyColumn: "SubNavItemId",
keyValue: 42,
column: "Label",
value: "Approved Invoices");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.UpdateData(
table: "sub_nav_items",
keyColumn: "SubNavItemId",
keyValue: 42,
column: "Label",
value: "Day End");
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,123 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ERPCore.Migrations
{
/// <inheritdoc />
public partial class AddSalesPaymentMethodsAndDayEndReport : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<decimal>(
name: "CardAmount",
table: "sales_slips",
type: "decimal(18,4)",
precision: 18,
scale: 4,
nullable: false,
defaultValue: 0m);
migrationBuilder.AddColumn<decimal>(
name: "CashAmount",
table: "sales_slips",
type: "decimal(18,4)",
precision: 18,
scale: 4,
nullable: false,
defaultValue: 0m);
migrationBuilder.AddColumn<string>(
name: "PaymentMethod",
table: "sales_invoice_payments",
type: "varchar(20)",
maxLength: 20,
nullable: false,
defaultValue: "Cash",
collation: "utf8mb4_unicode_ci");
migrationBuilder.AddColumn<decimal>(
name: "CardAmount",
table: "bundle_sales",
type: "decimal(18,4)",
precision: 18,
scale: 4,
nullable: false,
defaultValue: 0m);
migrationBuilder.AddColumn<decimal>(
name: "CashAmount",
table: "bundle_sales",
type: "decimal(18,4)",
precision: 18,
scale: 4,
nullable: false,
defaultValue: 0m);
migrationBuilder.InsertData(
table: "sub_nav_items",
columns: new[] { "SubNavItemId", "Code", "Href", "Icon", "Label", "NavItemId", "SortOrder" },
values: new object[] { 46, "sales.day-end-report", "/dashboard/sales/day-end-report", null, "Day-End Report", 13, 5 });
migrationBuilder.InsertData(
table: "permissions",
columns: new[] { "PermissionId", "Code", "NavItemId", "SubNavItemId" },
values: new object[] { 56, "NAV:sales.day-end-report", null, 46 });
// Every sale before the cash/card split existed was treated as cash (see SalesDayEnd's
// PaidTotal), so existing slips/bundles are all cash; invoice payments already default
// to 'Cash' through the column default above.
migrationBuilder.Sql("UPDATE `sales_slips` SET `CashAmount` = `PaidAmount`, `CardAmount` = 0;");
migrationBuilder.Sql("UPDATE `bundle_sales` SET `CashAmount` = `GrandTotal`, `CardAmount` = 0;");
// Grant the new report (56) to Admin and to every role that already reaches the
// cashier close-out (NAV:sales.day-end = 52) — it shows income, so it follows the
// close-out rather than plain invoicing. Same idempotent pattern as GrantExpensePermissions.
migrationBuilder.Sql("""
INSERT IGNORE INTO `role_permissions` (`RoleId`, `PermissionId`, `Actions`)
SELECT r.`RoleId`, 56, 31
FROM `roles` r
WHERE LOWER(r.`Code`) = 'admin'
OR EXISTS (SELECT 1 FROM `role_permissions` rp
WHERE rp.`RoleId` = r.`RoleId` AND rp.`PermissionId` = 52);
""");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql("DELETE FROM `role_permissions` WHERE `PermissionId` = 56;");
migrationBuilder.DeleteData(
table: "permissions",
keyColumn: "PermissionId",
keyValue: 56);
migrationBuilder.DeleteData(
table: "sub_nav_items",
keyColumn: "SubNavItemId",
keyValue: 46);
migrationBuilder.DropColumn(
name: "CardAmount",
table: "sales_slips");
migrationBuilder.DropColumn(
name: "CashAmount",
table: "sales_slips");
migrationBuilder.DropColumn(
name: "PaymentMethod",
table: "sales_invoice_payments");
migrationBuilder.DropColumn(
name: "CardAmount",
table: "bundle_sales");
migrationBuilder.DropColumn(
name: "CashAmount",
table: "bundle_sales");
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,131 @@
using System;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ERPCore.Migrations
{
/// <inheritdoc />
public partial class AddBankDepositModule : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "bank_deposits",
columns: table => new
{
BankDepositId = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
DocNo = table.Column<string>(type: "varchar(30)", maxLength: 30, nullable: false, collation: "utf8mb4_unicode_ci"),
BranchId = table.Column<int>(type: "int", nullable: false),
BusinessDate = table.Column<DateOnly>(type: "date", nullable: false),
DepositDate = table.Column<DateOnly>(type: "date", nullable: false),
Amount = table.Column<decimal>(type: "decimal(18,4)", precision: 18, scale: 4, nullable: false),
FromGlCashAccountId = table.Column<long>(type: "bigint", nullable: false),
FromCashAccountCode = table.Column<string>(type: "varchar(20)", maxLength: 20, nullable: false, collation: "utf8mb4_unicode_ci"),
FromCashAccountName = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: false, collation: "utf8mb4_unicode_ci"),
ToGlBankAccountId = table.Column<long>(type: "bigint", nullable: false),
ToBankAccountCode = table.Column<string>(type: "varchar(20)", maxLength: 20, nullable: false, collation: "utf8mb4_unicode_ci"),
ToBankAccountName = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: false, collation: "utf8mb4_unicode_ci"),
ToBankName = table.Column<string>(type: "varchar(150)", maxLength: 150, nullable: true, collation: "utf8mb4_unicode_ci"),
ToAccountNumber = table.Column<string>(type: "varchar(50)", maxLength: 50, nullable: true, collation: "utf8mb4_unicode_ci"),
DepositSlipNo = table.Column<string>(type: "varchar(50)", maxLength: 50, nullable: true, collation: "utf8mb4_unicode_ci"),
DepositedBy = table.Column<string>(type: "varchar(150)", maxLength: 150, nullable: true, collation: "utf8mb4_unicode_ci"),
Remarks = table.Column<string>(type: "varchar(500)", maxLength: 500, nullable: true, collation: "utf8mb4_unicode_ci"),
Status = table.Column<string>(type: "varchar(20)", maxLength: 20, nullable: false, defaultValue: "Posted", collation: "utf8mb4_unicode_ci"),
GlJournalNo = table.Column<string>(type: "varchar(30)", maxLength: 30, nullable: true, collation: "utf8mb4_unicode_ci"),
GlPostedAt = table.Column<DateTime>(type: "datetime(6)", nullable: true),
GlReversalJournalNo = table.Column<string>(type: "varchar(30)", maxLength: 30, nullable: true, collation: "utf8mb4_unicode_ci"),
CancelReason = table.Column<string>(type: "varchar(250)", maxLength: 250, nullable: true, collation: "utf8mb4_unicode_ci"),
CancelledBy = table.Column<int>(type: "int", nullable: true),
CancelledAt = table.Column<DateTime>(type: "datetime(6)", nullable: true),
CreatedBy = table.Column<int>(type: "int", nullable: false),
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
RowVersion = table.Column<uint>(type: "int unsigned", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_bank_deposits", x => x.BankDepositId);
table.CheckConstraint("ck_bank_deposits_amount", "`Amount` > 0");
table.ForeignKey(
name: "FK_bank_deposits_hr_branches_BranchId",
column: x => x.BranchId,
principalTable: "hr_branches",
principalColumn: "BranchId",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_bank_deposits_users_CreatedBy",
column: x => x.CreatedBy,
principalTable: "users",
principalColumn: "UserId",
onDelete: ReferentialAction.Restrict);
})
.Annotation("Relational:Collation", "utf8mb4_unicode_ci");
migrationBuilder.InsertData(
table: "sub_nav_items",
columns: new[] { "SubNavItemId", "Code", "Href", "Icon", "Label", "NavItemId", "SortOrder" },
values: new object[] { 47, "accounts.bank-deposits", "/dashboard/accounts/bank-deposits", null, "Bank Deposits", 12, 6 });
migrationBuilder.InsertData(
table: "permissions",
columns: new[] { "PermissionId", "Code", "NavItemId", "SubNavItemId" },
values: new object[] { 57, "NAV:accounts.bank-deposits", null, 47 });
migrationBuilder.CreateIndex(
name: "IX_bank_deposits_BranchId_BusinessDate_Status",
table: "bank_deposits",
columns: new[] { "BranchId", "BusinessDate", "Status" });
migrationBuilder.CreateIndex(
name: "IX_bank_deposits_CreatedBy",
table: "bank_deposits",
column: "CreatedBy");
migrationBuilder.CreateIndex(
name: "IX_bank_deposits_DocNo",
table: "bank_deposits",
column: "DocNo",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_bank_deposits_ToGlBankAccountId",
table: "bank_deposits",
column: "ToGlBankAccountId");
// Grant the new Accounts sub-item (57) to Admin and to every role that already reaches
// Accounts (NAV:accounts 32, bank-accounts 26, cheque-books 33, received-cheques 34,
// expenses 54). Actions 31 = all, so Create (record) and Delete (cancel) included; admins
// can narrow it per role afterwards. Same idempotent pattern as GrantExpensePermissions.
migrationBuilder.Sql("""
INSERT IGNORE INTO `role_permissions` (`RoleId`, `PermissionId`, `Actions`)
SELECT r.`RoleId`, 57, 31
FROM `roles` r
WHERE LOWER(r.`Code`) = 'admin'
OR EXISTS (SELECT 1 FROM `role_permissions` rp
WHERE rp.`RoleId` = r.`RoleId` AND rp.`PermissionId` IN (26, 32, 33, 34, 54));
""");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql("DELETE FROM `role_permissions` WHERE `PermissionId` = 57;");
migrationBuilder.DropTable(
name: "bank_deposits");
migrationBuilder.DeleteData(
table: "permissions",
keyColumn: "PermissionId",
keyValue: 57);
migrationBuilder.DeleteData(
table: "sub_nav_items",
keyColumn: "SubNavItemId",
keyValue: 47);
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,33 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ERPCore.Migrations
{
/// <summary>
/// Data-only: turns the new "stock.low" (Low Stock / Reorder Alert) module on for the in-app
/// bell. A module with no row is silently off, so without this no alert would ever reach anyone
/// until an admin ticked it under Settings → Notifications. Only inserts when the notification
/// config exists and the module has no row yet, so a choice already made is left alone.
/// </summary>
public partial class EnableLowStockAlerts : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql("""
INSERT INTO `notification_config_modules` (`NotificationConfigId`, `ModuleKey`, `EmailEnabled`, `SmsEnabled`, `InAppEnabled`)
SELECT c.`NotificationConfigId`, 'stock.low', 0, 0, 1
FROM `notification_config` c
WHERE c.`NotificationConfigId` = 1
AND NOT EXISTS (SELECT 1 FROM `notification_config_modules` m WHERE m.`ModuleKey` = 'stock.low');
""");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql("DELETE FROM `notification_config_modules` WHERE `ModuleKey` = 'stock.low';");
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,473 @@
using System;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
namespace ERPCore.Migrations
{
/// <inheritdoc />
public partial class AddDualApproval : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "Status",
table: "stock_adjustments",
type: "varchar(30)",
maxLength: 30,
nullable: false,
collation: "utf8mb4_unicode_ci",
oldClrType: typeof(string),
oldType: "varchar(20)",
oldMaxLength: 20)
.OldAnnotation("Relational:Collation", "utf8mb4_unicode_ci");
migrationBuilder.AddColumn<DateTime>(
name: "ApprovedLevel1At",
table: "stock_adjustments",
type: "datetime(6)",
nullable: true);
migrationBuilder.AddColumn<int>(
name: "ApprovedLevel1By",
table: "stock_adjustments",
type: "int",
nullable: true);
migrationBuilder.AddColumn<DateTime>(
name: "ApprovedLevel2At",
table: "stock_adjustments",
type: "datetime(6)",
nullable: true);
migrationBuilder.AddColumn<int>(
name: "ApprovedLevel2By",
table: "stock_adjustments",
type: "int",
nullable: true);
migrationBuilder.AddColumn<DateTime>(
name: "CancelledAt",
table: "stock_adjustments",
type: "datetime(6)",
nullable: true);
migrationBuilder.AddColumn<DateTime>(
name: "PostedAt",
table: "stock_adjustments",
type: "datetime(6)",
nullable: true);
migrationBuilder.AddColumn<string>(
name: "RejectReason",
table: "stock_adjustments",
type: "varchar(250)",
maxLength: 250,
nullable: true,
collation: "utf8mb4_unicode_ci");
migrationBuilder.AddColumn<DateTime>(
name: "RejectedAt",
table: "stock_adjustments",
type: "datetime(6)",
nullable: true);
migrationBuilder.AddColumn<int>(
name: "RejectedBy",
table: "stock_adjustments",
type: "int",
nullable: true);
migrationBuilder.AddColumn<int>(
name: "RequiredApprovals",
table: "stock_adjustments",
type: "int",
nullable: false,
defaultValue: 0);
migrationBuilder.AddColumn<string>(
name: "RequestedSerialIds",
table: "stock_adjustment_lines",
type: "varchar(4000)",
maxLength: 4000,
nullable: true,
collation: "utf8mb4_unicode_ci");
migrationBuilder.AddColumn<string>(
name: "RequestedSerialNos",
table: "stock_adjustment_lines",
type: "varchar(4000)",
maxLength: 4000,
nullable: true,
collation: "utf8mb4_unicode_ci");
migrationBuilder.CreateTable(
name: "approval_config",
columns: table => new
{
ApprovalConfigId = table.Column<int>(type: "int", nullable: false),
StockAdjustmentLevels = table.Column<int>(type: "int", nullable: false),
StockAdjustmentLevel2ThresholdValue = table.Column<decimal>(type: "decimal(18,4)", precision: 18, scale: 4, nullable: false),
PriceAdjustmentLevels = table.Column<int>(type: "int", nullable: false),
PriceAdjustmentLevel2ThresholdPercent = table.Column<decimal>(type: "decimal(9,4)", precision: 9, scale: 4, nullable: false),
Level2RoleCodes = table.Column<string>(type: "varchar(500)", maxLength: 500, nullable: true, collation: "utf8mb4_unicode_ci"),
UpdatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: true),
UpdatedBy = table.Column<int>(type: "int", nullable: true),
RowVersion = table.Column<uint>(type: "int unsigned", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_approval_config", x => x.ApprovalConfigId);
table.CheckConstraint("ck_approval_config_singleton", "`ApprovalConfigId` = 1");
})
.Annotation("Relational:Collation", "utf8mb4_unicode_ci");
migrationBuilder.CreateTable(
name: "document_approvals",
columns: table => new
{
DocumentApprovalId = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
DocType = table.Column<string>(type: "varchar(10)", maxLength: 10, nullable: false, collation: "utf8mb4_unicode_ci"),
DocId = table.Column<int>(type: "int", nullable: false),
Level = table.Column<int>(type: "int", nullable: false),
Decision = table.Column<string>(type: "varchar(20)", maxLength: 20, nullable: false, collation: "utf8mb4_unicode_ci"),
DecidedBy = table.Column<int>(type: "int", nullable: false),
DecidedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
Comment = table.Column<string>(type: "varchar(250)", maxLength: 250, nullable: true, collation: "utf8mb4_unicode_ci")
},
constraints: table =>
{
table.PrimaryKey("PK_document_approvals", x => x.DocumentApprovalId);
table.ForeignKey(
name: "FK_document_approvals_users_DecidedBy",
column: x => x.DecidedBy,
principalTable: "users",
principalColumn: "UserId",
onDelete: ReferentialAction.Restrict);
})
.Annotation("Relational:Collation", "utf8mb4_unicode_ci");
migrationBuilder.CreateTable(
name: "price_adjustments",
columns: table => new
{
PriceAdjustmentId = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
DocNo = table.Column<string>(type: "varchar(30)", maxLength: 30, nullable: false, collation: "utf8mb4_unicode_ci"),
Reason = table.Column<string>(type: "varchar(250)", maxLength: 250, nullable: false, collation: "utf8mb4_unicode_ci"),
Status = table.Column<string>(type: "varchar(30)", maxLength: 30, nullable: false, defaultValue: "PendingApproval", collation: "utf8mb4_unicode_ci"),
RequiredApprovals = table.Column<int>(type: "int", nullable: false),
CreatedBy = table.Column<int>(type: "int", nullable: false),
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
ApprovedLevel1By = table.Column<int>(type: "int", nullable: true),
ApprovedLevel1At = table.Column<DateTime>(type: "datetime(6)", nullable: true),
ApprovedLevel2By = table.Column<int>(type: "int", nullable: true),
ApprovedLevel2At = table.Column<DateTime>(type: "datetime(6)", nullable: true),
RejectedBy = table.Column<int>(type: "int", nullable: true),
RejectedAt = table.Column<DateTime>(type: "datetime(6)", nullable: true),
RejectReason = table.Column<string>(type: "varchar(250)", maxLength: 250, nullable: true, collation: "utf8mb4_unicode_ci"),
CancelledAt = table.Column<DateTime>(type: "datetime(6)", nullable: true),
AppliedAt = table.Column<DateTime>(type: "datetime(6)", nullable: true),
RowVersion = table.Column<uint>(type: "int unsigned", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_price_adjustments", x => x.PriceAdjustmentId);
table.ForeignKey(
name: "FK_price_adjustments_users_CreatedBy",
column: x => x.CreatedBy,
principalTable: "users",
principalColumn: "UserId",
onDelete: ReferentialAction.Restrict);
})
.Annotation("Relational:Collation", "utf8mb4_unicode_ci");
migrationBuilder.CreateTable(
name: "item_price_history",
columns: table => new
{
ItemPriceHistoryId = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
ItemId = table.Column<int>(type: "int", nullable: false),
PriceAdjustmentId = table.Column<int>(type: "int", nullable: true),
OldMinPrice = table.Column<decimal>(type: "decimal(18,4)", precision: 18, scale: 4, nullable: true),
OldMaxPrice = table.Column<decimal>(type: "decimal(18,4)", precision: 18, scale: 4, nullable: true),
OldFlatPrice = table.Column<decimal>(type: "decimal(18,4)", precision: 18, scale: 4, nullable: true),
NewMinPrice = table.Column<decimal>(type: "decimal(18,4)", precision: 18, scale: 4, nullable: true),
NewMaxPrice = table.Column<decimal>(type: "decimal(18,4)", precision: 18, scale: 4, nullable: true),
NewFlatPrice = table.Column<decimal>(type: "decimal(18,4)", precision: 18, scale: 4, nullable: true),
RequestedBy = table.Column<int>(type: "int", nullable: false),
ApprovedLevel1By = table.Column<int>(type: "int", nullable: true),
ApprovedLevel2By = table.Column<int>(type: "int", nullable: true),
AppliedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_item_price_history", x => x.ItemPriceHistoryId);
table.ForeignKey(
name: "FK_item_price_history_items_ItemId",
column: x => x.ItemId,
principalTable: "items",
principalColumn: "ItemId",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_item_price_history_price_adjustments_PriceAdjustmentId",
column: x => x.PriceAdjustmentId,
principalTable: "price_adjustments",
principalColumn: "PriceAdjustmentId",
onDelete: ReferentialAction.Restrict);
})
.Annotation("Relational:Collation", "utf8mb4_unicode_ci");
migrationBuilder.CreateTable(
name: "price_adjustment_lines",
columns: table => new
{
PriceAdjustmentLineId = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
PriceAdjustmentId = table.Column<int>(type: "int", nullable: false),
ItemId = table.Column<int>(type: "int", nullable: false),
OldMinPrice = table.Column<decimal>(type: "decimal(18,4)", precision: 18, scale: 4, nullable: true),
OldMaxPrice = table.Column<decimal>(type: "decimal(18,4)", precision: 18, scale: 4, nullable: true),
OldFlatPrice = table.Column<decimal>(type: "decimal(18,4)", precision: 18, scale: 4, nullable: true),
NewMinPrice = table.Column<decimal>(type: "decimal(18,4)", precision: 18, scale: 4, nullable: true),
NewMaxPrice = table.Column<decimal>(type: "decimal(18,4)", precision: 18, scale: 4, nullable: true),
NewFlatPrice = table.Column<decimal>(type: "decimal(18,4)", precision: 18, scale: 4, nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_price_adjustment_lines", x => x.PriceAdjustmentLineId);
table.ForeignKey(
name: "FK_price_adjustment_lines_items_ItemId",
column: x => x.ItemId,
principalTable: "items",
principalColumn: "ItemId",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_price_adjustment_lines_price_adjustments_PriceAdjustmentId",
column: x => x.PriceAdjustmentId,
principalTable: "price_adjustments",
principalColumn: "PriceAdjustmentId",
onDelete: ReferentialAction.Cascade);
})
.Annotation("Relational:Collation", "utf8mb4_unicode_ci");
migrationBuilder.InsertData(
table: "approval_config",
columns: new[] { "ApprovalConfigId", "Level2RoleCodes", "PriceAdjustmentLevel2ThresholdPercent", "PriceAdjustmentLevels", "RowVersion", "StockAdjustmentLevel2ThresholdValue", "StockAdjustmentLevels", "UpdatedAt", "UpdatedBy" },
values: new object[] { 1, null, 0m, 2, 1u, 0m, 2, null, null });
migrationBuilder.InsertData(
table: "sub_nav_items",
columns: new[] { "SubNavItemId", "Code", "Href", "Icon", "Label", "NavItemId", "SortOrder" },
values: new object[,]
{
{ 48, "products.price-adjustments", "/dashboard/products/price-adjustments", null, "Price Adjustments", 2, 8 },
{ 49, "settings.approvals", "/dashboard/settings/approvals", null, "Approvals", 9, 4 }
});
migrationBuilder.InsertData(
table: "permissions",
columns: new[] { "PermissionId", "Code", "NavItemId", "SubNavItemId" },
values: new object[,]
{
{ 58, "NAV:products.price-adjustments", null, 48 },
{ 59, "NAV:settings.approvals", null, 49 }
});
migrationBuilder.CreateIndex(
name: "IX_stock_adjustments_Status",
table: "stock_adjustments",
column: "Status");
migrationBuilder.CreateIndex(
name: "IX_document_approvals_DecidedBy",
table: "document_approvals",
column: "DecidedBy");
migrationBuilder.CreateIndex(
name: "IX_document_approvals_DocType_DocId",
table: "document_approvals",
columns: new[] { "DocType", "DocId" });
migrationBuilder.CreateIndex(
name: "IX_item_price_history_ItemId_AppliedAt",
table: "item_price_history",
columns: new[] { "ItemId", "AppliedAt" });
migrationBuilder.CreateIndex(
name: "IX_item_price_history_PriceAdjustmentId",
table: "item_price_history",
column: "PriceAdjustmentId");
migrationBuilder.CreateIndex(
name: "IX_price_adjustment_lines_ItemId",
table: "price_adjustment_lines",
column: "ItemId");
migrationBuilder.CreateIndex(
name: "IX_price_adjustment_lines_PriceAdjustmentId",
table: "price_adjustment_lines",
column: "PriceAdjustmentId");
migrationBuilder.CreateIndex(
name: "IX_price_adjustments_CreatedBy",
table: "price_adjustments",
column: "CreatedBy");
migrationBuilder.CreateIndex(
name: "IX_price_adjustments_DocNo",
table: "price_adjustments",
column: "DocNo",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_price_adjustments_Status",
table: "price_adjustments",
column: "Status");
// Existing adjustments all auto-posted, so they need no approval rows — RequiredApprovals = 0
// (the column default) marks them as "posted without approval".
// Price Adjustments (58): Admin and every role that already reaches Products (NAV:products 2,
// products.item 11). Approval settings (59): Admin only. Actions 31 = all, including Approve —
// admins should narrow Approve to the people who really approve (at least two per branch).
migrationBuilder.Sql("""
INSERT IGNORE INTO `role_permissions` (`RoleId`, `PermissionId`, `Actions`)
SELECT r.`RoleId`, 58, 31
FROM `roles` r
WHERE LOWER(r.`Code`) = 'admin'
OR EXISTS (SELECT 1 FROM `role_permissions` rp
WHERE rp.`RoleId` = r.`RoleId` AND rp.`PermissionId` IN (2, 11));
""");
migrationBuilder.Sql("""
INSERT IGNORE INTO `role_permissions` (`RoleId`, `PermissionId`, `Actions`)
SELECT r.`RoleId`, 59, 31 FROM `roles` r WHERE LOWER(r.`Code`) = 'admin';
""");
// The approval notifications are on in the bell by default — without them nobody learns a
// request is waiting. Same guarded insert as EnableLowStockAlerts.
foreach (var key in new[] { "approval.pending", "approval.approved", "approval.rejected" })
{
migrationBuilder.Sql($"""
INSERT INTO `notification_config_modules` (`NotificationConfigId`, `ModuleKey`, `EmailEnabled`, `SmsEnabled`, `InAppEnabled`)
SELECT c.`NotificationConfigId`, '{key}', 0, 0, 1
FROM `notification_config` c
WHERE c.`NotificationConfigId` = 1
AND NOT EXISTS (SELECT 1 FROM `notification_config_modules` m WHERE m.`ModuleKey` = '{key}');
""");
}
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql("DELETE FROM `role_permissions` WHERE `PermissionId` IN (58, 59);");
migrationBuilder.Sql("DELETE FROM `notification_config_modules` WHERE `ModuleKey` IN ('approval.pending', 'approval.approved', 'approval.rejected');");
migrationBuilder.DropTable(
name: "approval_config");
migrationBuilder.DropTable(
name: "document_approvals");
migrationBuilder.DropTable(
name: "item_price_history");
migrationBuilder.DropTable(
name: "price_adjustment_lines");
migrationBuilder.DropTable(
name: "price_adjustments");
migrationBuilder.DropIndex(
name: "IX_stock_adjustments_Status",
table: "stock_adjustments");
migrationBuilder.DeleteData(
table: "permissions",
keyColumn: "PermissionId",
keyValue: 58);
migrationBuilder.DeleteData(
table: "permissions",
keyColumn: "PermissionId",
keyValue: 59);
migrationBuilder.DeleteData(
table: "sub_nav_items",
keyColumn: "SubNavItemId",
keyValue: 48);
migrationBuilder.DeleteData(
table: "sub_nav_items",
keyColumn: "SubNavItemId",
keyValue: 49);
migrationBuilder.DropColumn(
name: "ApprovedLevel1At",
table: "stock_adjustments");
migrationBuilder.DropColumn(
name: "ApprovedLevel1By",
table: "stock_adjustments");
migrationBuilder.DropColumn(
name: "ApprovedLevel2At",
table: "stock_adjustments");
migrationBuilder.DropColumn(
name: "ApprovedLevel2By",
table: "stock_adjustments");
migrationBuilder.DropColumn(
name: "CancelledAt",
table: "stock_adjustments");
migrationBuilder.DropColumn(
name: "PostedAt",
table: "stock_adjustments");
migrationBuilder.DropColumn(
name: "RejectReason",
table: "stock_adjustments");
migrationBuilder.DropColumn(
name: "RejectedAt",
table: "stock_adjustments");
migrationBuilder.DropColumn(
name: "RejectedBy",
table: "stock_adjustments");
migrationBuilder.DropColumn(
name: "RequiredApprovals",
table: "stock_adjustments");
migrationBuilder.DropColumn(
name: "RequestedSerialIds",
table: "stock_adjustment_lines");
migrationBuilder.DropColumn(
name: "RequestedSerialNos",
table: "stock_adjustment_lines");
migrationBuilder.AlterColumn<string>(
name: "Status",
table: "stock_adjustments",
type: "varchar(20)",
maxLength: 20,
nullable: false,
collation: "utf8mb4_unicode_ci",
oldClrType: typeof(string),
oldType: "varchar(30)",
oldMaxLength: 30)
.OldAnnotation("Relational:Collation", "utf8mb4_unicode_ci");
}
}
}
@@ -23,6 +23,58 @@ namespace ERPCore.Migrations
MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);
modelBuilder.Entity("ERPCore.Domain.Entities.ApprovalConfig", b =>
{
b.Property<int>("ApprovalConfigId")
.HasColumnType("int");
b.Property<string>("Level2RoleCodes")
.HasMaxLength(500)
.HasColumnType("varchar(500)");
b.Property<decimal>("PriceAdjustmentLevel2ThresholdPercent")
.HasPrecision(9, 4)
.HasColumnType("decimal(9,4)");
b.Property<int>("PriceAdjustmentLevels")
.HasColumnType("int");
b.Property<uint>("RowVersion")
.IsConcurrencyToken()
.HasColumnType("int unsigned");
b.Property<decimal>("StockAdjustmentLevel2ThresholdValue")
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<int>("StockAdjustmentLevels")
.HasColumnType("int");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("datetime(6)");
b.Property<int?>("UpdatedBy")
.HasColumnType("int");
b.HasKey("ApprovalConfigId");
b.ToTable("approval_config", null, t =>
{
t.HasCheckConstraint("ck_approval_config_singleton", "`ApprovalConfigId` = 1");
});
b.HasData(
new
{
ApprovalConfigId = 1,
PriceAdjustmentLevel2ThresholdPercent = 0m,
PriceAdjustmentLevels = 2,
RowVersion = 1u,
StockAdjustmentLevel2ThresholdValue = 0m,
StockAdjustmentLevels = 2
});
});
modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceRecord", b =>
{
b.Property<int>("AttendanceRecordId")
@@ -214,6 +266,133 @@ namespace ERPCore.Migrations
b.ToTable("audit_logs", (string)null);
});
modelBuilder.Entity("ERPCore.Domain.Entities.BankDeposit", b =>
{
b.Property<int>("BankDepositId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>("BankDepositId"));
b.Property<decimal>("Amount")
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<int>("BranchId")
.HasColumnType("int");
b.Property<DateOnly>("BusinessDate")
.HasColumnType("date");
b.Property<string>("CancelReason")
.HasMaxLength(250)
.HasColumnType("varchar(250)");
b.Property<DateTime?>("CancelledAt")
.HasColumnType("datetime(6)");
b.Property<int?>("CancelledBy")
.HasColumnType("int");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<int>("CreatedBy")
.HasColumnType("int");
b.Property<DateOnly>("DepositDate")
.HasColumnType("date");
b.Property<string>("DepositSlipNo")
.HasMaxLength(50)
.HasColumnType("varchar(50)");
b.Property<string>("DepositedBy")
.HasMaxLength(150)
.HasColumnType("varchar(150)");
b.Property<string>("DocNo")
.IsRequired()
.HasMaxLength(30)
.HasColumnType("varchar(30)");
b.Property<string>("FromCashAccountCode")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("varchar(20)");
b.Property<string>("FromCashAccountName")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<long>("FromGlCashAccountId")
.HasColumnType("bigint");
b.Property<string>("GlJournalNo")
.HasMaxLength(30)
.HasColumnType("varchar(30)");
b.Property<DateTime?>("GlPostedAt")
.HasColumnType("datetime(6)");
b.Property<string>("GlReversalJournalNo")
.HasMaxLength(30)
.HasColumnType("varchar(30)");
b.Property<string>("Remarks")
.HasMaxLength(500)
.HasColumnType("varchar(500)");
b.Property<uint>("RowVersion")
.IsConcurrencyToken()
.HasColumnType("int unsigned");
b.Property<string>("Status")
.IsRequired()
.ValueGeneratedOnAdd()
.HasMaxLength(20)
.HasColumnType("varchar(20)")
.HasDefaultValue("Posted");
b.Property<string>("ToAccountNumber")
.HasMaxLength(50)
.HasColumnType("varchar(50)");
b.Property<string>("ToBankAccountCode")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("varchar(20)");
b.Property<string>("ToBankAccountName")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<string>("ToBankName")
.HasMaxLength(150)
.HasColumnType("varchar(150)");
b.Property<long>("ToGlBankAccountId")
.HasColumnType("bigint");
b.HasKey("BankDepositId");
b.HasIndex("CreatedBy");
b.HasIndex("DocNo")
.IsUnique();
b.HasIndex("ToGlBankAccountId");
b.HasIndex("BranchId", "BusinessDate", "Status");
b.ToTable("bank_deposits", null, t =>
{
t.HasCheckConstraint("ck_bank_deposits_amount", "`Amount` > 0");
});
});
modelBuilder.Entity("ERPCore.Domain.Entities.Batch", b =>
{
b.Property<int>("BatchId")
@@ -435,6 +614,14 @@ namespace ERPCore.Migrations
b.Property<int>("BundleSaleTemplateId")
.HasColumnType("int");
b.Property<decimal>("CardAmount")
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<decimal>("CashAmount")
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<int>("CashierUserId")
.HasColumnType("int");
@@ -904,6 +1091,49 @@ namespace ERPCore.Migrations
b.ToTable("hr_designations", (string)null);
});
modelBuilder.Entity("ERPCore.Domain.Entities.DocumentApproval", b =>
{
b.Property<int>("DocumentApprovalId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>("DocumentApprovalId"));
b.Property<string>("Comment")
.HasMaxLength(250)
.HasColumnType("varchar(250)");
b.Property<DateTime>("DecidedAt")
.HasColumnType("datetime(6)");
b.Property<int>("DecidedBy")
.HasColumnType("int");
b.Property<string>("Decision")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("varchar(20)");
b.Property<int>("DocId")
.HasColumnType("int");
b.Property<string>("DocType")
.IsRequired()
.HasMaxLength(10)
.HasColumnType("varchar(10)");
b.Property<int>("Level")
.HasColumnType("int");
b.HasKey("DocumentApprovalId");
b.HasIndex("DecidedBy");
b.HasIndex("DocType", "DocId");
b.ToTable("document_approvals", (string)null);
});
modelBuilder.Entity("ERPCore.Domain.Entities.Employee", b =>
{
b.Property<int>("EmployeeId")
@@ -1989,6 +2219,65 @@ namespace ERPCore.Migrations
b.ToTable("item_images", (string)null);
});
modelBuilder.Entity("ERPCore.Domain.Entities.ItemPriceHistory", b =>
{
b.Property<int>("ItemPriceHistoryId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>("ItemPriceHistoryId"));
b.Property<DateTime>("AppliedAt")
.HasColumnType("datetime(6)");
b.Property<int?>("ApprovedLevel1By")
.HasColumnType("int");
b.Property<int?>("ApprovedLevel2By")
.HasColumnType("int");
b.Property<int>("ItemId")
.HasColumnType("int");
b.Property<decimal?>("NewFlatPrice")
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<decimal?>("NewMaxPrice")
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<decimal?>("NewMinPrice")
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<decimal?>("OldFlatPrice")
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<decimal?>("OldMaxPrice")
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<decimal?>("OldMinPrice")
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<int?>("PriceAdjustmentId")
.HasColumnType("int");
b.Property<int>("RequestedBy")
.HasColumnType("int");
b.HasKey("ItemPriceHistoryId");
b.HasIndex("PriceAdjustmentId");
b.HasIndex("ItemId", "AppliedAt");
b.ToTable("item_price_history", (string)null);
});
modelBuilder.Entity("ERPCore.Domain.Entities.ItemReorder", b =>
{
b.Property<int>("ReorderId")
@@ -3343,6 +3632,42 @@ namespace ERPCore.Migrations
PermissionId = 53,
Code = "NAV:products.tax-rates",
SubNavItemId = 43
},
new
{
PermissionId = 54,
Code = "NAV:accounts.expenses",
SubNavItemId = 44
},
new
{
PermissionId = 55,
Code = "NAV:accounts.expense-setup",
SubNavItemId = 45
},
new
{
PermissionId = 56,
Code = "NAV:sales.day-end-report",
SubNavItemId = 46
},
new
{
PermissionId = 57,
Code = "NAV:accounts.bank-deposits",
SubNavItemId = 47
},
new
{
PermissionId = 58,
Code = "NAV:products.price-adjustments",
SubNavItemId = 48
},
new
{
PermissionId = 59,
Code = "NAV:settings.approvals",
SubNavItemId = 49
});
});
@@ -3390,6 +3715,131 @@ namespace ERPCore.Migrations
b.ToTable("po_lines", (string)null);
});
modelBuilder.Entity("ERPCore.Domain.Entities.PriceAdjustment", b =>
{
b.Property<int>("PriceAdjustmentId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>("PriceAdjustmentId"));
b.Property<DateTime?>("AppliedAt")
.HasColumnType("datetime(6)");
b.Property<DateTime?>("ApprovedLevel1At")
.HasColumnType("datetime(6)");
b.Property<int?>("ApprovedLevel1By")
.HasColumnType("int");
b.Property<DateTime?>("ApprovedLevel2At")
.HasColumnType("datetime(6)");
b.Property<int?>("ApprovedLevel2By")
.HasColumnType("int");
b.Property<DateTime?>("CancelledAt")
.HasColumnType("datetime(6)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<int>("CreatedBy")
.HasColumnType("int");
b.Property<string>("DocNo")
.IsRequired()
.HasMaxLength(30)
.HasColumnType("varchar(30)");
b.Property<string>("Reason")
.IsRequired()
.HasMaxLength(250)
.HasColumnType("varchar(250)");
b.Property<string>("RejectReason")
.HasMaxLength(250)
.HasColumnType("varchar(250)");
b.Property<DateTime?>("RejectedAt")
.HasColumnType("datetime(6)");
b.Property<int?>("RejectedBy")
.HasColumnType("int");
b.Property<int>("RequiredApprovals")
.HasColumnType("int");
b.Property<uint>("RowVersion")
.IsConcurrencyToken()
.HasColumnType("int unsigned");
b.Property<string>("Status")
.IsRequired()
.ValueGeneratedOnAdd()
.HasMaxLength(30)
.HasColumnType("varchar(30)")
.HasDefaultValue("PendingApproval");
b.HasKey("PriceAdjustmentId");
b.HasIndex("CreatedBy");
b.HasIndex("DocNo")
.IsUnique();
b.HasIndex("Status");
b.ToTable("price_adjustments", (string)null);
});
modelBuilder.Entity("ERPCore.Domain.Entities.PriceAdjustmentLine", b =>
{
b.Property<int>("PriceAdjustmentLineId")
.ValueGeneratedOnAdd()
.HasColumnType("int");
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>("PriceAdjustmentLineId"));
b.Property<int>("ItemId")
.HasColumnType("int");
b.Property<decimal?>("NewFlatPrice")
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<decimal?>("NewMaxPrice")
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<decimal?>("NewMinPrice")
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<decimal?>("OldFlatPrice")
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<decimal?>("OldMaxPrice")
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<decimal?>("OldMinPrice")
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<int>("PriceAdjustmentId")
.HasColumnType("int");
b.HasKey("PriceAdjustmentLineId");
b.HasIndex("ItemId");
b.HasIndex("PriceAdjustmentId");
b.ToTable("price_adjustment_lines", (string)null);
});
modelBuilder.Entity("ERPCore.Domain.Entities.ProductConfig", b =>
{
b.Property<int>("ConfigId")
@@ -4910,6 +5360,13 @@ namespace ERPCore.Migrations
b.Property<DateTime>("PaymentDate")
.HasColumnType("datetime(6)");
b.Property<string>("PaymentMethod")
.IsRequired()
.ValueGeneratedOnAdd()
.HasMaxLength(20)
.HasColumnType("varchar(20)")
.HasDefaultValue("Cash");
b.Property<string>("Reference")
.HasMaxLength(100)
.HasColumnType("varchar(100)");
@@ -5112,6 +5569,14 @@ namespace ERPCore.Migrations
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<decimal>("CardAmount")
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<decimal>("CashAmount")
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<int>("CashierUserId")
.HasColumnType("int");
@@ -5549,9 +6014,24 @@ namespace ERPCore.Migrations
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>("AdjustmentId"));
b.Property<DateTime?>("ApprovedLevel1At")
.HasColumnType("datetime(6)");
b.Property<int?>("ApprovedLevel1By")
.HasColumnType("int");
b.Property<DateTime?>("ApprovedLevel2At")
.HasColumnType("datetime(6)");
b.Property<int?>("ApprovedLevel2By")
.HasColumnType("int");
b.Property<int>("BranchId")
.HasColumnType("int");
b.Property<DateTime?>("CancelledAt")
.HasColumnType("datetime(6)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
@@ -5570,17 +6050,33 @@ namespace ERPCore.Migrations
b.Property<DateTime?>("GlPostedAt")
.HasColumnType("datetime(6)");
b.Property<DateTime?>("PostedAt")
.HasColumnType("datetime(6)");
b.Property<int>("ReasonCodeId")
.HasColumnType("int");
b.Property<string>("RejectReason")
.HasMaxLength(250)
.HasColumnType("varchar(250)");
b.Property<DateTime?>("RejectedAt")
.HasColumnType("datetime(6)");
b.Property<int?>("RejectedBy")
.HasColumnType("int");
b.Property<int>("RequiredApprovals")
.HasColumnType("int");
b.Property<uint>("RowVersion")
.IsConcurrencyToken()
.HasColumnType("int unsigned");
b.Property<string>("Status")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("varchar(20)");
.HasMaxLength(30)
.HasColumnType("varchar(30)");
b.Property<int>("WarehouseId")
.HasColumnType("int");
@@ -5596,6 +6092,8 @@ namespace ERPCore.Migrations
b.HasIndex("ReasonCodeId");
b.HasIndex("Status");
b.HasIndex("WarehouseId");
b.ToTable("stock_adjustments", (string)null);
@@ -5625,6 +6123,14 @@ namespace ERPCore.Migrations
.HasPrecision(18, 4)
.HasColumnType("decimal(18,4)");
b.Property<string>("RequestedSerialIds")
.HasMaxLength(4000)
.HasColumnType("varchar(4000)");
b.Property<string>("RequestedSerialNos")
.HasMaxLength(4000)
.HasColumnType("varchar(4000)");
b.Property<int?>("SerialId")
.HasColumnType("int");
@@ -6189,6 +6695,16 @@ namespace ERPCore.Migrations
Status = "Active"
},
new
{
SubNavItemId = 48,
Code = "products.price-adjustments",
Href = "/dashboard/products/price-adjustments",
Label = "Price Adjustments",
NavItemId = 2,
SortOrder = 8,
Status = "Active"
},
new
{
SubNavItemId = 29,
Code = "settings.branches",
@@ -6229,6 +6745,16 @@ namespace ERPCore.Migrations
Status = "Active"
},
new
{
SubNavItemId = 49,
Code = "settings.approvals",
Href = "/dashboard/settings/approvals",
Label = "Approvals",
NavItemId = 9,
SortOrder = 4,
Status = "Active"
},
new
{
SubNavItemId = 40,
Code = "sales.invoices",
@@ -6263,12 +6789,22 @@ namespace ERPCore.Migrations
SubNavItemId = 42,
Code = "sales.day-end",
Href = "/dashboard/sales/day-end",
Label = "Day End",
Label = "Approved Invoices",
NavItemId = 13,
SortOrder = 4,
Status = "Active"
},
new
{
SubNavItemId = 46,
Code = "sales.day-end-report",
Href = "/dashboard/sales/day-end-report",
Label = "Day-End Report",
NavItemId = 13,
SortOrder = 5,
Status = "Active"
},
new
{
SubNavItemId = 30,
Code = "procurement.vendors",
@@ -6429,6 +6965,36 @@ namespace ERPCore.Migrations
Status = "Active"
},
new
{
SubNavItemId = 44,
Code = "accounts.expenses",
Href = "/dashboard/accounts/expenses",
Label = "Expenses",
NavItemId = 12,
SortOrder = 4,
Status = "Active"
},
new
{
SubNavItemId = 45,
Code = "accounts.expense-setup",
Href = "/dashboard/accounts/expense-setup",
Label = "Expense Setup",
NavItemId = 12,
SortOrder = 5,
Status = "Active"
},
new
{
SubNavItemId = 47,
Code = "accounts.bank-deposits",
Href = "/dashboard/accounts/bank-deposits",
Label = "Bank Deposits",
NavItemId = 12,
SortOrder = 6,
Status = "Active"
},
new
{
SubNavItemId = 27,
Code = "production.templates",
@@ -7245,6 +7811,25 @@ namespace ERPCore.Migrations
.IsRequired();
});
modelBuilder.Entity("ERPCore.Domain.Entities.BankDeposit", b =>
{
b.HasOne("ERPCore.Domain.Entities.Branch", "Branch")
.WithMany()
.HasForeignKey("BranchId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.HasOne("ERPCore.Domain.Entities.User", "Creator")
.WithMany()
.HasForeignKey("CreatedBy")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("Branch");
b.Navigation("Creator");
});
modelBuilder.Entity("ERPCore.Domain.Entities.Batch", b =>
{
b.HasOne("ERPCore.Domain.Entities.Item", "Item")
@@ -7415,6 +8000,17 @@ namespace ERPCore.Migrations
b.Navigation("ParentDepartment");
});
modelBuilder.Entity("ERPCore.Domain.Entities.DocumentApproval", b =>
{
b.HasOne("ERPCore.Domain.Entities.User", "Decider")
.WithMany()
.HasForeignKey("DecidedBy")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("Decider");
});
modelBuilder.Entity("ERPCore.Domain.Entities.Employee", b =>
{
b.HasOne("ERPCore.Domain.Entities.Branch", "Branch")
@@ -7746,6 +8342,24 @@ namespace ERPCore.Migrations
b.Navigation("Item");
});
modelBuilder.Entity("ERPCore.Domain.Entities.ItemPriceHistory", b =>
{
b.HasOne("ERPCore.Domain.Entities.Item", "Item")
.WithMany()
.HasForeignKey("ItemId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.HasOne("ERPCore.Domain.Entities.PriceAdjustment", "PriceAdjustment")
.WithMany()
.HasForeignKey("PriceAdjustmentId")
.OnDelete(DeleteBehavior.Restrict);
b.Navigation("Item");
b.Navigation("PriceAdjustment");
});
modelBuilder.Entity("ERPCore.Domain.Entities.ItemReorder", b =>
{
b.HasOne("ERPCore.Domain.Entities.Item", "Item")
@@ -7985,6 +8599,36 @@ namespace ERPCore.Migrations
b.Navigation("Warehouse");
});
modelBuilder.Entity("ERPCore.Domain.Entities.PriceAdjustment", b =>
{
b.HasOne("ERPCore.Domain.Entities.User", "Creator")
.WithMany()
.HasForeignKey("CreatedBy")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("Creator");
});
modelBuilder.Entity("ERPCore.Domain.Entities.PriceAdjustmentLine", b =>
{
b.HasOne("ERPCore.Domain.Entities.Item", "Item")
.WithMany()
.HasForeignKey("ItemId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.HasOne("ERPCore.Domain.Entities.PriceAdjustment", "PriceAdjustment")
.WithMany("Lines")
.HasForeignKey("PriceAdjustmentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Item");
b.Navigation("PriceAdjustment");
});
modelBuilder.Entity("ERPCore.Domain.Entities.ProductConfig", b =>
{
b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser")
@@ -9377,6 +10021,16 @@ namespace ERPCore.Migrations
b.Navigation("Lines");
});
modelBuilder.Entity("ERPCore.Domain.Entities.Expense", b =>
{
b.Navigation("Payments");
});
modelBuilder.Entity("ERPCore.Domain.Entities.ExpenseCategory", b =>
{
b.Navigation("Titles");
});
modelBuilder.Entity("ERPCore.Domain.Entities.Grn", b =>
{
b.Navigation("Lines");
@@ -9419,6 +10073,11 @@ namespace ERPCore.Migrations
b.Navigation("Lines");
});
modelBuilder.Entity("ERPCore.Domain.Entities.PriceAdjustment", b =>
{
b.Navigation("Lines");
});
modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b =>
{
b.Navigation("Edges");