diff --git a/Backend/ERPCore/Controllers/BranchConfigController.cs b/Backend/ERPCore/Controllers/BranchConfigController.cs index 8ea5430..945be2a 100644 --- a/Backend/ERPCore/Controllers/BranchConfigController.cs +++ b/Backend/ERPCore/Controllers/BranchConfigController.cs @@ -1,3 +1,5 @@ +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; using ERPCore.Dtos.Config; using ERPCore.Services.Interfaces; using Microsoft.AspNetCore.Mvc; @@ -14,6 +16,7 @@ namespace ERPCore.Controllers; /// /// [Route("api/v1/branch-config")] +[Authorize(Policy = NavPolicies.Prefix + "settings")] public sealed class BranchConfigController : ApiControllerBase { private readonly IBranchConfigService _config; diff --git a/Backend/ERPCore/Controllers/BrandsController.cs b/Backend/ERPCore/Controllers/BrandsController.cs index 7d4c5b3..014cd13 100644 --- a/Backend/ERPCore/Controllers/BrandsController.cs +++ b/Backend/ERPCore/Controllers/BrandsController.cs @@ -1,3 +1,5 @@ +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; using ERPCore.Domain.Enums; using ERPCore.Dtos.Brands; using ERPCore.Dtos.Common; @@ -8,6 +10,7 @@ namespace ERPCore.Controllers; /// Brand master endpoints (docs/11-BACKEND-PHASE1.md §2.6). [Route("api/v1/brands")] +[Authorize(Policy = NavPolicies.Prefix + "products")] public sealed class BrandsController : ApiControllerBase { private readonly IBrandService _brands; diff --git a/Backend/ERPCore/Controllers/BundleSalesController.cs b/Backend/ERPCore/Controllers/BundleSalesController.cs index d768c97..95ed07c 100644 --- a/Backend/ERPCore/Controllers/BundleSalesController.cs +++ b/Backend/ERPCore/Controllers/BundleSalesController.cs @@ -1,3 +1,5 @@ +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; using ERPCore.Domain.Enums; using ERPCore.Dtos.Common; using ERPCore.Dtos.Sales; @@ -7,6 +9,7 @@ using Microsoft.AspNetCore.Mvc; namespace ERPCore.Controllers; [Route("api/v1/bundle-sales")] +[Authorize(Policy = NavPolicies.Prefix + "sales")] public sealed class BundleSalesController : ApiControllerBase { private readonly IBundleSaleService _bundles; diff --git a/Backend/ERPCore/Controllers/CategoriesController.cs b/Backend/ERPCore/Controllers/CategoriesController.cs index 3fcd0e2..767b7de 100644 --- a/Backend/ERPCore/Controllers/CategoriesController.cs +++ b/Backend/ERPCore/Controllers/CategoriesController.cs @@ -1,3 +1,5 @@ +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; using ERPCore.Domain.Enums; using ERPCore.Dtos.Categories; using ERPCore.Dtos.Common; @@ -12,6 +14,7 @@ namespace ERPCore.Controllers; /// ?tree=true parameter is gone along with the self-nesting model. /// [Route("api/v1/categories")] +[Authorize(Policy = NavPolicies.Prefix + "products")] public sealed class CategoriesController : ApiControllerBase { private readonly ICategoryService _categories; diff --git a/Backend/ERPCore/Controllers/CustomersController.cs b/Backend/ERPCore/Controllers/CustomersController.cs index ff7cda4..e05bb54 100644 --- a/Backend/ERPCore/Controllers/CustomersController.cs +++ b/Backend/ERPCore/Controllers/CustomersController.cs @@ -1,3 +1,5 @@ +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; using ERPCore.Domain.Enums; using ERPCore.Dtos.Common; using ERPCore.Dtos.Customers; @@ -8,6 +10,7 @@ namespace ERPCore.Controllers; /// Customer master endpoints for Phase 1 sales. [Route("api/v1/customers")] +[Authorize(Policy = NavPolicies.Prefix + "sales")] public sealed class CustomersController : ApiControllerBase { private readonly ICustomerService _customers; diff --git a/Backend/ERPCore/Controllers/DashboardController.cs b/Backend/ERPCore/Controllers/DashboardController.cs index eeaf72d..a979c63 100644 --- a/Backend/ERPCore/Controllers/DashboardController.cs +++ b/Backend/ERPCore/Controllers/DashboardController.cs @@ -1,3 +1,5 @@ +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; using ERPCore.Dtos.Dashboard; using ERPCore.Services.Interfaces; using Microsoft.AspNetCore.Mvc; @@ -6,6 +8,7 @@ namespace ERPCore.Controllers; /// Dashboard overview stats — cross-domain counts, not a stored entity. [Route("api/v1/dashboard")] +[Authorize(Policy = NavPolicies.Prefix + "dashboard")] public sealed class DashboardController : ApiControllerBase { private readonly IDashboardService _dashboard; diff --git a/Backend/ERPCore/Controllers/FreeIssuesController.cs b/Backend/ERPCore/Controllers/FreeIssuesController.cs index 93057e8..9e9b6d8 100644 --- a/Backend/ERPCore/Controllers/FreeIssuesController.cs +++ b/Backend/ERPCore/Controllers/FreeIssuesController.cs @@ -1,3 +1,5 @@ +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; using ERPCore.Domain.Enums; using ERPCore.Dtos.Common; using ERPCore.Dtos.Sales; @@ -12,6 +14,7 @@ namespace ERPCore.Controllers; /// the existing sales-slip CRUD surface under a more business-friendly route. /// [Route("api/v1/free-issues")] +[Authorize(Policy = NavPolicies.Prefix + "sales")] public sealed class FreeIssuesController : ApiControllerBase { private readonly ISalesSlipService _slips; diff --git a/Backend/ERPCore/Controllers/GeneralLedgerController.cs b/Backend/ERPCore/Controllers/GeneralLedgerController.cs index 2f0bf12..837a942 100644 --- a/Backend/ERPCore/Controllers/GeneralLedgerController.cs +++ b/Backend/ERPCore/Controllers/GeneralLedgerController.cs @@ -1,3 +1,5 @@ +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; using ERPCore.Services.Interfaces; using Microsoft.AspNetCore.Mvc; @@ -14,6 +16,7 @@ namespace ERPCore.Controllers; /// only and is never exposed to the frontend. /// [Route("api/v1/gl")] +[Authorize(Policy = NavPolicies.Prefix + "ledgers")] public sealed class GeneralLedgerController : ApiControllerBase { private readonly IGeneralLedgerService _gl; diff --git a/Backend/ERPCore/Controllers/GrnsController.cs b/Backend/ERPCore/Controllers/GrnsController.cs index 1ba4861..3c45ea4 100644 --- a/Backend/ERPCore/Controllers/GrnsController.cs +++ b/Backend/ERPCore/Controllers/GrnsController.cs @@ -1,3 +1,5 @@ +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; using ERPCore.Domain.Enums; using ERPCore.Dtos.Common; using ERPCore.Dtos.Grn; @@ -8,6 +10,7 @@ namespace ERPCore.Controllers; /// Goods-receipt endpoints (docs/11 §4). [Route("api/v1/grns")] +[Authorize(Policy = NavPolicies.Prefix + "receiving")] public sealed class GrnsController : ApiControllerBase { private readonly IGrnService _grns; diff --git a/Backend/ERPCore/Controllers/Hrm/EmployeesController.cs b/Backend/ERPCore/Controllers/Hrm/EmployeesController.cs index bde2285..674744f 100644 --- a/Backend/ERPCore/Controllers/Hrm/EmployeesController.cs +++ b/Backend/ERPCore/Controllers/Hrm/EmployeesController.cs @@ -94,13 +94,13 @@ public sealed class EmployeesController : ApiControllerBase /// Permanently deletes the employee and all dependent HR records. Blocked (409) if payroll history exists. [HttpDelete("{employeeId:int}")] - [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(typeof(EmployeeDeleteResultDto), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status409Conflict)] - public async Task Delete(int employeeId, CancellationToken ct) + public async Task> Delete(int employeeId, [FromQuery] bool deleteUserAccount, CancellationToken ct) { - await _employees.DeleteAsync(employeeId, ct); - return NoContent(); + var result = await _employees.DeleteAsync(employeeId, deleteUserAccount, ct); + return Ok(result); } [HttpPost("{employeeId:int}/link-user")] diff --git a/Backend/ERPCore/Controllers/ItemTypesController.cs b/Backend/ERPCore/Controllers/ItemTypesController.cs index efbc4f7..a4457de 100644 --- a/Backend/ERPCore/Controllers/ItemTypesController.cs +++ b/Backend/ERPCore/Controllers/ItemTypesController.cs @@ -1,3 +1,5 @@ +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; using ERPCore.Domain.Enums; using ERPCore.Dtos.Common; using ERPCore.Dtos.ItemTypes; @@ -13,6 +15,7 @@ namespace ERPCore.Controllers; /// into the client-generated SKU (docs/10 Part C.9). /// [Route("api/v1/item-types")] +[Authorize(Policy = NavPolicies.Prefix + "products")] public sealed class ItemTypesController : ApiControllerBase { private readonly IItemTypeService _itemTypes; diff --git a/Backend/ERPCore/Controllers/ItemsController.cs b/Backend/ERPCore/Controllers/ItemsController.cs index f792529..5dcb584 100644 --- a/Backend/ERPCore/Controllers/ItemsController.cs +++ b/Backend/ERPCore/Controllers/ItemsController.cs @@ -1,3 +1,5 @@ +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; using ERPCore.Domain.Enums; using ERPCore.Dtos.Common; using ERPCore.Dtos.Items; @@ -8,6 +10,7 @@ namespace ERPCore.Controllers; /// Item master endpoints (docs/11-BACKEND-PHASE1.md §2.1–2.2). [Route("api/v1/items")] +[Authorize(Policy = NavPolicies.Prefix + "products")] public sealed class ItemsController : ApiControllerBase { private readonly IItemService _items; @@ -27,6 +30,17 @@ public sealed class ItemsController : ApiControllerBase CancellationToken ct) => Ok(await _items.ListAsync(query, status, categoryId, subCategoryId, brandId, trackingMode, ct)); + /// Barcode/RFID lookup — matches an item's barcode/SKU, or a batch/serial + /// barcode/no (optionally scoped to first). + [HttpGet("scan")] + [ProducesResponseType(typeof(ItemScanResultDto), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public async Task> Scan([FromQuery] string code, [FromQuery] int? itemId, CancellationToken ct) + { + var result = await _items.ScanAsync(code, itemId, ct); + return result is null ? NotFound() : Ok(result); + } + /// Get a single item; returns an ETag for optimistic concurrency. [HttpGet("{itemId:int}")] [ProducesResponseType(typeof(ItemDetailDto), StatusCodes.Status200OK)] diff --git a/Backend/ERPCore/Controllers/JournalEntriesController.cs b/Backend/ERPCore/Controllers/JournalEntriesController.cs index 54789c9..d999987 100644 --- a/Backend/ERPCore/Controllers/JournalEntriesController.cs +++ b/Backend/ERPCore/Controllers/JournalEntriesController.cs @@ -1,3 +1,5 @@ +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; using ERPCore.Dtos.Audit; using ERPCore.Dtos.Common; using ERPCore.Services.Interfaces; @@ -10,6 +12,7 @@ namespace ERPCore.Controllers; /// Data only — no posting in Phase 1. /// [Route("api/v1/journal-entries")] +[Authorize(Policy = NavPolicies.Prefix + "ledgers")] public sealed class JournalEntriesController : ApiControllerBase { private readonly IAuditService _audit; diff --git a/Backend/ERPCore/Controllers/NotificationConfigController.cs b/Backend/ERPCore/Controllers/NotificationConfigController.cs index 13b035b..95413cb 100644 --- a/Backend/ERPCore/Controllers/NotificationConfigController.cs +++ b/Backend/ERPCore/Controllers/NotificationConfigController.cs @@ -1,3 +1,5 @@ +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; using ERPCore.Dtos.Notifications; using ERPCore.Services.Interfaces; using Microsoft.AspNetCore.Mvc; @@ -5,6 +7,7 @@ using Microsoft.AspNetCore.Mvc; namespace ERPCore.Controllers; [Route("api/v1/notification-config")] +[Authorize(Policy = NavPolicies.Prefix + "settings")] public sealed class NotificationConfigController : ApiControllerBase { private readonly INotificationConfigService _config; diff --git a/Backend/ERPCore/Controllers/NotificationsController.cs b/Backend/ERPCore/Controllers/NotificationsController.cs new file mode 100644 index 0000000..73b1ae9 --- /dev/null +++ b/Backend/ERPCore/Controllers/NotificationsController.cs @@ -0,0 +1,32 @@ +using ERPCore.Infra.Auth; +using ERPCore.Services.Interfaces; +using Microsoft.AspNetCore.Mvc; + +namespace ERPCore.Controllers; + +[Route("api/v1/notifications")] +public sealed class NotificationsController : ApiControllerBase +{ + private readonly INotificationService _notifications; + private readonly ICurrentUser _currentUser; + + public NotificationsController(INotificationService notifications, ICurrentUser currentUser) + { + _notifications = notifications; + _currentUser = currentUser; + } + + [HttpGet] + public async Task Get([FromQuery] int take = 20, CancellationToken ct = default) + { + var feed = await _notifications.GetFeedAsync(_currentUser.AuditUserId, take, ct); + return Ok(feed); + } + + [HttpPost("mark-all-read")] + public async Task MarkAllRead(CancellationToken ct) + { + await _notifications.MarkAllReadAsync(_currentUser.AuditUserId, ct); + return NoContent(); + } +} diff --git a/Backend/ERPCore/Controllers/ProductConfigController.cs b/Backend/ERPCore/Controllers/ProductConfigController.cs index 300f446..e20261a 100644 --- a/Backend/ERPCore/Controllers/ProductConfigController.cs +++ b/Backend/ERPCore/Controllers/ProductConfigController.cs @@ -1,3 +1,5 @@ +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; using ERPCore.Dtos.Config; using ERPCore.Services.Interfaces; using Microsoft.AspNetCore.Mvc; @@ -16,6 +18,7 @@ namespace ERPCore.Controllers; /// /// [Route("api/v1/product-config")] +[Authorize(Policy = NavPolicies.Prefix + "products")] public sealed class ProductConfigController : ApiControllerBase { private readonly IProductConfigService _config; diff --git a/Backend/ERPCore/Controllers/ProductionRunsController.cs b/Backend/ERPCore/Controllers/ProductionRunsController.cs index 3937f86..97c41f5 100644 --- a/Backend/ERPCore/Controllers/ProductionRunsController.cs +++ b/Backend/ERPCore/Controllers/ProductionRunsController.cs @@ -1,3 +1,5 @@ +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; using ERPCore.Domain.Enums; using ERPCore.Dtos.Common; using ERPCore.Dtos.Production; @@ -8,6 +10,7 @@ namespace ERPCore.Controllers; /// Production run endpoints (docs/30-BACKEND-PHASE2.md §D.2–D.3). [Route("api/v1/production-runs")] +[Authorize(Policy = NavPolicies.Prefix + "production")] public sealed class ProductionRunsController : ApiControllerBase { private readonly IProductionRunService _runs; diff --git a/Backend/ERPCore/Controllers/ProductionTemplatesController.cs b/Backend/ERPCore/Controllers/ProductionTemplatesController.cs index c637741..9333ae4 100644 --- a/Backend/ERPCore/Controllers/ProductionTemplatesController.cs +++ b/Backend/ERPCore/Controllers/ProductionTemplatesController.cs @@ -1,3 +1,5 @@ +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; using ERPCore.Domain.Enums; using ERPCore.Dtos.Common; using ERPCore.Dtos.Production; @@ -8,6 +10,7 @@ namespace ERPCore.Controllers; /// Production template endpoints (docs/30-BACKEND-PHASE2.md §D.1). [Route("api/v1/production-templates")] +[Authorize(Policy = NavPolicies.Prefix + "production")] public sealed class ProductionTemplatesController : ApiControllerBase { private readonly IProductionTemplateService _templates; diff --git a/Backend/ERPCore/Controllers/PurchaseInvoicesController.cs b/Backend/ERPCore/Controllers/PurchaseInvoicesController.cs index 35a8696..3561463 100644 --- a/Backend/ERPCore/Controllers/PurchaseInvoicesController.cs +++ b/Backend/ERPCore/Controllers/PurchaseInvoicesController.cs @@ -1,3 +1,5 @@ +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; using ERPCore.Domain.Enums; using ERPCore.Dtos.Common; using ERPCore.Dtos.Grn; @@ -9,6 +11,7 @@ namespace ERPCore.Controllers; /// Purchase invoice endpoints — vendor invoices consolidating Confirmed GRNs. [Route("api/v1/purchase-invoices")] +[Authorize(Policy = NavPolicies.Prefix + "procurement")] public sealed class PurchaseInvoicesController : ApiControllerBase { private readonly IPurchaseInvoiceService _invoices; diff --git a/Backend/ERPCore/Controllers/PurchaseOrdersController.cs b/Backend/ERPCore/Controllers/PurchaseOrdersController.cs index ff9dc71..3d674e6 100644 --- a/Backend/ERPCore/Controllers/PurchaseOrdersController.cs +++ b/Backend/ERPCore/Controllers/PurchaseOrdersController.cs @@ -1,3 +1,5 @@ +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; using ERPCore.Domain.Enums; using ERPCore.Dtos.Common; using ERPCore.Dtos.Procurement; @@ -8,6 +10,7 @@ namespace ERPCore.Controllers; /// Purchase-order endpoints (docs/11 §3.3). [Route("api/v1/purchase-orders")] +[Authorize(Policy = NavPolicies.Prefix + "procurement")] public sealed class PurchaseOrdersController : ApiControllerBase { private readonly IPurchaseOrderService _pos; @@ -32,7 +35,7 @@ public sealed class PurchaseOrdersController : ApiControllerBase return Ok(result.Value); } - /// Create a PO — auto-approved on creation in Phase 1 (FR-PROC-04). Totals computed server-side. + /// Create a PO — non-draft is issued straight into PendingApproval (FR-PROC-04). Totals computed server-side. [HttpPost] [ProducesResponseType(typeof(PurchaseOrderDto), StatusCodes.Status201Created)] [ProducesResponseType(StatusCodes.Status422UnprocessableEntity)] @@ -57,7 +60,7 @@ public sealed class PurchaseOrdersController : ApiControllerBase return Ok(result.Value); } - /// Submit a Draft PO (Draft → Approved). 409 PO_NOT_EDITABLE if not Draft. + /// Submit a Draft PO (Draft → PendingApproval). 409 PO_NOT_EDITABLE if not Draft. [HttpPost("{poId:int}/submit")] [ProducesResponseType(typeof(PurchaseOrderDto), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] @@ -67,6 +70,7 @@ public sealed class PurchaseOrdersController : ApiControllerBase /// Delete a PO — permitted only while Draft (409 PO_NOT_EDITABLE otherwise). [HttpDelete("{poId:int}")] + [Authorize(Policy = NavPolicies.Prefix + "procurement" + NavPolicies.ActionSeparator + NavPolicies.DeleteAction)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status409Conflict)] @@ -76,13 +80,28 @@ public sealed class PurchaseOrdersController : ApiControllerBase return NoContent(); } - /// Approve — no-op in Phase 1 (POs auto-approve); transitions PendingApproval→Approved when enabled. + /// Approve — PendingApproval → Approved. 403 PO_APPROVAL_FORBIDDEN if the caller + /// isn't an Admin or is the PO's own creator; 409 PO_NOT_PENDING_APPROVAL otherwise. [HttpPost("{poId:int}/approve")] + [Authorize(Policy = NavPolicies.Prefix + "procurement" + NavPolicies.ActionSeparator + NavPolicies.ApproveAction)] [ProducesResponseType(typeof(PurchaseOrderDto), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status409Conflict)] public async Task> Approve(int poId, CancellationToken ct) => Ok(await _pos.ApproveAsync(poId, ct)); + /// Reject — PendingApproval → Draft, so the requester can revise and resubmit. + /// Same caller restrictions as . + [HttpPost("{poId:int}/reject")] + [Authorize(Policy = NavPolicies.Prefix + "procurement" + NavPolicies.ActionSeparator + NavPolicies.ApproveAction)] + [ProducesResponseType(typeof(PurchaseOrderDto), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status403Forbidden)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status409Conflict)] + public async Task> Reject(int poId, [FromBody] RejectPurchaseOrderRequest request, CancellationToken ct) + => Ok(await _pos.RejectAsync(poId, request.Reason, ct)); + /// Cancel — 409 if any goods have been received against the PO. [HttpPost("{poId:int}/cancel")] [ProducesResponseType(typeof(PurchaseOrderDto), StatusCodes.Status200OK)] diff --git a/Backend/ERPCore/Controllers/PurchaseReturnsController.cs b/Backend/ERPCore/Controllers/PurchaseReturnsController.cs index 40ce9a2..2b634cf 100644 --- a/Backend/ERPCore/Controllers/PurchaseReturnsController.cs +++ b/Backend/ERPCore/Controllers/PurchaseReturnsController.cs @@ -1,3 +1,5 @@ +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; using ERPCore.Dtos.Common; using ERPCore.Dtos.Procurement; using ERPCore.Services.Interfaces; @@ -7,6 +9,7 @@ namespace ERPCore.Controllers; /// Purchase-return endpoints (docs/11 §3.4). [Route("api/v1/purchase-returns")] +[Authorize(Policy = NavPolicies.Prefix + "procurement")] public sealed class PurchaseReturnsController : ApiControllerBase { private readonly IPurchaseReturnService _returns; diff --git a/Backend/ERPCore/Controllers/RequisitionsController.cs b/Backend/ERPCore/Controllers/RequisitionsController.cs index e16d2e1..439c869 100644 --- a/Backend/ERPCore/Controllers/RequisitionsController.cs +++ b/Backend/ERPCore/Controllers/RequisitionsController.cs @@ -1,3 +1,5 @@ +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; using ERPCore.Domain.Enums; using ERPCore.Dtos.Common; using ERPCore.Dtos.Procurement; @@ -8,6 +10,7 @@ namespace ERPCore.Controllers; /// Purchase-requisition endpoints (docs/11 §3.1). [Route("api/v1/requisitions")] +[Authorize(Policy = NavPolicies.Prefix + "procurement")] public sealed class RequisitionsController : ApiControllerBase { private readonly IRequisitionService _requisitions; diff --git a/Backend/ERPCore/Controllers/RfqsController.cs b/Backend/ERPCore/Controllers/RfqsController.cs index c917479..92715a5 100644 --- a/Backend/ERPCore/Controllers/RfqsController.cs +++ b/Backend/ERPCore/Controllers/RfqsController.cs @@ -1,3 +1,5 @@ +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; using ERPCore.Domain.Enums; using ERPCore.Dtos.Common; using ERPCore.Dtos.Procurement; @@ -8,6 +10,7 @@ namespace ERPCore.Controllers; /// RFQ & quotation endpoints (docs/11 §3.2). [Route("api/v1/rfqs")] +[Authorize(Policy = NavPolicies.Prefix + "procurement")] public sealed class RfqsController : ApiControllerBase { private readonly IRfqService _rfqs; diff --git a/Backend/ERPCore/Controllers/RolesController.cs b/Backend/ERPCore/Controllers/RolesController.cs index 69db895..5a2c374 100644 --- a/Backend/ERPCore/Controllers/RolesController.cs +++ b/Backend/ERPCore/Controllers/RolesController.cs @@ -1,3 +1,5 @@ +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; using ERPCore.Domain.Enums; using ERPCore.Dtos.Common; using ERPCore.Dtos.Rbac; @@ -8,6 +10,7 @@ namespace ERPCore.Controllers; /// Role CRUD + permission assignment (mirrors AuthHex's Role; see docs/10 C.9). [Route("api/v1/roles")] +[Authorize(Policy = NavPolicies.Prefix + "settings")] public sealed class RolesController : ApiControllerBase { private readonly IRoleService _roles; @@ -64,6 +67,7 @@ public sealed class RolesController : ApiControllerBase } [HttpDelete("{roleId:int}")] + [Authorize(Policy = NavPolicies.Prefix + "settings" + NavPolicies.ActionSeparator + NavPolicies.DeleteAction)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status409Conflict)] diff --git a/Backend/ERPCore/Controllers/SalesDayEndController.cs b/Backend/ERPCore/Controllers/SalesDayEndController.cs index 4695c04..c2653bc 100644 --- a/Backend/ERPCore/Controllers/SalesDayEndController.cs +++ b/Backend/ERPCore/Controllers/SalesDayEndController.cs @@ -1,3 +1,5 @@ +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; using ERPCore.Dtos.Common; using ERPCore.Dtos.Sales; using ERPCore.Services.Interfaces; @@ -8,6 +10,7 @@ namespace ERPCore.Controllers; /// Cashier day-end close-out — locks a cashier's Posted sales slips for a business /// date and posts one consolidated GL journal entry for the day (docs/14 Sales API). [Route("api/v1/sales-day-end")] +[Authorize(Policy = NavPolicies.Prefix + "sales")] public sealed class SalesDayEndController : ApiControllerBase { private readonly ISalesDayEndService _dayEnds; diff --git a/Backend/ERPCore/Controllers/SalesInvoicesController.cs b/Backend/ERPCore/Controllers/SalesInvoicesController.cs index 3720f0d..c1f524b 100644 --- a/Backend/ERPCore/Controllers/SalesInvoicesController.cs +++ b/Backend/ERPCore/Controllers/SalesInvoicesController.cs @@ -1,3 +1,5 @@ +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; using ERPCore.Domain.Enums; using ERPCore.Dtos.Common; using ERPCore.Dtos.Sales; @@ -7,6 +9,7 @@ using Microsoft.AspNetCore.Mvc; namespace ERPCore.Controllers; [Route("api/v1/sales-invoices")] +[Authorize(Policy = NavPolicies.Prefix + "sales")] public sealed class SalesInvoicesController : ApiControllerBase { private readonly ISalesInvoiceService _invoices; diff --git a/Backend/ERPCore/Controllers/SalesReportsController.cs b/Backend/ERPCore/Controllers/SalesReportsController.cs index b6f18c7..9e35bd6 100644 --- a/Backend/ERPCore/Controllers/SalesReportsController.cs +++ b/Backend/ERPCore/Controllers/SalesReportsController.cs @@ -1,3 +1,5 @@ +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; using ERPCore.Dtos.Sales; using ERPCore.Services.Interfaces; using Microsoft.AspNetCore.Mvc; @@ -5,6 +7,7 @@ using Microsoft.AspNetCore.Mvc; namespace ERPCore.Controllers; [Route("api/v1/reports/sales")] +[Authorize(Policy = NavPolicies.Prefix + "sales")] public sealed class SalesReportsController : ApiControllerBase { private readonly ISalesReportService _reports; diff --git a/Backend/ERPCore/Controllers/SalesReturnsController.cs b/Backend/ERPCore/Controllers/SalesReturnsController.cs index a550da6..7135dbc 100644 --- a/Backend/ERPCore/Controllers/SalesReturnsController.cs +++ b/Backend/ERPCore/Controllers/SalesReturnsController.cs @@ -1,3 +1,5 @@ +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; using ERPCore.Dtos.Common; using ERPCore.Dtos.Sales; using ERPCore.Services.Interfaces; @@ -7,6 +9,7 @@ namespace ERPCore.Controllers; /// Sales-return endpoints — customer returns of previously sold goods. [Route("api/v1/sales-returns")] +[Authorize(Policy = NavPolicies.Prefix + "sales")] public sealed class SalesReturnsController : ApiControllerBase { private readonly ISalesReturnService _returns; diff --git a/Backend/ERPCore/Controllers/SalesSlipPromotionsController.cs b/Backend/ERPCore/Controllers/SalesSlipPromotionsController.cs index f5874dc..bc742c6 100644 --- a/Backend/ERPCore/Controllers/SalesSlipPromotionsController.cs +++ b/Backend/ERPCore/Controllers/SalesSlipPromotionsController.cs @@ -1,3 +1,5 @@ +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; using ERPCore.Dtos.Sales; using ERPCore.Services.Interfaces; using Microsoft.AspNetCore.Mvc; @@ -5,6 +7,7 @@ using Microsoft.AspNetCore.Mvc; namespace ERPCore.Controllers; [Route("api/v1/sales-slips/{salesSlipId:int}/free-issue-suggestions")] +[Authorize(Policy = NavPolicies.Prefix + "sales")] public sealed class SalesSlipPromotionsController : ApiControllerBase { private readonly ISalesPromotionSuggestionService _suggestions; diff --git a/Backend/ERPCore/Controllers/SalesSlipsController.cs b/Backend/ERPCore/Controllers/SalesSlipsController.cs index a59f93e..66eac99 100644 --- a/Backend/ERPCore/Controllers/SalesSlipsController.cs +++ b/Backend/ERPCore/Controllers/SalesSlipsController.cs @@ -1,3 +1,5 @@ +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; using ERPCore.Domain.Enums; using ERPCore.Dtos.Common; using ERPCore.Dtos.Sales; @@ -7,6 +9,7 @@ using Microsoft.AspNetCore.Mvc; namespace ERPCore.Controllers; [Route("api/v1/sales-slips")] +[Authorize(Policy = NavPolicies.Prefix + "sales")] public sealed class SalesSlipsController : ApiControllerBase { private readonly ISalesSlipService _slips; diff --git a/Backend/ERPCore/Controllers/SearchController.cs b/Backend/ERPCore/Controllers/SearchController.cs new file mode 100644 index 0000000..4538352 --- /dev/null +++ b/Backend/ERPCore/Controllers/SearchController.cs @@ -0,0 +1,20 @@ +using ERPCore.Dtos.Search; +using ERPCore.Services.Interfaces; +using Microsoft.AspNetCore.Mvc; + +namespace ERPCore.Controllers; + +[Route("api/v1/search")] +public sealed class SearchController : ApiControllerBase +{ + private readonly IGlobalSearchService _search; + + public SearchController(IGlobalSearchService search) => _search = search; + + [HttpGet] + public async Task>> Get([FromQuery] string q, CancellationToken ct) + { + var results = await _search.SearchAsync(q, 6, ct); + return Ok(results); + } +} diff --git a/Backend/ERPCore/Controllers/StockAdjustmentsController.cs b/Backend/ERPCore/Controllers/StockAdjustmentsController.cs index f8a1b52..1b10b37 100644 --- a/Backend/ERPCore/Controllers/StockAdjustmentsController.cs +++ b/Backend/ERPCore/Controllers/StockAdjustmentsController.cs @@ -1,3 +1,5 @@ +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; using ERPCore.Dtos.Common; using ERPCore.Dtos.Stock; using ERPCore.Services.Interfaces; @@ -7,6 +9,7 @@ namespace ERPCore.Controllers; /// Stock-adjustment endpoints (docs/11 §5.5). [Route("api/v1/stock-adjustments")] +[Authorize(Policy = NavPolicies.Prefix + "stock")] public sealed class StockAdjustmentsController : ApiControllerBase { private readonly IAdjustmentService _adjustments; diff --git a/Backend/ERPCore/Controllers/StockController.cs b/Backend/ERPCore/Controllers/StockController.cs index 609ac08..7e4436a 100644 --- a/Backend/ERPCore/Controllers/StockController.cs +++ b/Backend/ERPCore/Controllers/StockController.cs @@ -1,3 +1,5 @@ +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; using ERPCore.Dtos.Common; using ERPCore.Dtos.Procurement; using ERPCore.Dtos.Stock; @@ -8,6 +10,7 @@ namespace ERPCore.Controllers; /// Stock enquiry, ledger, valuation and reorder-alert endpoints (docs/11 §5.1–5.3, §5.7). [Route("api/v1/stock")] +[Authorize(Policy = NavPolicies.Prefix + "stock")] public sealed class StockController : ApiControllerBase { private readonly IStockService _stock; diff --git a/Backend/ERPCore/Controllers/StockCountsController.cs b/Backend/ERPCore/Controllers/StockCountsController.cs index 3802f1f..b0fee7b 100644 --- a/Backend/ERPCore/Controllers/StockCountsController.cs +++ b/Backend/ERPCore/Controllers/StockCountsController.cs @@ -1,3 +1,5 @@ +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; using ERPCore.Domain.Enums; using ERPCore.Dtos.Common; using ERPCore.Dtos.Stock; @@ -8,6 +10,7 @@ namespace ERPCore.Controllers; /// Stock-count endpoints (docs/11 §5.6). [Route("api/v1/stock-counts")] +[Authorize(Policy = NavPolicies.Prefix + "stock")] public sealed class StockCountsController : ApiControllerBase { private readonly ICountService _counts; diff --git a/Backend/ERPCore/Controllers/StockTransfersController.cs b/Backend/ERPCore/Controllers/StockTransfersController.cs index 67d9525..a5767fa 100644 --- a/Backend/ERPCore/Controllers/StockTransfersController.cs +++ b/Backend/ERPCore/Controllers/StockTransfersController.cs @@ -1,3 +1,5 @@ +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; using ERPCore.Domain.Enums; using ERPCore.Dtos.Common; using ERPCore.Dtos.Stock; @@ -8,6 +10,7 @@ namespace ERPCore.Controllers; /// Stock-transfer endpoints (docs/11 §5.4). [Route("api/v1/stock-transfers")] +[Authorize(Policy = NavPolicies.Prefix + "stock")] public sealed class StockTransfersController : ApiControllerBase { private readonly ITransferService _transfers; diff --git a/Backend/ERPCore/Controllers/SubCategoriesController.cs b/Backend/ERPCore/Controllers/SubCategoriesController.cs index 162a89e..985a668 100644 --- a/Backend/ERPCore/Controllers/SubCategoriesController.cs +++ b/Backend/ERPCore/Controllers/SubCategoriesController.cs @@ -1,3 +1,5 @@ +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; using ERPCore.Dtos.Categories; using ERPCore.Services.Interfaces; using Microsoft.AspNetCore.Mvc; @@ -10,6 +12,7 @@ namespace ERPCore.Controllers; /// since a subcategory only exists in the context of one. /// [Route("api/v1/subcategories")] +[Authorize(Policy = NavPolicies.Prefix + "products")] public sealed class SubCategoriesController : ApiControllerBase { private readonly ICategoryService _categories; diff --git a/Backend/ERPCore/Controllers/SupportTicketsController.cs b/Backend/ERPCore/Controllers/SupportTicketsController.cs new file mode 100644 index 0000000..91f5211 --- /dev/null +++ b/Backend/ERPCore/Controllers/SupportTicketsController.cs @@ -0,0 +1,70 @@ +using ERPCore.Dtos.Support; +using ERPCore.Infra.Auth; +using ERPCore.Services.Interfaces; +using Microsoft.AspNetCore.Mvc; + +namespace ERPCore.Controllers; + +[Route("api/v1/support-tickets")] +public sealed class SupportTicketsController : ApiControllerBase +{ + private readonly ISupportTicketService _tickets; + private readonly ICurrentUser _currentUser; + + public SupportTicketsController(ISupportTicketService tickets, ICurrentUser currentUser) + { + _tickets = tickets; + _currentUser = currentUser; + } + + [HttpPost] + [ProducesResponseType(typeof(SupportTicketDto), StatusCodes.Status201Created)] + public async Task> Create([FromBody] CreateSupportTicketRequest request, CancellationToken ct) + { + var result = await _tickets.CreateAsync(_currentUser.AuditUserId, request, ct); + SetETag(result.RowVersion); + return CreatedAtAction(nameof(GetById), new { id = result.Value.TicketId }, result.Value); + } + + [HttpGet] + [ProducesResponseType(typeof(IReadOnlyList), StatusCodes.Status200OK)] + public async Task>> GetList(CancellationToken ct) + { + var list = await _tickets.GetListAsync(_currentUser.AuditUserId, _currentUser.IsAdmin, ct); + return Ok(list); + } + + [HttpGet("{id:int}")] + [ProducesResponseType(typeof(SupportTicketDto), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public async Task> GetById(int id, CancellationToken ct) + { + var result = await _tickets.GetByIdAsync(id, _currentUser.AuditUserId, _currentUser.IsAdmin, ct); + SetETag(result.RowVersion); + return Ok(result.Value); + } + + [HttpPost("{id:int}/messages")] + [ProducesResponseType(typeof(SupportTicketDto), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status412PreconditionFailed)] + public async Task> AddMessage(int id, [FromBody] AddSupportTicketMessageRequest request, CancellationToken ct) + { + var expected = RequireIfMatch(); + var result = await _tickets.AddMessageAsync(id, _currentUser.AuditUserId, _currentUser.IsAdmin, request, expected, ct); + SetETag(result.RowVersion); + return Ok(result.Value); + } + + [HttpPut("{id:int}/status")] + [ProducesResponseType(typeof(SupportTicketDto), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status412PreconditionFailed)] + public async Task> UpdateStatus(int id, [FromBody] UpdateSupportTicketStatusRequest request, CancellationToken ct) + { + var expected = RequireIfMatch(); + var result = await _tickets.UpdateStatusAsync(id, _currentUser.AuditUserId, _currentUser.IsAdmin, request, expected, ct); + SetETag(result.RowVersion); + return Ok(result.Value); + } +} diff --git a/Backend/ERPCore/Controllers/TaxRatesController.cs b/Backend/ERPCore/Controllers/TaxRatesController.cs new file mode 100644 index 0000000..56fa62f --- /dev/null +++ b/Backend/ERPCore/Controllers/TaxRatesController.cs @@ -0,0 +1,70 @@ +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; +using ERPCore.Domain.Enums; +using ERPCore.Dtos.Common; +using ERPCore.Dtos.TaxRates; +using ERPCore.Services.Interfaces; +using Microsoft.AspNetCore.Mvc; + +namespace ERPCore.Controllers; + +/// Tax rate master endpoints — see . +[Route("api/v1/tax-rates")] +[Authorize(Policy = NavPolicies.Prefix + "products")] +public sealed class TaxRatesController : ApiControllerBase +{ + private readonly ITaxRateService _taxRates; + + public TaxRatesController(ITaxRateService taxRates) => _taxRates = taxRates; + + [HttpGet] + [ProducesResponseType(typeof(PagedResponse), StatusCodes.Status200OK)] + public async Task>> List( + [FromQuery] PageQuery query, [FromQuery] EntityStatus? status, CancellationToken ct) + => Ok(await _taxRates.ListAsync(query, status, ct)); + + [HttpGet("{taxRateId:int}")] + [ProducesResponseType(typeof(TaxRateDto), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public async Task> GetById(int taxRateId, CancellationToken ct) + { + var result = await _taxRates.GetAsync(taxRateId, ct); + if (result is null) return NotFound(); + + SetETag(result.RowVersion); + return Ok(result.Value); + } + + [HttpPost] + [ProducesResponseType(typeof(TaxRateDto), StatusCodes.Status201Created)] + [ProducesResponseType(StatusCodes.Status409Conflict)] + public async Task> Create([FromBody] CreateTaxRateRequest request, CancellationToken ct) + { + var result = await _taxRates.CreateAsync(request, ct); + SetETag(result.RowVersion); + return Created($"/api/v1/tax-rates/{result.Value.TaxRateId}", result.Value); + } + + [HttpPut("{taxRateId:int}")] + [ProducesResponseType(typeof(TaxRateDto), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status409Conflict)] + [ProducesResponseType(StatusCodes.Status412PreconditionFailed)] + public async Task> Update(int taxRateId, [FromBody] UpdateTaxRateRequest request, CancellationToken ct) + { + var expected = RequireIfMatch(); + var result = await _taxRates.UpdateAsync(taxRateId, request, expected, ct); + SetETag(result.RowVersion); + return Ok(result.Value); + } + + /// Deactivate/reactivate. Masters are never hard-deleted (FR-MD-08). + [HttpPatch("{taxRateId:int}/status")] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public async Task SetStatus(int taxRateId, [FromBody] UpdateTaxRateStatusRequest request, CancellationToken ct) + { + await _taxRates.SetStatusAsync(taxRateId, request.Status, ct); + return NoContent(); + } +} diff --git a/Backend/ERPCore/Controllers/UomsController.cs b/Backend/ERPCore/Controllers/UomsController.cs index 55219dc..85193fb 100644 --- a/Backend/ERPCore/Controllers/UomsController.cs +++ b/Backend/ERPCore/Controllers/UomsController.cs @@ -1,3 +1,6 @@ +using ERPCore.Domain.Enums; +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; using ERPCore.Dtos.Common; using ERPCore.Dtos.Uoms; using ERPCore.Services.Interfaces; @@ -7,6 +10,7 @@ namespace ERPCore.Controllers; /// Unit-of-measure endpoints (docs/11-BACKEND-PHASE1.md §2.2). [Route("api/v1/uoms")] +[Authorize(Policy = NavPolicies.Prefix + "products")] public sealed class UomsController : ApiControllerBase { private readonly IUomService _uoms; @@ -15,8 +19,9 @@ public sealed class UomsController : ApiControllerBase [HttpGet] [ProducesResponseType(typeof(PagedResponse), StatusCodes.Status200OK)] - public async Task>> List([FromQuery] PageQuery query, CancellationToken ct) - => Ok(await _uoms.ListAsync(query, ct)); + public async Task>> List( + [FromQuery] PageQuery query, [FromQuery] EntityStatus? status, CancellationToken ct) + => Ok(await _uoms.ListAsync(query, status, ct)); [HttpPost] [ProducesResponseType(typeof(UomDto), StatusCodes.Status201Created)] @@ -26,4 +31,14 @@ public sealed class UomsController : ApiControllerBase var dto = await _uoms.CreateAsync(request, ct); return Created($"/api/v1/uoms/{dto.UomId}", dto); } + + /// Deactivate/reactivate. Masters are never hard-deleted (FR-MD-08). + [HttpPatch("{uomId:int}/status")] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public async Task SetStatus(int uomId, [FromBody] UpdateUomStatusRequest request, CancellationToken ct) + { + await _uoms.SetStatusAsync(uomId, request.Status, ct); + return NoContent(); + } } diff --git a/Backend/ERPCore/Controllers/UsersController.cs b/Backend/ERPCore/Controllers/UsersController.cs index e71bf7d..171157a 100644 --- a/Backend/ERPCore/Controllers/UsersController.cs +++ b/Backend/ERPCore/Controllers/UsersController.cs @@ -1,10 +1,13 @@ +using Microsoft.AspNetCore.Authorization; using ERPCore.Domain.Enums; using ERPCore.Dtos.Audit; +using ERPCore.Dtos.Auth; using ERPCore.Dtos.Common; using ERPCore.Dtos.Hrm; using ERPCore.Dtos.Users; using ERPCore.Infra.Auth; using ERPCore.Services.Interfaces; +using ERPCore.System.Errors; using Microsoft.AspNetCore.Mvc; namespace ERPCore.Controllers; @@ -14,6 +17,7 @@ namespace ERPCore.Controllers; /// account creation orchestrated against AuthHex (see ). /// [Route("api/v1/users")] +[Authorize(Policy = NavPolicies.Prefix + "settings")] public sealed class UsersController : ApiControllerBase { private readonly IUserManagementService _users; @@ -83,4 +87,20 @@ public sealed class UsersController : ApiControllerBase [ProducesResponseType(typeof(PagedResponse), StatusCodes.Status200OK)] public async Task>> ListLoginDevices(int userId, [FromQuery] PageQuery query, CancellationToken ct) => Ok(await _audit.ListLoginDevicesAsync(userId, query, ct)); + + /// + /// Admin-only escape hatch: permanently deletes a stale AuthHex identity (by email/mobile/NIC/ + /// username) that is blocking new registrations. Does not touch ERPCore's own `users` table. + /// See . + /// + [HttpPost("purge-authhex-identity")] + [ProducesResponseType(typeof(DeleteAuthHexUserResult), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status403Forbidden)] + public async Task> PurgeAuthHexIdentity([FromBody] PurgeAuthHexIdentityRequest request, CancellationToken ct) + { + if (!_currentUser.IsAdmin) + throw new DomainException("FORBIDDEN", "Only an administrator can purge an AuthHex identity.", 403); + + return Ok(await _users.PurgeAuthHexIdentityAsync(request, ct)); + } } diff --git a/Backend/ERPCore/Controllers/VendorsController.cs b/Backend/ERPCore/Controllers/VendorsController.cs index ee1021d..29f3175 100644 --- a/Backend/ERPCore/Controllers/VendorsController.cs +++ b/Backend/ERPCore/Controllers/VendorsController.cs @@ -1,3 +1,5 @@ +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; using ERPCore.Domain.Enums; using ERPCore.Dtos.Common; using ERPCore.Dtos.Vendors; @@ -8,6 +10,7 @@ namespace ERPCore.Controllers; /// Vendor master endpoints (docs/11-BACKEND-PHASE1.md §2.4). [Route("api/v1/vendors")] +[Authorize(Policy = NavPolicies.Prefix + "vendors")] public sealed class VendorsController : ApiControllerBase { private readonly IVendorService _vendors; diff --git a/Backend/ERPCore/Controllers/WarehousesController.cs b/Backend/ERPCore/Controllers/WarehousesController.cs index 939bc94..9a6bf93 100644 --- a/Backend/ERPCore/Controllers/WarehousesController.cs +++ b/Backend/ERPCore/Controllers/WarehousesController.cs @@ -1,3 +1,5 @@ +using Microsoft.AspNetCore.Authorization; +using ERPCore.Infra.Auth; using ERPCore.Dtos.Common; using ERPCore.Dtos.Warehouses; using ERPCore.Services.Interfaces; @@ -7,6 +9,7 @@ namespace ERPCore.Controllers; /// Warehouse & bin endpoints (docs/11-BACKEND-PHASE1.md §2.5). [Route("api/v1/warehouses")] +[Authorize(Policy = NavPolicies.Prefix + "warehouses")] public sealed class WarehousesController : ApiControllerBase { private readonly IWarehouseService _warehouses; @@ -37,6 +40,24 @@ public sealed class WarehousesController : ApiControllerBase return Created($"/api/v1/warehouses/{dto.WarehouseId}", dto); } + [HttpPut("{warehouseId:int}")] + [ProducesResponseType(typeof(WarehouseDto), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status409Conflict)] + public async Task> Update(int warehouseId, [FromBody] UpdateWarehouseRequest request, CancellationToken ct) + => Ok(await _warehouses.UpdateAsync(warehouseId, request, ct)); + + [HttpDelete("{warehouseId:int}")] + [Authorize(Policy = NavPolicies.Prefix + "warehouses" + NavPolicies.ActionSeparator + NavPolicies.DeleteAction)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status409Conflict)] + public async Task Delete(int warehouseId, CancellationToken ct) + { + await _warehouses.DeleteAsync(warehouseId, ct); + return NoContent(); + } + [HttpGet("{warehouseId:int}/bins")] [ProducesResponseType(typeof(IReadOnlyList), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] diff --git a/Backend/ERPCore/Domain/Entities/Batch.cs b/Backend/ERPCore/Domain/Entities/Batch.cs index 03ba570..41b1aea 100644 --- a/Backend/ERPCore/Domain/Entities/Batch.cs +++ b/Backend/ERPCore/Domain/Entities/Batch.cs @@ -13,4 +13,7 @@ public class Batch public string BatchNo { get; set; } = string.Empty; public DateOnly? ExpiryDate { get; set; } + + /// Optional scan code for barcode/RFID lookup (unique when set). + public string? Barcode { get; set; } } diff --git a/Backend/ERPCore/Domain/Entities/BranchConfig.cs b/Backend/ERPCore/Domain/Entities/BranchConfig.cs index 37d83c0..7fb2cee 100644 --- a/Backend/ERPCore/Domain/Entities/BranchConfig.cs +++ b/Backend/ERPCore/Domain/Entities/BranchConfig.cs @@ -17,6 +17,12 @@ public class BranchConfig public bool BranchingEnabled { get; set; } = true; + /// Independent sub-toggle: when the global is on + /// but this is off, Warehouses stop asking for/showing a branch while Employees etc. + /// still do. Meaningless when is off (everything is + /// single-branch already). + public bool WarehouseBranchingEnabled { get; set; } = true; + public DateTime? UpdatedAt { get; set; } public int? UpdatedBy { get; set; } diff --git a/Backend/ERPCore/Domain/Entities/Customer.cs b/Backend/ERPCore/Domain/Entities/Customer.cs index 916a1b9..cf34fdf 100644 --- a/Backend/ERPCore/Domain/Entities/Customer.cs +++ b/Backend/ERPCore/Domain/Entities/Customer.cs @@ -29,6 +29,9 @@ public class Customer public int? DefaultWarehouseId { get; set; } public Warehouse? DefaultWarehouse { get; set; } + public int BranchId { get; set; } + public Branch? Branch { get; set; } + public EntityStatus Status { get; set; } = EntityStatus.Active; public DateTime CreatedAt { get; set; } public DateTime? UpdatedAt { get; set; } diff --git a/Backend/ERPCore/Domain/Entities/Item.cs b/Backend/ERPCore/Domain/Entities/Item.cs index 2a6fa07..292345c 100644 --- a/Backend/ERPCore/Domain/Entities/Item.cs +++ b/Backend/ERPCore/Domain/Entities/Item.cs @@ -14,6 +14,9 @@ public class Item public string Name { get; set; } = string.Empty; public string? Description { get; set; } + /// Optional scan code for barcode/RFID lookup (unique when set). + public string? Barcode { get; set; } + public int CategoryId { get; set; } public Category? Category { get; set; } @@ -41,7 +44,14 @@ public class Item public Warranty Warranty { get; set; } = Warranty.NonWarranty; /// Coverage length in months (see ) when is Warranty; null otherwise. public int? WarrantyPeriodMonths { get; set; } - public string? TaxClass { get; set; } + + /// + /// The tax rate a sales/purchase line for this item defaults to (see + /// ) — replaces the old free-text "tax class" label that nothing + /// ever read. Null means no default; a line must be given an explicit tax percentage. + /// + public int? TaxRateId { get; set; } + public TaxRate? TaxRate { get; set; } /// /// Optional selling price range and flat price used by Sales only. diff --git a/Backend/ERPCore/Domain/Entities/Notification.cs b/Backend/ERPCore/Domain/Entities/Notification.cs new file mode 100644 index 0000000..bdebf06 --- /dev/null +++ b/Backend/ERPCore/Domain/Entities/Notification.cs @@ -0,0 +1,22 @@ +namespace ERPCore.Domain.Entities; + +/// +/// A single raised notification event (e.g. "GRN Confirmed"). Broadcast to +/// active users via rows, gated by +/// whether the module's InApp channel is enabled in . +/// +public class Notification +{ + public int NotificationId { get; set; } + + public string ModuleKey { get; set; } = string.Empty; + public string Title { get; set; } = string.Empty; + public string Message { get; set; } = string.Empty; + + public string? RelatedEntityType { get; set; } + public int? RelatedEntityId { get; set; } + + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; + + public ICollection Recipients { get; set; } = new List(); +} diff --git a/Backend/ERPCore/Domain/Entities/NotificationRecipient.cs b/Backend/ERPCore/Domain/Entities/NotificationRecipient.cs new file mode 100644 index 0000000..dead367 --- /dev/null +++ b/Backend/ERPCore/Domain/Entities/NotificationRecipient.cs @@ -0,0 +1,18 @@ +namespace ERPCore.Domain.Entities; + +/// +/// Per-user read state for a broadcast . +/// +public class NotificationRecipient +{ + public int NotificationRecipientId { get; set; } + + public int NotificationId { get; set; } + public Notification? Notification { get; set; } + + public int UserId { get; set; } + public User? User { get; set; } + + public bool IsRead { get; set; } + public DateTime? ReadAt { get; set; } +} diff --git a/Backend/ERPCore/Domain/Entities/NumberSequence.cs b/Backend/ERPCore/Domain/Entities/NumberSequence.cs index c4f7ffc..c1b6e8e 100644 --- a/Backend/ERPCore/Domain/Entities/NumberSequence.cs +++ b/Backend/ERPCore/Domain/Entities/NumberSequence.cs @@ -10,6 +10,10 @@ public class NumberSequence { public int SequenceId { get; set; } public string DocType { get; set; } = string.Empty; + /// Per-branch counter key (docs/BRANCH_ISOLATION_PLAN.md §5) — backfilled to the + /// deployment's default branch for rows that predate per-branch numbering. + public int BranchId { get; set; } + public Branch? Branch { get; set; } public int Year { get; set; } public int LastNumber { get; set; } } diff --git a/Backend/ERPCore/Domain/Entities/PurchaseInvoice.cs b/Backend/ERPCore/Domain/Entities/PurchaseInvoice.cs index 2e73d7f..c419867 100644 --- a/Backend/ERPCore/Domain/Entities/PurchaseInvoice.cs +++ b/Backend/ERPCore/Domain/Entities/PurchaseInvoice.cs @@ -20,6 +20,9 @@ public class PurchaseInvoice public int VendorId { get; set; } public Vendor? Vendor { get; set; } + public int BranchId { get; set; } + public Branch? Branch { get; set; } + public string VendorSnapshotName { get; set; } = string.Empty; public string? VendorSnapshotTaxNo { get; set; } diff --git a/Backend/ERPCore/Domain/Entities/PurchaseOrder.cs b/Backend/ERPCore/Domain/Entities/PurchaseOrder.cs index a94c0a1..90aa55a 100644 --- a/Backend/ERPCore/Domain/Entities/PurchaseOrder.cs +++ b/Backend/ERPCore/Domain/Entities/PurchaseOrder.cs @@ -5,9 +5,10 @@ namespace ERPCore.Domain.Entities; /// /// Purchase order header (FR-PROC-03..06). Mutable aggregate with a /// ETag token; editable while open (FR-PROC-05). -/// Phase 1 auto-approves on creation; is retained -/// for the future approval workflow. Totals are computed server-side from lines -/// (not stored). Model: docs/10 Part C.2. +/// A submitted/issued PO goes to and +/// needs a separate Approve action (an Admin who isn't ) before it +/// reaches . Totals are computed server-side +/// from lines (not stored). Model: docs/10 Part C.2. /// public class PurchaseOrder { @@ -17,15 +18,25 @@ public class PurchaseOrder public int VendorId { get; set; } public Vendor? Vendor { get; set; } + public int BranchId { get; set; } + public Branch? Branch { get; set; } + public int? RequisitionId { get; set; } public Requisition? Requisition { get; set; } public PurchaseOrderStatus Status { get; set; } = PurchaseOrderStatus.Draft; + /// True once the PO has been (or needs to be) routed through approval — + /// i.e. it is not a still-editable Draft. public bool ApprovalRequired { get; set; } public int CreatedBy { get; set; } public User? Creator { get; set; } + /// Who approved this PO — set only when reaches Approved. + public int? ApprovedBy { get; set; } + public User? Approver { get; set; } + public DateTime? ApprovedAt { get; set; } + public DateTime CreatedAt { get; set; } public DateTime? UpdatedAt { get; set; } diff --git a/Backend/ERPCore/Domain/Entities/Requisition.cs b/Backend/ERPCore/Domain/Entities/Requisition.cs index 29103ca..79298eb 100644 --- a/Backend/ERPCore/Domain/Entities/Requisition.cs +++ b/Backend/ERPCore/Domain/Entities/Requisition.cs @@ -14,6 +14,9 @@ public class Requisition public int RequestedBy { get; set; } public User? Requester { get; set; } + public int BranchId { get; set; } + public Branch? Branch { get; set; } + public RequisitionStatus Status { get; set; } = RequisitionStatus.Draft; public DateTime CreatedAt { get; set; } diff --git a/Backend/ERPCore/Domain/Entities/Rfq.cs b/Backend/ERPCore/Domain/Entities/Rfq.cs index 5a4e5c1..3ef9138 100644 --- a/Backend/ERPCore/Domain/Entities/Rfq.cs +++ b/Backend/ERPCore/Domain/Entities/Rfq.cs @@ -14,6 +14,9 @@ public class Rfq public int RequisitionId { get; set; } public Requisition? Requisition { get; set; } + public int BranchId { get; set; } + public Branch? Branch { get; set; } + public RfqStatus Status { get; set; } = RfqStatus.Open; public DateTime CreatedAt { get; set; } diff --git a/Backend/ERPCore/Domain/Entities/RolePermission.cs b/Backend/ERPCore/Domain/Entities/RolePermission.cs index 75734d4..7005b57 100644 --- a/Backend/ERPCore/Domain/Entities/RolePermission.cs +++ b/Backend/ERPCore/Domain/Entities/RolePermission.cs @@ -1,3 +1,5 @@ +using ERPCore.Domain.Enums; + namespace ERPCore.Domain.Entities; /// Join row granting a visibility of a (nav node). @@ -6,6 +8,13 @@ public class RolePermission public int RoleId { get; set; } public int PermissionId { get; set; } + /// + /// Which mutating actions the role may perform within this permission's module + /// (see ); defaults to + /// so existing grants keep today's behavior until an admin narrows them. + /// + public RolePermissionAction Actions { get; set; } = RolePermissionAction.All; + public Role? Role { get; set; } public Permission? Permission { get; set; } } diff --git a/Backend/ERPCore/Domain/Entities/SalesDayEnd.cs b/Backend/ERPCore/Domain/Entities/SalesDayEnd.cs index 63ff8f6..c731f96 100644 --- a/Backend/ERPCore/Domain/Entities/SalesDayEnd.cs +++ b/Backend/ERPCore/Domain/Entities/SalesDayEnd.cs @@ -27,6 +27,16 @@ public class SalesDayEnd public decimal TaxTotal { get; set; } public decimal GrandTotal { get; set; } + /// + /// Sum of across the day's slips (bundle sales have no + /// partial-payment field and are always counted as fully paid) — what actually gets debited + /// to Cash on close. is the rest (GrandTotal - PaidTotal), + /// debited to Accounts Receivable instead. Before partial payments existed these were always + /// equal to GrandTotal/0 respectively (every sale was assumed fully cash). + /// + public decimal PaidTotal { get; set; } + public decimal BalanceTotal { get; set; } + /// Sum of the FIFO cost consumed for these slips (from ), for the COGS GL lines. public decimal CostOfGoodsSold { get; set; } diff --git a/Backend/ERPCore/Domain/Entities/SalesSlipLine.cs b/Backend/ERPCore/Domain/Entities/SalesSlipLine.cs index 11302d2..5497afe 100644 --- a/Backend/ERPCore/Domain/Entities/SalesSlipLine.cs +++ b/Backend/ERPCore/Domain/Entities/SalesSlipLine.cs @@ -19,6 +19,12 @@ public class SalesSlipLine public int WarehouseId { get; set; } public Warehouse? Warehouse { get; set; } + public int? BatchId { get; set; } + public Batch? Batch { get; set; } + + public int? SerialId { get; set; } + public Serial? Serial { get; set; } + public decimal UnitPrice { get; set; } public decimal BaseCost { get; set; } public string PriceSource { get; set; } = string.Empty; diff --git a/Backend/ERPCore/Domain/Entities/Serial.cs b/Backend/ERPCore/Domain/Entities/Serial.cs index a4d1876..dbbf7a2 100644 --- a/Backend/ERPCore/Domain/Entities/Serial.cs +++ b/Backend/ERPCore/Domain/Entities/Serial.cs @@ -13,4 +13,7 @@ public class Serial public string SerialNo { get; set; } = string.Empty; public string Status { get; set; } = "InStock"; + + /// Optional scan code for barcode/RFID lookup (unique when set). + public string? Barcode { get; set; } } diff --git a/Backend/ERPCore/Domain/Entities/StockCountLine.cs b/Backend/ERPCore/Domain/Entities/StockCountLine.cs index debcfb7..62b9ea7 100644 --- a/Backend/ERPCore/Domain/Entities/StockCountLine.cs +++ b/Backend/ERPCore/Domain/Entities/StockCountLine.cs @@ -16,6 +16,12 @@ public class StockCountLine public int? BinId { get; set; } + public int? BatchId { get; set; } + public Batch? Batch { get; set; } + + public int? SerialId { get; set; } + public Serial? Serial { get; set; } + public decimal SystemQty { get; set; } public decimal? CountedQty { get; set; } public decimal? Variance { get; set; } diff --git a/Backend/ERPCore/Domain/Entities/SupportTicket.cs b/Backend/ERPCore/Domain/Entities/SupportTicket.cs new file mode 100644 index 0000000..cb1660b --- /dev/null +++ b/Backend/ERPCore/Domain/Entities/SupportTicket.cs @@ -0,0 +1,25 @@ +using ERPCore.Domain.Enums; + +namespace ERPCore.Domain.Entities; + +/// +/// A help-desk ticket raised by a user from the Help page. Status is +/// admin-managed; the conversation is a flat thread of rows. +/// Field/concurrency shape follows the same conventions as +/// (CreatedBy/UpdatedBy actor stamps, RowVersion for optimistic concurrency). +/// +public class SupportTicket +{ + public int TicketId { get; set; } + + public string Subject { get; set; } = string.Empty; + public TicketStatus Status { get; set; } = TicketStatus.Open; + + public int CreatedBy { get; set; } + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; + public int? UpdatedBy { get; set; } + public DateTime? UpdatedAt { get; set; } + public uint RowVersion { get; set; } + + public ICollection Messages { get; set; } = new List(); +} diff --git a/Backend/ERPCore/Domain/Entities/SupportTicketMessage.cs b/Backend/ERPCore/Domain/Entities/SupportTicketMessage.cs new file mode 100644 index 0000000..324f0f3 --- /dev/null +++ b/Backend/ERPCore/Domain/Entities/SupportTicketMessage.cs @@ -0,0 +1,16 @@ +namespace ERPCore.Domain.Entities; + +/// One message in a thread — from the submitter or an admin. +public class SupportTicketMessage +{ + public int MessageId { get; set; } + + public int TicketId { get; set; } + public SupportTicket? Ticket { get; set; } + + public int SenderUserId { get; set; } + public bool IsFromAdmin { get; set; } + public string Message { get; set; } = string.Empty; + + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; +} diff --git a/Backend/ERPCore/Domain/Entities/TaxRate.cs b/Backend/ERPCore/Domain/Entities/TaxRate.cs new file mode 100644 index 0000000..617169a --- /dev/null +++ b/Backend/ERPCore/Domain/Entities/TaxRate.cs @@ -0,0 +1,27 @@ +using ERPCore.Domain.Enums; + +namespace ERPCore.Domain.Entities; + +/// +/// A named tax rate (e.g. "Standard" 15%, "Zero-Rated" 0%, "Exempt" 0%) — the real backing +/// for . Before this existed, Item.TaxClass was a free-text +/// label nothing ever read, and every sales/purchase line carried its own hand-typed tax +/// percentage with no link back to the item at all. Now a line's tax defaults to whatever +/// percentage the item's assigned TaxRate carries at the moment the line is created — change +/// the rate here and every new document picks it up; a line already created keeps the percentage +/// it was given (SalesSlipLine.TaxPct etc. are snapshots, never recomputed from this table). +/// +public class TaxRate +{ + public int TaxRateId { get; set; } + public string Code { get; set; } = string.Empty; + public string Name { get; set; } = string.Empty; + public decimal Percentage { get; set; } + public EntityStatus Status { get; set; } = EntityStatus.Active; + + public DateTime CreatedAt { get; set; } + public DateTime? UpdatedAt { get; set; } + + /// PostgreSQL xmin-backed optimistic concurrency token (ETag source). + public uint RowVersion { get; set; } +} diff --git a/Backend/ERPCore/Domain/Entities/Uom.cs b/Backend/ERPCore/Domain/Entities/Uom.cs index 71b5769..053532c 100644 --- a/Backend/ERPCore/Domain/Entities/Uom.cs +++ b/Backend/ERPCore/Domain/Entities/Uom.cs @@ -1,3 +1,5 @@ +using ERPCore.Domain.Enums; + namespace ERPCore.Domain.Entities; /// @@ -10,4 +12,8 @@ public class Uom { public int UomId { get; set; } public string Name { get; set; } = string.Empty; + public EntityStatus Status { get; set; } = EntityStatus.Active; + + public DateTime CreatedAt { get; set; } + public DateTime? UpdatedAt { get; set; } } diff --git a/Backend/ERPCore/Domain/Entities/Vendor.cs b/Backend/ERPCore/Domain/Entities/Vendor.cs index 05a85d3..aad62de 100644 --- a/Backend/ERPCore/Domain/Entities/Vendor.cs +++ b/Backend/ERPCore/Domain/Entities/Vendor.cs @@ -17,6 +17,9 @@ public class Vendor public string Currency { get; set; } = "LKR"; public EntityStatus Status { get; set; } = EntityStatus.Active; + public int BranchId { get; set; } + public Branch? Branch { get; set; } + public DateTime CreatedAt { get; set; } public DateTime? UpdatedAt { get; set; } diff --git a/Backend/ERPCore/Domain/Entities/Warehouse.cs b/Backend/ERPCore/Domain/Entities/Warehouse.cs index 2c6a3ab..94200dc 100644 --- a/Backend/ERPCore/Domain/Entities/Warehouse.cs +++ b/Backend/ERPCore/Domain/Entities/Warehouse.cs @@ -9,6 +9,8 @@ public class Warehouse public int WarehouseId { get; set; } public string Code { get; set; } = string.Empty; public string Name { get; set; } = string.Empty; + public string? Address { get; set; } + public string? Phone { get; set; } public int BranchId { get; set; } public Branch? Branch { get; set; } diff --git a/Backend/ERPCore/Domain/Enums/PurchaseOrderStatus.cs b/Backend/ERPCore/Domain/Enums/PurchaseOrderStatus.cs index 9cb7c49..88cc4f5 100644 --- a/Backend/ERPCore/Domain/Enums/PurchaseOrderStatus.cs +++ b/Backend/ERPCore/Domain/Enums/PurchaseOrderStatus.cs @@ -1,9 +1,10 @@ namespace ERPCore.Domain.Enums; /// -/// Purchase-order lifecycle (docs/11 §8; docs/10 §B.8.1). Phase 1 auto-approves on -/// creation, so is reserved (not entered) until the -/// approval workflow is enabled (FR-PROC-04). Stored as a string. +/// Purchase-order lifecycle (docs/11 §8; docs/10 §B.8.1). Issuing a PO (create +/// non-draft, or submit a Draft) enters ; an Admin who +/// isn't the creator must Approve it to reach , or Reject it back +/// to (FR-PROC-04). Stored as a string. /// public enum PurchaseOrderStatus { diff --git a/Backend/ERPCore/Domain/Enums/RolePermissionAction.cs b/Backend/ERPCore/Domain/Enums/RolePermissionAction.cs new file mode 100644 index 0000000..2584a90 --- /dev/null +++ b/Backend/ERPCore/Domain/Enums/RolePermissionAction.cs @@ -0,0 +1,21 @@ +namespace ERPCore.Domain.Enums; + +/// +/// Fine-grained actions a can grant within a module +/// it already has nav-level access to (see ). Nav-level +/// access answers "can this role reach this module"; this answers "which mutations within +/// it can this role actually perform" — e.g. a role that can see Procurement but should not +/// be able to delete or approve purchase orders. +/// +[Flags] +public enum RolePermissionAction +{ + None = 0, + View = 1, + Create = 2, + Edit = 4, + Delete = 8, + Approve = 16, + + All = View | Create | Edit | Delete | Approve +} diff --git a/Backend/ERPCore/Domain/Enums/TicketStatus.cs b/Backend/ERPCore/Domain/Enums/TicketStatus.cs new file mode 100644 index 0000000..69b2315 --- /dev/null +++ b/Backend/ERPCore/Domain/Enums/TicketStatus.cs @@ -0,0 +1,8 @@ +namespace ERPCore.Domain.Enums; + +public enum TicketStatus +{ + Open, + InProgress, + Resolved +} diff --git a/Backend/ERPCore/Dtos/Auth/AuthUserDtos.cs b/Backend/ERPCore/Dtos/Auth/AuthUserDtos.cs index a8ca585..750eb67 100644 --- a/Backend/ERPCore/Dtos/Auth/AuthUserDtos.cs +++ b/Backend/ERPCore/Dtos/Auth/AuthUserDtos.cs @@ -29,6 +29,21 @@ public sealed class AuthSessionResponse public int ExpiresIn { get; set; } } +/// Result of AuthHex's admin-only deleteUser function. +public sealed class DeleteAuthHexUserResult +{ + public int DeletedCount { get; set; } + public List? Deleted { get; set; } +} + +public sealed class DeletedAuthHexUser +{ + public Guid Id { get; set; } + public string? FullName { get; set; } + public string? UserName { get; set; } + public string? Email { get; set; } +} + public sealed class RegisterRequest { /// Optional — AuthHex requires a client-supplied id; ERPCore generates one when omitted. diff --git a/Backend/ERPCore/Dtos/Config/BranchConfigDtos.cs b/Backend/ERPCore/Dtos/Config/BranchConfigDtos.cs index 26976c8..aa5b229 100644 --- a/Backend/ERPCore/Dtos/Config/BranchConfigDtos.cs +++ b/Backend/ERPCore/Dtos/Config/BranchConfigDtos.cs @@ -4,7 +4,7 @@ namespace ERPCore.Dtos.Config; /// Branch configuration resource — the singleton toggle for whether this deployment /// requires a branch on Employee/Warehouse records at all. -public sealed record BranchConfigDto(bool BranchingEnabled, DateTime? UpdatedAt, int? UpdatedBy); +public sealed record BranchConfigDto(bool BranchingEnabled, bool WarehouseBranchingEnabled, DateTime? UpdatedAt, int? UpdatedBy); /// /// Full replacement of the flag. UpdatedBy is derived from the token, never posted. @@ -17,4 +17,5 @@ public sealed record BranchConfigDto(bool BranchingEnabled, DateTime? UpdatedAt, public sealed class UpdateBranchConfigRequest { [Required] public bool? BranchingEnabled { get; set; } + [Required] public bool? WarehouseBranchingEnabled { get; set; } } diff --git a/Backend/ERPCore/Dtos/Customers/CustomerDtos.cs b/Backend/ERPCore/Dtos/Customers/CustomerDtos.cs index 3b7175d..8176c60 100644 --- a/Backend/ERPCore/Dtos/Customers/CustomerDtos.cs +++ b/Backend/ERPCore/Dtos/Customers/CustomerDtos.cs @@ -21,6 +21,7 @@ public sealed record CustomerDto( int CreditDays, int? DefaultWarehouseId, EntityStatus Status, + int BranchId, DateTime CreatedAt, DateTime? UpdatedAt); @@ -40,6 +41,7 @@ public sealed class CreateCustomerRequest [Range(0, double.MaxValue)] public decimal CreditLimit { get; set; } [Range(0, int.MaxValue)] public int CreditDays { get; set; } public int? DefaultWarehouseId { get; set; } + public int BranchId { get; set; } } public sealed class UpdateCustomerRequest @@ -58,6 +60,7 @@ public sealed class UpdateCustomerRequest [Range(0, double.MaxValue)] public decimal CreditLimit { get; set; } [Range(0, int.MaxValue)] public int CreditDays { get; set; } public int? DefaultWarehouseId { get; set; } + public int BranchId { get; set; } } public sealed class UpdateCustomerStatusRequest diff --git a/Backend/ERPCore/Dtos/Dashboard/DashboardDtos.cs b/Backend/ERPCore/Dtos/Dashboard/DashboardDtos.cs index 857ba9a..07e97ad 100644 --- a/Backend/ERPCore/Dtos/Dashboard/DashboardDtos.cs +++ b/Backend/ERPCore/Dtos/Dashboard/DashboardDtos.cs @@ -4,9 +4,12 @@ namespace ERPCore.Dtos.Dashboard; /// Aggregate counts for the dashboard overview — mirrors the widget set in /// docs/dashboard-implementation.pdf: reorder alerts, on-hand summary, stock valuation, /// pending-approval POs, pending GRNs, open requisitions, open counts awaiting posting, -/// and open RFQs. Recent movements isn't here — it's just GET /stock/ledger with a small -/// pageSize, no aggregation needed. A single computed-on-read object, not a stored -/// entity — same as reorder alerts (docs/11 §5.7). +/// open RFQs, pending leave requests, and overdue sales invoices. Also reused as small +/// KPI tiles on individual list pages (Purchase Orders, GRN, Requisitions, RFQs, Stock +/// Counts, Reorder Alerts, HRM Leave, Sales Invoices), not just the Dashboard home page. +/// Recent movements isn't here — it's just GET /stock/ledger with a small pageSize, no +/// aggregation needed. A single computed-on-read object, not a stored entity — same as +/// reorder alerts (docs/11 §5.7). /// public sealed record DashboardStatsDto( int LowStockAlerts, @@ -18,7 +21,9 @@ public sealed record DashboardStatsDto( int PendingGrns, int OpenRequisitions, int PendingCounts, - int OpenRfqs); + int OpenRfqs, + int PendingLeaveRequests, + int OverdueSalesInvoices); /// One bar in the Stock Valuation chart — total FIFO layer value for a warehouse. public sealed record WarehouseValuationDto(int WarehouseId, decimal Total); diff --git a/Backend/ERPCore/Dtos/Grn/GrnDtos.cs b/Backend/ERPCore/Dtos/Grn/GrnDtos.cs index 6cb0c87..b05e626 100644 --- a/Backend/ERPCore/Dtos/Grn/GrnDtos.cs +++ b/Backend/ERPCore/Dtos/Grn/GrnDtos.cs @@ -63,8 +63,9 @@ public sealed class CreateGrnLineInput [Range(0, double.MaxValue)] public decimal UnitCost { get; set; } /// Trade discount percentage (0–100). Reduces the inventory cost. [Range(0, 100)] public decimal DiscountPct { get; set; } - /// VAT percentage (0–100). Recoverable — does not affect stock value. - [Range(0, 100)] public decimal VatPct { get; set; } + /// VAT percentage (0–100). Recoverable — does not affect stock value. Explicit + /// override; omit (null) to use the item's assigned TaxRate percentage instead. + [Range(0, 100)] public decimal? VatPct { get; set; } [EnumDataType(typeof(HoldStatus))] public HoldStatus HoldStatus { get; set; } = HoldStatus.Available; public BatchInput? Batch { get; set; } /// diff --git a/Backend/ERPCore/Dtos/Hrm/EmployeeDtos.cs b/Backend/ERPCore/Dtos/Hrm/EmployeeDtos.cs index 8c9e445..fa81489 100644 --- a/Backend/ERPCore/Dtos/Hrm/EmployeeDtos.cs +++ b/Backend/ERPCore/Dtos/Hrm/EmployeeDtos.cs @@ -3,6 +3,8 @@ using ERPCore.Domain.Enums; namespace ERPCore.Dtos.Hrm; +public sealed record EmployeeDeleteResultDto(bool UserAccountDeleted, bool UserAccountDeactivated, bool AuthHexIdentityPurged = false); + public sealed record EmployeeListItemDto( int EmployeeId, string EmployeeCode, string FullName, string? Email, int DepartmentId, string? DepartmentName, int DesignationId, string? DesignationName, diff --git a/Backend/ERPCore/Dtos/Items/ItemDtos.cs b/Backend/ERPCore/Dtos/Items/ItemDtos.cs index 32a584d..e1ab0ff 100644 --- a/Backend/ERPCore/Dtos/Items/ItemDtos.cs +++ b/Backend/ERPCore/Dtos/Items/ItemDtos.cs @@ -10,10 +10,11 @@ public sealed record ItemListItemDto( int ItemId, string Sku, string Name, int CategoryId, int? SubCategoryId, int? BrandId, int BaseUomId, int? DefaultVendorId, StockNature StockNature, TrackingMode TrackingMode, Warranty Warranty, int? WarrantyPeriodMonths, - string? TaxClass, decimal? SellingMinPrice, decimal? SellingMaxPrice, decimal? SellingFlatPrice, + int? TaxRateId, string? TaxRateName, decimal? TaxRatePercentage, + decimal? SellingMinPrice, decimal? SellingMaxPrice, decimal? SellingFlatPrice, decimal? ContentQty, MeasureUnit? ContentUnit, decimal? ContentBaseQty, MeasureUnit? ContentBaseUnit, - EntityStatus Status); + EntityStatus Status, string? Barcode); /// A single per-warehouse reorder policy row. public sealed record ItemReorderDto(int WarehouseId, decimal ReorderPoint, decimal ReorderQty); @@ -31,10 +32,11 @@ public sealed record ItemDetailDto( int? SubCategoryId, int? BrandId, int BaseUomId, int? DefaultVendorId, StockNature StockNature, TrackingMode TrackingMode, Warranty Warranty, int? WarrantyPeriodMonths, - string? TaxClass, decimal? SellingMinPrice, decimal? SellingMaxPrice, decimal? SellingFlatPrice, + int? TaxRateId, string? TaxRateName, decimal? TaxRatePercentage, + decimal? SellingMinPrice, decimal? SellingMaxPrice, decimal? SellingFlatPrice, decimal? ContentQty, MeasureUnit? ContentUnit, decimal? ContentBaseQty, MeasureUnit? ContentBaseUnit, - EntityStatus Status, IReadOnlyList Reorder, + EntityStatus Status, string? Barcode, IReadOnlyList Reorder, DateTime CreatedAt, DateTime? UpdatedAt); /// Response body for PUT /items/{id}/reorder. @@ -64,7 +66,8 @@ public sealed class CreateItemRequest [EnumDataType(typeof(Warranty))] public Warranty Warranty { get; set; } = Warranty.NonWarranty; /// Required (one of ) when is Warranty; ignored otherwise. public int? WarrantyPeriodMonths { get; set; } - [StringLength(20)] public string? TaxClass { get; set; } + /// The tax rate sales/purchase lines for this item default to — see . + public int? TaxRateId { get; set; } /// Optional fixed sale price (Sales only). Null ⇒ sell at stock/FIFO value. [Range(0, double.MaxValue)] public decimal? SellingMinPrice { get; set; } [Range(0, double.MaxValue)] public decimal? SellingMaxPrice { get; set; } @@ -77,6 +80,8 @@ public sealed class CreateItemRequest /// [Range(0.0001, double.MaxValue)] public decimal? ContentQty { get; set; } [EnumDataType(typeof(MeasureUnit))] public MeasureUnit? ContentUnit { get; set; } + /// Optional scan code for barcode/RFID lookup. Unlike , not required. + [StringLength(100)] public string? Barcode { get; set; } } public sealed class UpdateItemRequest @@ -96,7 +101,8 @@ public sealed class UpdateItemRequest [EnumDataType(typeof(Warranty))] public Warranty Warranty { get; set; } = Warranty.NonWarranty; /// Required (one of ) when is Warranty; ignored otherwise. public int? WarrantyPeriodMonths { get; set; } - [StringLength(20)] public string? TaxClass { get; set; } + /// The tax rate sales/purchase lines for this item default to — see . + public int? TaxRateId { get; set; } /// Optional fixed sale price (Sales only). Null ⇒ sell at stock/FIFO value. [Range(0, double.MaxValue)] public decimal? SellingMinPrice { get; set; } [Range(0, double.MaxValue)] public decimal? SellingMaxPrice { get; set; } @@ -109,6 +115,8 @@ public sealed class UpdateItemRequest /// [Range(0.0001, double.MaxValue)] public decimal? ContentQty { get; set; } [EnumDataType(typeof(MeasureUnit))] public MeasureUnit? ContentUnit { get; set; } + /// Optional scan code for barcode/RFID lookup. Unlike , not required. + [StringLength(100)] public string? Barcode { get; set; } } public sealed class UpdateItemStatusRequest diff --git a/Backend/ERPCore/Dtos/Items/ItemScanDtos.cs b/Backend/ERPCore/Dtos/Items/ItemScanDtos.cs new file mode 100644 index 0000000..182b99d --- /dev/null +++ b/Backend/ERPCore/Dtos/Items/ItemScanDtos.cs @@ -0,0 +1,11 @@ +using ERPCore.Domain.Enums; + +namespace ERPCore.Dtos.Items; + +/// Result of a barcode/RFID scan lookup — an item, or an item resolved via a +/// specific batch/serial. See . +public sealed record ItemScanResultDto( + int ItemId, string Sku, string Name, TrackingMode TrackingMode, int BaseUomId, + string MatchedBy, // "Item" | "Batch" | "Serial" + int? BatchId, string? BatchNo, DateOnly? ExpiryDate, + int? SerialId, string? SerialNo, string? SerialStatus); diff --git a/Backend/ERPCore/Dtos/Notifications/NotificationDtos.cs b/Backend/ERPCore/Dtos/Notifications/NotificationDtos.cs new file mode 100644 index 0000000..1b2f573 --- /dev/null +++ b/Backend/ERPCore/Dtos/Notifications/NotificationDtos.cs @@ -0,0 +1,15 @@ +namespace ERPCore.Dtos.Notifications; + +public sealed record NotificationDto( + int NotificationId, + string ModuleKey, + string Title, + string Message, + string? RelatedEntityType, + int? RelatedEntityId, + DateTime CreatedAt, + bool IsRead); + +public sealed record NotificationFeedDto( + IReadOnlyList Notifications, + int UnreadCount); diff --git a/Backend/ERPCore/Dtos/Procurement/PurchaseInvoiceDtos.cs b/Backend/ERPCore/Dtos/Procurement/PurchaseInvoiceDtos.cs index d53b078..483b8db 100644 --- a/Backend/ERPCore/Dtos/Procurement/PurchaseInvoiceDtos.cs +++ b/Backend/ERPCore/Dtos/Procurement/PurchaseInvoiceDtos.cs @@ -12,14 +12,14 @@ public sealed record PurchaseInvoiceTotalsDto( public sealed record PurchaseInvoiceDto( int PurchaseInvoiceId, string DocNo, string VendorInvoiceNo, DateTime VendorInvoiceDate, - int VendorId, string VendorSnapshotName, string? VendorSnapshotTaxNo, + int VendorId, int BranchId, string VendorSnapshotName, string? VendorSnapshotTaxNo, PurchaseInvoiceStatus Status, int GrnCount, int CreatedBy, DateTime CreatedAt, DateTime? UpdatedAt, string? GlJournalNo, DateTime? GlPostedAt, PurchaseInvoiceTotalsDto Totals, IReadOnlyList Lines); public sealed record PurchaseInvoiceSummaryDto( int PurchaseInvoiceId, string DocNo, string VendorInvoiceNo, DateTime VendorInvoiceDate, - int VendorId, string VendorSnapshotName, PurchaseInvoiceStatus Status, int GrnCount, + int VendorId, int BranchId, string VendorSnapshotName, PurchaseInvoiceStatus Status, int GrnCount, PurchaseInvoiceTotalsDto Totals, DateTime CreatedAt, string? GlJournalNo); public sealed record PurchaseInvoicePaymentDto( diff --git a/Backend/ERPCore/Dtos/Procurement/PurchaseOrderDtos.cs b/Backend/ERPCore/Dtos/Procurement/PurchaseOrderDtos.cs index 01177ff..59a1a26 100644 --- a/Backend/ERPCore/Dtos/Procurement/PurchaseOrderDtos.cs +++ b/Backend/ERPCore/Dtos/Procurement/PurchaseOrderDtos.cs @@ -12,13 +12,14 @@ public sealed record PoLineDto( public sealed record PoTotalsDto(decimal SubTotal, decimal Tax, decimal GrandTotal, string Currency); public sealed record PurchaseOrderDto( - int PoId, string DocNo, int VendorId, int? RequisitionId, PurchaseOrderStatus Status, - bool ApprovalRequired, int CreatedBy, DateTime CreatedAt, DateTime? UpdatedAt, + int PoId, string DocNo, int VendorId, int BranchId, int? RequisitionId, PurchaseOrderStatus Status, + bool ApprovalRequired, int CreatedBy, int? ApprovedBy, DateTime? ApprovedAt, + DateTime CreatedAt, DateTime? UpdatedAt, PoTotalsDto Totals, IReadOnlyList Lines); public sealed record PurchaseOrderSummaryDto( - int PoId, string DocNo, int VendorId, PurchaseOrderStatus Status, - bool ApprovalRequired, DateTime CreatedAt, PoTotalsDto Totals); + int PoId, string DocNo, int VendorId, int BranchId, PurchaseOrderStatus Status, + bool ApprovalRequired, int CreatedBy, DateTime CreatedAt, PoTotalsDto Totals); // Requests — server sets docNo, status, createdBy, timestamps, qtyReceived, totals @@ -35,12 +36,13 @@ public sealed class CreatePurchaseOrderRequest { [Required] public int VendorId { get; set; } public int? RequisitionId { get; set; } + public int BranchId { get; set; } [Required, MinLength(1)] public List Lines { get; set; } = new(); /// /// When true the PO is created in Draft (editable/deletable, not yet issued). - /// When false (default) it auto-approves on creation, preserving the Requisition→PO - /// and RFQ→PO flows unchanged (docs/11 §3.3). + /// When false (default) it is issued immediately into PendingApproval, same as + /// submitting a Draft (docs/11 §3.3). /// public bool SaveAsDraft { get; set; } } @@ -49,6 +51,7 @@ public sealed class UpdatePurchaseOrderRequest { [Required] public int VendorId { get; set; } public int? RequisitionId { get; set; } + public int BranchId { get; set; } [Required, MinLength(1)] public List Lines { get; set; } = new(); } @@ -56,3 +59,8 @@ public sealed class CancelPurchaseOrderRequest { [StringLength(500)] public string? Reason { get; set; } } + +public sealed class RejectPurchaseOrderRequest +{ + [StringLength(500)] public string? Reason { get; set; } +} diff --git a/Backend/ERPCore/Dtos/Procurement/RequisitionDtos.cs b/Backend/ERPCore/Dtos/Procurement/RequisitionDtos.cs index ef8cae1..7ed215f 100644 --- a/Backend/ERPCore/Dtos/Procurement/RequisitionDtos.cs +++ b/Backend/ERPCore/Dtos/Procurement/RequisitionDtos.cs @@ -8,11 +8,11 @@ namespace ERPCore.Dtos.Procurement; public sealed record RequisitionLineDto(int ReqLineId, int ItemId, decimal Qty, DateOnly? RequiredBy); public sealed record RequisitionDto( - int RequisitionId, string DocNo, RequisitionStatus Status, int RequestedBy, + int RequisitionId, string DocNo, RequisitionStatus Status, int RequestedBy, int BranchId, DateTime CreatedAt, IReadOnlyList Lines); public sealed record RequisitionSummaryDto( - int RequisitionId, string DocNo, RequisitionStatus Status, int RequestedBy, DateTime CreatedAt, int LineCount); + int RequisitionId, string DocNo, RequisitionStatus Status, int RequestedBy, int BranchId, DateTime CreatedAt, int LineCount); // Requests — server sets docNo, status, requestedBy (audit actor), timestamps ---- @@ -26,4 +26,7 @@ public sealed class CreateRequisitionLineInput public sealed class CreateRequisitionRequest { [Required, MinLength(1)] public List Lines { get; set; } = new(); + /// Optional — resolved via + /// when branching is enabled; ignored (defaulted) otherwise. + public int BranchId { get; set; } } diff --git a/Backend/ERPCore/Dtos/Procurement/RfqDtos.cs b/Backend/ERPCore/Dtos/Procurement/RfqDtos.cs index f9a5635..55d0687 100644 --- a/Backend/ERPCore/Dtos/Procurement/RfqDtos.cs +++ b/Backend/ERPCore/Dtos/Procurement/RfqDtos.cs @@ -8,11 +8,11 @@ namespace ERPCore.Dtos.Procurement; public sealed record RfqLineDto(int RfqLineId, int ItemId, decimal Qty); public sealed record RfqDto( - int RfqId, string DocNo, int RequisitionId, RfqStatus Status, IReadOnlyList Lines); + int RfqId, string DocNo, int RequisitionId, int BranchId, RfqStatus Status, IReadOnlyList Lines); /// Row shape for GET /rfqs — line/quotation counts instead of the lines themselves. public sealed record RfqSummaryDto( - int RfqId, string DocNo, int RequisitionId, RfqStatus Status, int LineCount, int QuotationCount); + int RfqId, string DocNo, int RequisitionId, int BranchId, RfqStatus Status, int LineCount, int QuotationCount); public sealed record QuotationLineDto(int ItemId, decimal UnitPrice, int LeadDays); diff --git a/Backend/ERPCore/Dtos/Rbac/MeDtos.cs b/Backend/ERPCore/Dtos/Rbac/MeDtos.cs index f56c32f..93bbbf4 100644 --- a/Backend/ERPCore/Dtos/Rbac/MeDtos.cs +++ b/Backend/ERPCore/Dtos/Rbac/MeDtos.cs @@ -11,4 +11,4 @@ namespace ERPCore.Dtos.Rbac; /// entirely rather than merely restricting them by role. public sealed record MeResponseDto( string? RoleCode, string? RoleName, IReadOnlyList NavCodes, - bool IsAdmin, int? BranchId, string? BranchName, bool BranchingEnabled); + bool IsAdmin, int? BranchId, string? BranchName, bool BranchingEnabled, bool WarehouseBranchingEnabled); diff --git a/Backend/ERPCore/Dtos/Rbac/RoleDtos.cs b/Backend/ERPCore/Dtos/Rbac/RoleDtos.cs index 2c0d26b..77a7cc7 100644 --- a/Backend/ERPCore/Dtos/Rbac/RoleDtos.cs +++ b/Backend/ERPCore/Dtos/Rbac/RoleDtos.cs @@ -29,6 +29,22 @@ public sealed class AssignRolePermissionsRequest { public List NavItemIds { get; set; } = new(); public List SubNavItemIds { get; set; } = new(); + + /// + /// Optional per-nav/sub-nav-item action override, keyed by NavItemId/ + /// SubNavItemId and valued with a bitmask + /// (e.g. View|Create|Edit = 7 to grant a module without Delete/Approve). An id + /// present in / but absent here + /// keeps today's default of — this only narrows, + /// never grants access to an id that isn't also in those lists. + /// + public Dictionary NavItemActions { get; set; } = new(); + public Dictionary SubNavItemActions { get; set; } = new(); } -public sealed record RolePermissionsDto(int RoleId, List NavItemIds, List SubNavItemIds); +public sealed record RolePermissionsDto( + int RoleId, + List NavItemIds, + List SubNavItemIds, + Dictionary NavItemActions, + Dictionary SubNavItemActions); diff --git a/Backend/ERPCore/Dtos/Sales/SalesDayEndDtos.cs b/Backend/ERPCore/Dtos/Sales/SalesDayEndDtos.cs index 398e266..5b04012 100644 --- a/Backend/ERPCore/Dtos/Sales/SalesDayEndDtos.cs +++ b/Backend/ERPCore/Dtos/Sales/SalesDayEndDtos.cs @@ -20,19 +20,21 @@ public sealed record SalesDayEndInvoiceSummaryDto( public sealed record SalesDayEndDto( int SalesDayEndId, string DocNo, int CashierUserId, DateOnly BusinessDate, int SlipCount, int BundleCount, decimal Subtotal, decimal DiscountTotal, decimal TaxTotal, decimal GrandTotal, + decimal PaidTotal, decimal BalanceTotal, decimal CostOfGoodsSold, string? GlJournalNo, DateTime? GlPostedAt, int ClosedBy, DateTime ClosedAt, IReadOnlyList SlipNumbers, IReadOnlyList BundleNumbers, IReadOnlyList ItemBreakdown, SalesDayEndInvoiceSummaryDto Invoices); public sealed record SalesDayEndSummaryDto( int SalesDayEndId, string DocNo, int CashierUserId, DateOnly BusinessDate, - int SlipCount, int BundleCount, decimal GrandTotal, string? GlJournalNo, DateTime ClosedAt); + int SlipCount, int BundleCount, decimal GrandTotal, decimal PaidTotal, decimal BalanceTotal, string? GlJournalNo, DateTime ClosedAt); /// What closing right now would include — call before POST /sales-day-end so the /// cashier can see the day's totals, and any still-Draft slips/bundles blocking the close. public sealed record SalesDayEndPreviewDto( int CashierUserId, DateOnly BusinessDate, bool AlreadyClosed, int SlipCount, int BundleCount, decimal Subtotal, decimal DiscountTotal, decimal TaxTotal, decimal GrandTotal, + decimal PaidTotal, decimal BalanceTotal, IReadOnlyList SlipNumbers, IReadOnlyList BundleNumbers, IReadOnlyList DraftSlipsBlockingClose, IReadOnlyList DraftBundleSalesBlockingClose, diff --git a/Backend/ERPCore/Dtos/Sales/SalesInvoiceDtos.cs b/Backend/ERPCore/Dtos/Sales/SalesInvoiceDtos.cs index cd037f8..9f3ebad 100644 --- a/Backend/ERPCore/Dtos/Sales/SalesInvoiceDtos.cs +++ b/Backend/ERPCore/Dtos/Sales/SalesInvoiceDtos.cs @@ -56,7 +56,9 @@ public sealed class CreateSalesInvoiceLineRequest [Range(0, 100)] public decimal DiscountPct { get; set; } [Range(0, double.MaxValue)] public decimal DiscountAmount { get; set; } [Range(0, double.MaxValue)] public decimal DiscountValue { get; set; } - [Range(0, 100)] public decimal TaxPct { get; set; } + /// Explicit override. Omit (null) to use the item's assigned TaxRate — see + /// . + [Range(0, 100)] public decimal? TaxPct { get; set; } public bool IsFreeIssue { get; set; } public int? ParentLineId { get; set; } } diff --git a/Backend/ERPCore/Dtos/Sales/SalesSlipDtos.cs b/Backend/ERPCore/Dtos/Sales/SalesSlipDtos.cs index 629bb0d..a65bd4e 100644 --- a/Backend/ERPCore/Dtos/Sales/SalesSlipDtos.cs +++ b/Backend/ERPCore/Dtos/Sales/SalesSlipDtos.cs @@ -7,7 +7,8 @@ public sealed record SalesSlipLineDto( int SalesSlipLineId, int ItemId, string Description, decimal Qty, decimal FreeQty, int WarehouseId, decimal UnitPrice, decimal BaseCost, string PriceSource, decimal DiscountPct, decimal DiscountAmount, SalesDiscountMode DiscountMode, decimal NetUnitPrice, decimal LineTotal, - decimal TaxPct, decimal TaxAmount, bool IsFreeIssue, int? ParentLineId); + decimal TaxPct, decimal TaxAmount, bool IsFreeIssue, int? ParentLineId, + int? BatchId, int? SerialId); public sealed record SalesSlipTotalsDto( decimal Subtotal, decimal DiscountTotal, decimal FreeQtyTotal, decimal TaxTotal, decimal GrandTotal, @@ -54,9 +55,15 @@ public sealed class CreateSalesSlipLineRequest [Range(0, 100)] public decimal DiscountPct { get; set; } [Range(0, double.MaxValue)] public decimal DiscountAmount { get; set; } [Range(0, double.MaxValue)] public decimal DiscountValue { get; set; } - [Range(0, 100)] public decimal TaxPct { get; set; } + /// Explicit override. Omit (null) to use the item's assigned TaxRate — see + /// . + [Range(0, 100)] public decimal? TaxPct { get; set; } public bool IsFreeIssue { get; set; } public int? ParentLineId { get; set; } + /// Pins the line to a specific batch (must belong to ), consumed via FIFO. + public int? BatchId { get; set; } + /// Pins the line to a specific serial (must belong to ); marked Sold on posting. + public int? SerialId { get; set; } } public sealed class CreateSalesSlipRequest @@ -65,6 +72,16 @@ public sealed class CreateSalesSlipRequest [Required] public int WarehouseId { get; set; } [Required] public int CashierUserId { get; set; } [Required, MinLength(1)] public List Lines { get; set; } = new(); + + /// + /// How much the customer actually paid at ring-up. Omit (or send null) for the default — + /// fully paid, i.e. PaidAmount == GrandTotal and BalanceAmount == 0 — matching + /// every slip's behavior before partial payment existed. Must be between 0 and the computed + /// GrandTotal; anything less than GrandTotal leaves the difference as BalanceAmount owed by + /// the customer "on account," which Sales Day-End then splits between Cash and Accounts + /// Receivable when it posts (see SalesDayEndService.CloseAsync). + /// + [Range(0, double.MaxValue)] public decimal? PaidAmount { get; set; } } public sealed class UpdateSalesSlipRequest @@ -73,4 +90,7 @@ public sealed class UpdateSalesSlipRequest [Required] public int WarehouseId { get; set; } [Required] public int CashierUserId { get; set; } [Required, MinLength(1)] public List Lines { get; set; } = new(); + + /// See . + [Range(0, double.MaxValue)] public decimal? PaidAmount { get; set; } } diff --git a/Backend/ERPCore/Dtos/Search/GlobalSearchDtos.cs b/Backend/ERPCore/Dtos/Search/GlobalSearchDtos.cs new file mode 100644 index 0000000..eb7fefc --- /dev/null +++ b/Backend/ERPCore/Dtos/Search/GlobalSearchDtos.cs @@ -0,0 +1,16 @@ +namespace ERPCore.Dtos.Search; + +public enum GlobalSearchResultType +{ + Item, + PurchaseOrder, + Invoice, + Employee +} + +public sealed record GlobalSearchResultDto( + GlobalSearchResultType Type, + int Id, + string Number, + string Title, + string? Subtitle); diff --git a/Backend/ERPCore/Dtos/Stock/CountDtos.cs b/Backend/ERPCore/Dtos/Stock/CountDtos.cs index f330163..ab4a238 100644 --- a/Backend/ERPCore/Dtos/Stock/CountDtos.cs +++ b/Backend/ERPCore/Dtos/Stock/CountDtos.cs @@ -5,7 +5,9 @@ namespace ERPCore.Dtos.Stock; // Responses (docs/11 §5.6) ------------------------------------------------------ -public sealed record CountLineDto(int CountLineId, int ItemId, int? BinId, decimal SystemQty, decimal? CountedQty, decimal? Variance); +public sealed record CountLineDto( + int CountLineId, int ItemId, int? BinId, decimal SystemQty, decimal? CountedQty, decimal? Variance, + int? BatchId, string? BatchNo, int? SerialId, string? SerialNo); public sealed record CountDto( int CountId, string DocNo, int WarehouseId, int BranchId, CountType CountType, CountStatus Status, diff --git a/Backend/ERPCore/Dtos/Support/SupportTicketDtos.cs b/Backend/ERPCore/Dtos/Support/SupportTicketDtos.cs new file mode 100644 index 0000000..7c44ce9 --- /dev/null +++ b/Backend/ERPCore/Dtos/Support/SupportTicketDtos.cs @@ -0,0 +1,56 @@ +using System.ComponentModel.DataAnnotations; +using ERPCore.Domain.Enums; + +namespace ERPCore.Dtos.Support; + +public sealed class CreateSupportTicketRequest +{ + [Required, MaxLength(200)] + public string Subject { get; set; } = string.Empty; + + [Required, MaxLength(2000)] + public string Message { get; set; } = string.Empty; +} + +public sealed class AddSupportTicketMessageRequest +{ + [Required, MaxLength(2000)] + public string Message { get; set; } = string.Empty; +} + +public sealed class UpdateSupportTicketStatusRequest +{ + [Required] + public TicketStatus Status { get; set; } +} + +public sealed record SupportTicketMessageDto( + int MessageId, + int SenderUserId, + string SenderName, + bool IsFromAdmin, + string Message, + DateTime CreatedAt); + +public sealed record SupportTicketSummaryDto( + int TicketId, + string Subject, + TicketStatus Status, + int CreatedBy, + string CreatedByName, + DateTime CreatedAt, + int? UpdatedBy, + DateTime? UpdatedAt, + int MessageCount); + +public sealed record SupportTicketDto( + int TicketId, + string Subject, + TicketStatus Status, + int CreatedBy, + string CreatedByName, + DateTime CreatedAt, + int? UpdatedBy, + string? UpdatedByName, + DateTime? UpdatedAt, + IReadOnlyList Messages); diff --git a/Backend/ERPCore/Dtos/TaxRates/TaxRateDtos.cs b/Backend/ERPCore/Dtos/TaxRates/TaxRateDtos.cs new file mode 100644 index 0000000..0f29b4e --- /dev/null +++ b/Backend/ERPCore/Dtos/TaxRates/TaxRateDtos.cs @@ -0,0 +1,26 @@ +using System.ComponentModel.DataAnnotations; +using ERPCore.Domain.Enums; + +namespace ERPCore.Dtos.TaxRates; + +public sealed record TaxRateDto( + int TaxRateId, string Code, string Name, decimal Percentage, EntityStatus Status, DateTime CreatedAt, DateTime? UpdatedAt); + +public sealed class CreateTaxRateRequest +{ + [Required, StringLength(20)] public string Code { get; set; } = string.Empty; + [Required, StringLength(100)] public string Name { get; set; } = string.Empty; + [Range(0, 100)] public decimal Percentage { get; set; } +} + +public sealed class UpdateTaxRateRequest +{ + [Required, StringLength(20)] public string Code { get; set; } = string.Empty; + [Required, StringLength(100)] public string Name { get; set; } = string.Empty; + [Range(0, 100)] public decimal Percentage { get; set; } +} + +public sealed class UpdateTaxRateStatusRequest +{ + [Required, EnumDataType(typeof(EntityStatus))] public EntityStatus Status { get; set; } +} diff --git a/Backend/ERPCore/Dtos/Uoms/UomDtos.cs b/Backend/ERPCore/Dtos/Uoms/UomDtos.cs index 655fd06..011f9be 100644 --- a/Backend/ERPCore/Dtos/Uoms/UomDtos.cs +++ b/Backend/ERPCore/Dtos/Uoms/UomDtos.cs @@ -1,11 +1,17 @@ using System.ComponentModel.DataAnnotations; +using ERPCore.Domain.Enums; namespace ERPCore.Dtos.Uoms; /// UOM resource (docs/11-BACKEND-PHASE1.md §2.2). -public sealed record UomDto(int UomId, string Name); +public sealed record UomDto(int UomId, string Name, EntityStatus Status, DateTime CreatedAt, DateTime? UpdatedAt); public sealed class CreateUomRequest { [Required, StringLength(50)] public string Name { get; set; } = string.Empty; } + +public sealed class UpdateUomStatusRequest +{ + [Required, EnumDataType(typeof(EntityStatus))] public EntityStatus Status { get; set; } +} diff --git a/Backend/ERPCore/Dtos/Users/UserDtos.cs b/Backend/ERPCore/Dtos/Users/UserDtos.cs index c8d9ead..40fe0e2 100644 --- a/Backend/ERPCore/Dtos/Users/UserDtos.cs +++ b/Backend/ERPCore/Dtos/Users/UserDtos.cs @@ -7,6 +7,15 @@ public sealed record ManagedUserDto( int UserId, string Username, string DisplayName, string? Email, EntityStatus Status, int? RoleId, string? RoleCode, string? RoleName); +/// At least one identifier must be supplied — matches AuthHex's own OR-across-fields dedupe. +public sealed class PurgeAuthHexIdentityRequest +{ + public string? Email { get; set; } + public string? MobileNumber { get; set; } + public string? Nic { get; set; } + public string? UserName { get; set; } +} + /// /// Creates a user in both backends: forwards to AuthHex's `registerUser` (source /// of truth for credentials), then mirrors the account into ERPCore's local diff --git a/Backend/ERPCore/Dtos/Vendors/VendorDtos.cs b/Backend/ERPCore/Dtos/Vendors/VendorDtos.cs index 36c0145..b646dd1 100644 --- a/Backend/ERPCore/Dtos/Vendors/VendorDtos.cs +++ b/Backend/ERPCore/Dtos/Vendors/VendorDtos.cs @@ -6,7 +6,7 @@ namespace ERPCore.Dtos.Vendors; /// Vendor resource (docs/11-BACKEND-PHASE1.md §2.4). public sealed record VendorDto( int VendorId, string Code, string Name, string? Terms, string? TaxReg, - string Currency, EntityStatus Status, DateTime CreatedAt, DateTime? UpdatedAt); + string Currency, EntityStatus Status, int BranchId, DateTime CreatedAt, DateTime? UpdatedAt); public sealed class CreateVendorRequest { @@ -15,6 +15,9 @@ public sealed class CreateVendorRequest [StringLength(50)] public string? Terms { get; set; } [StringLength(50)] public string? TaxReg { get; set; } [Required, StringLength(3, MinimumLength = 3)] public string Currency { get; set; } = "LKR"; + /// Optional — resolved via + /// when branching is enabled; ignored (defaulted) otherwise. + public int BranchId { get; set; } } public sealed class UpdateVendorRequest @@ -24,6 +27,7 @@ public sealed class UpdateVendorRequest [StringLength(50)] public string? Terms { get; set; } [StringLength(50)] public string? TaxReg { get; set; } [Required, StringLength(3, MinimumLength = 3)] public string Currency { get; set; } = "LKR"; + public int BranchId { get; set; } } public sealed class UpdateVendorStatusRequest diff --git a/Backend/ERPCore/Dtos/Warehouses/WarehouseDtos.cs b/Backend/ERPCore/Dtos/Warehouses/WarehouseDtos.cs index 83e15f9..f9fd12d 100644 --- a/Backend/ERPCore/Dtos/Warehouses/WarehouseDtos.cs +++ b/Backend/ERPCore/Dtos/Warehouses/WarehouseDtos.cs @@ -5,7 +5,7 @@ namespace ERPCore.Dtos.Warehouses; /// Warehouse resource (docs/11-BACKEND-PHASE1.md §2.5). is /// the anchor `docs/BRANCH_ISOLATION_PLAN.md` uses to branch-scope everything that carries /// a `warehouseId` (Sales, GRN, stock, ...) without a column on every one of those entities. -public sealed record WarehouseDto(int WarehouseId, string Code, string Name, int BranchId, string? BranchName); +public sealed record WarehouseDto(int WarehouseId, string Code, string Name, string? Address, string? Phone, int BranchId, string? BranchName); /// Bin/location resource (docs/11 §2.5). public sealed record BinDto(int BinId, int WarehouseId, string Code, string? BinType); @@ -14,6 +14,17 @@ public sealed class CreateWarehouseRequest { [Required, StringLength(50)] public string Code { get; set; } = string.Empty; [Required, StringLength(200)] public string Name { get; set; } = string.Empty; + [StringLength(300)] public string? Address { get; set; } + [StringLength(30)] public string? Phone { get; set; } + [Required] public int BranchId { get; set; } +} + +public sealed class UpdateWarehouseRequest +{ + [Required, StringLength(50)] public string Code { get; set; } = string.Empty; + [Required, StringLength(200)] public string Name { get; set; } = string.Empty; + [StringLength(300)] public string? Address { get; set; } + [StringLength(30)] public string? Phone { get; set; } [Required] public int BranchId { get; set; } } diff --git a/Backend/ERPCore/ERPCore.csproj b/Backend/ERPCore/ERPCore.csproj index 77137ac..e6214e4 100644 --- a/Backend/ERPCore/ERPCore.csproj +++ b/Backend/ERPCore/ERPCore.csproj @@ -1,9 +1,10 @@ - + net10.0 enable enable + 48915044-7652-476f-ac84-0c82c718098a diff --git a/Backend/ERPCore/Infra/Auth/AuthHex/AuthHexClient.cs b/Backend/ERPCore/Infra/Auth/AuthHex/AuthHexClient.cs index ef6b616..5a4789e 100644 --- a/Backend/ERPCore/Infra/Auth/AuthHex/AuthHexClient.cs +++ b/Backend/ERPCore/Infra/Auth/AuthHex/AuthHexClient.cs @@ -28,8 +28,13 @@ public sealed class AuthHexClient : IAuthHexClient }; private readonly HttpClient _http; + private readonly IConfiguration _config; - public AuthHexClient(HttpClient http) => _http = http; + public AuthHexClient(HttpClient http, IConfiguration config) + { + _http = http; + _config = config; + } // ---- UserManager -------------------------------------------------- @@ -87,6 +92,19 @@ public sealed class AuthHexClient : IAuthHexClient public Task GetTwoFaStatusAsync(string bearerToken, CancellationToken ct) => CallAsync("user", "getTwoFAStatus", new { }, bearerToken, ct); + public Task DeleteUserAsync(string? email, string? mobileNumber, string? nic, string? username, CancellationToken ct) + { + var adminApiKey = _config["AuthHex:AdminApiKey"]; + if (string.IsNullOrEmpty(adminApiKey)) + throw new DomainException(ErrorCodes.AuthUpstreamError, "AuthHex:AdminApiKey is not configured — cannot call the admin deleteUser function.", 500); + + return CallAsync( + "user", "deleteUser", + new { email, mobileNumber, nic, userName = username }, + null, ct, + extraHeaders: new Dictionary { ["X-Admin-Api-Key"] = adminApiKey }); + } + // ---- RecoveryManager ------------------------------------------------ public Task ForgotPasswordAsync(ForgotPasswordRequest request, CancellationToken ct) @@ -134,11 +152,14 @@ public sealed class AuthHexClient : IAuthHexClient private async Task CallVoidAsync(string routeGroup, string functionName, object payload, string? bearerToken, CancellationToken ct) => await CallAsync(routeGroup, functionName, payload, bearerToken, ct); - private async Task CallAsync(string routeGroup, string functionName, object payload, string? bearerToken, CancellationToken ct) + private async Task CallAsync(string routeGroup, string functionName, object payload, string? bearerToken, CancellationToken ct, Dictionary? extraHeaders = null) { using var httpRequest = new HttpRequestMessage(HttpMethod.Post, $"/api/{routeGroup}"); if (!string.IsNullOrEmpty(bearerToken)) httpRequest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", bearerToken); + if (extraHeaders is not null) + foreach (var (key, value) in extraHeaders) + httpRequest.Headers.Add(key, value); httpRequest.Content = JsonContent.Create( new AuthHexRequestBody { FunctionName = functionName, Payload = payload, Reference = string.Empty }, diff --git a/Backend/ERPCore/Infra/Auth/AuthHex/IAuthHexClient.cs b/Backend/ERPCore/Infra/Auth/AuthHex/IAuthHexClient.cs index cd0f614..db2e1fa 100644 --- a/Backend/ERPCore/Infra/Auth/AuthHex/IAuthHexClient.cs +++ b/Backend/ERPCore/Infra/Auth/AuthHex/IAuthHexClient.cs @@ -30,6 +30,14 @@ public interface IAuthHexClient Task DisableTwoFaAsync(DisableTwoFaRequest request, string bearerToken, CancellationToken ct); Task GetTwoFaStatusAsync(string bearerToken, CancellationToken ct); + /// + /// Admin-only: permanently deletes every AuthHex identity matching any of the given + /// identifiers, so a stale email/NIC/username/mobile no longer blocks re-registration + /// (CanRegisterUser's duplicate check has no notion of "deleted" — this is the only way + /// to actually clear one). Gated by AuthHex:AdminApiKey — throws if unset or rejected. + /// + Task DeleteUserAsync(string? email, string? mobileNumber, string? nic, string? username, CancellationToken ct); + // RecoveryManager (POST /api/recovery) Task ForgotPasswordAsync(ForgotPasswordRequest request, CancellationToken ct); Task VerifyRecoveryOtpAsync(VerifyRecoveryOtpRequest request, CancellationToken ct); diff --git a/Backend/ERPCore/Infra/Auth/AuthHexClaims.cs b/Backend/ERPCore/Infra/Auth/AuthHexClaims.cs index e35400a..325aaa4 100644 --- a/Backend/ERPCore/Infra/Auth/AuthHexClaims.cs +++ b/Backend/ERPCore/Infra/Auth/AuthHexClaims.cs @@ -14,4 +14,12 @@ public static class AuthHexClaims public const string RoleId = "RoleId"; public const string RoleCode = "RoleCode"; public const string Nic = "NIC"; + + /// + /// Local (non-AuthHex) claim injected by — + /// the resolved local user's , used by + /// / for + /// branch-scoped query filtering (docs/BRANCH_ISOLATION_PLAN.md). + /// + public const string BranchId = "erp:BranchId"; } diff --git a/Backend/ERPCore/Infra/Auth/CurrentUser.cs b/Backend/ERPCore/Infra/Auth/CurrentUser.cs index 1d7340a..676e1fb 100644 --- a/Backend/ERPCore/Infra/Auth/CurrentUser.cs +++ b/Backend/ERPCore/Infra/Auth/CurrentUser.cs @@ -35,4 +35,13 @@ public sealed class CurrentUser : ICurrentUser public string? RoleCode => _accessor.HttpContext?.User?.FindFirstValue(AuthHexClaims.RoleCode); public bool IsAdmin => string.Equals(RoleCode?.Trim(), "Admin", StringComparison.OrdinalIgnoreCase); + + public int? BranchId + { + get + { + var raw = _accessor.HttpContext?.User?.FindFirstValue(AuthHexClaims.BranchId); + return int.TryParse(raw, out var id) ? id : null; + } + } } diff --git a/Backend/ERPCore/Infra/Auth/ICurrentBranchContext.cs b/Backend/ERPCore/Infra/Auth/ICurrentBranchContext.cs new file mode 100644 index 0000000..04baab7 --- /dev/null +++ b/Backend/ERPCore/Infra/Auth/ICurrentBranchContext.cs @@ -0,0 +1,34 @@ +namespace ERPCore.Infra.Auth; + +/// +/// Scoped accessor feeding 's global query filters +/// (docs/BRANCH_ISOLATION_PLAN.md — "What this doesn't solve by itself" / enforcement +/// layer). EF Core query filters can't read ambient HTTP state directly, so this is +/// resolved once per request/scope and injected into the DbContext constructor instead. +/// +public interface ICurrentBranchContext +{ + /// The branch to scope reads to. Null means "don't filter" — used for + /// admins, unauthenticated/system contexts, and any caller with no resolved branch. + int? BranchId { get; } + + /// False disables filtering entirely (e.g. background jobs, migrations, + /// admin callers) regardless of . + bool IsActive { get; } +} + +/// +/// Default implementation: derives from . Admins and users with +/// no resolved branch are never filtered — the same bypass +/// already applies for write-path checks. +/// +public sealed class CurrentBranchContext : ICurrentBranchContext +{ + private readonly ICurrentUser _currentUser; + + public CurrentBranchContext(ICurrentUser currentUser) => _currentUser = currentUser; + + public int? BranchId => _currentUser.IsAdmin ? null : _currentUser.BranchId; + + public bool IsActive => _currentUser.IsAuthenticated && !_currentUser.IsAdmin && _currentUser.BranchId is not null; +} diff --git a/Backend/ERPCore/Infra/Auth/ICurrentUser.cs b/Backend/ERPCore/Infra/Auth/ICurrentUser.cs index 78da05e..904df01 100644 --- a/Backend/ERPCore/Infra/Auth/ICurrentUser.cs +++ b/Backend/ERPCore/Infra/Auth/ICurrentUser.cs @@ -29,4 +29,12 @@ public interface ICurrentUser /// the only role that bypasses branch-scoping (see ). /// bool IsAdmin { get; } + + /// + /// The resolved local user's branch (), read from + /// the local claim injected by . Null when the + /// user has no linked employee, is unauthenticated, or is an admin (admins are never scoped — + /// see and ). + /// + int? BranchId { get; } } diff --git a/Backend/ERPCore/Infra/Auth/NavAuthorization.cs b/Backend/ERPCore/Infra/Auth/NavAuthorization.cs new file mode 100644 index 0000000..4be04f4 --- /dev/null +++ b/Backend/ERPCore/Infra/Auth/NavAuthorization.cs @@ -0,0 +1,125 @@ +using ERPCore.Domain.Enums; +using ERPCore.Services.Interfaces; +using Microsoft.AspNetCore.Authorization; +using Microsoft.Extensions.Options; + +namespace ERPCore.Infra.Auth; + +/// +/// Per-endpoint RBAC (docs/02-SECURITY.md AR-01): "can this role reach this module at +/// all", reusing the exact RolePermission data the sidebar already filters on +/// () instead of leaving every controller open to +/// any authenticated user. Apply via [Authorize(Policy = NavPolicies.For("..."))] +/// alongside the base already on +/// — multiple [Authorize] attributes +/// combine as AND, so both must pass. +/// +/// A second, optional layer narrows within a module: appending +/// ":{RolePermissionAction}" (e.g. NavPolicies.Prefix + "procurement:" + +/// NavPolicies.DeleteAction) checks the role's granted RolePermission.Actions +/// bitmask instead of only "can reach this module" — put this on the specific actions +/// (delete, approve, …) a module-level viewer role should not get. Without the suffix the +/// policy stays module-only, matching existing controller-level attributes. +/// +public static class NavPolicies +{ + /// + /// Prepend to a nav-item/sub-nav-item Code (e.g. "procurement", not + /// "NAV:procurement" — the "NAV:" prefix lives on Permission.Code, not here) + /// to get the policy name: NavPolicies.Prefix + "procurement". An attribute + /// argument must be a compile-time constant, so this can't be a method — write the + /// concatenation out at each call site instead of introducing a For(...) helper. + /// + public const string Prefix = "Nav:"; + + /// Separator between the nav code and the action suffix, e.g. "Nav:procurement:Delete". + public const string ActionSeparator = ":"; + + // One const per RolePermissionAction flag, spelled to match Enum.Parse — kept as + // consts (not the enum itself) so call sites stay compile-time-constant attribute args. + public const string CreateAction = "Create"; + public const string EditAction = "Edit"; + public const string DeleteAction = "Delete"; + public const string ApproveAction = "Approve"; +} + +/// The nav module code a request must be permitted for, and optionally the specific +/// action within it — see . +public sealed class NavRequirement : IAuthorizationRequirement +{ + public string NavCode { get; } + public RolePermissionAction? Action { get; } + + public NavRequirement(string navCode, RolePermissionAction? action = null) + { + NavCode = navCode; + Action = action; + } +} + +/// Admin always passes (mirrors every other Admin-bypasses-scoping rule in this +/// codebase, e.g. BranchAccessService); everyone else needs the role permission, +/// and — when the policy names one — the specific action within it too. +public sealed class NavAuthorizationHandler : AuthorizationHandler +{ + private readonly ICurrentUser _currentUser; + private readonly INavPermissionService _navPermissions; + + public NavAuthorizationHandler(ICurrentUser currentUser, INavPermissionService navPermissions) + { + _currentUser = currentUser; + _navPermissions = navPermissions; + } + + protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, NavRequirement requirement) + { + if (!_currentUser.IsAuthenticated) return; + + if (_currentUser.IsAdmin) + { + context.Succeed(requirement); + return; + } + + if (!await _navPermissions.HasAccessAsync(_currentUser.RoleCode, requirement.NavCode)) return; + + if (requirement.Action is null || await _navPermissions.HasActionAsync(_currentUser.RoleCode, requirement.NavCode, requirement.Action.Value)) + context.Succeed(requirement); + } +} + +/// +/// Resolves "Nav:{code}" and "Nav:{code}:{Action}" policy names to a +/// on demand (so a policy doesn't need pre-registering per +/// nav code in AddAuthorization); everything else (notably +/// ) falls through to the framework +/// default provider unchanged. +/// +public sealed class NavPolicyProvider : IAuthorizationPolicyProvider +{ + private readonly DefaultAuthorizationPolicyProvider _fallback; + + public NavPolicyProvider(IOptions options) => _fallback = new DefaultAuthorizationPolicyProvider(options); + + public Task GetDefaultPolicyAsync() => _fallback.GetDefaultPolicyAsync(); + public Task GetFallbackPolicyAsync() => _fallback.GetFallbackPolicyAsync(); + + public Task GetPolicyAsync(string policyName) + { + if (policyName.StartsWith(NavPolicies.Prefix, StringComparison.Ordinal)) + { + var rest = policyName[NavPolicies.Prefix.Length..]; + var sepIndex = rest.LastIndexOf(NavPolicies.ActionSeparator, StringComparison.Ordinal); + + NavRequirement requirement; + if (sepIndex >= 0 && Enum.TryParse(rest[(sepIndex + 1)..], out var action)) + requirement = new NavRequirement(rest[..sepIndex], action); + else + requirement = new NavRequirement(rest); + + var policy = new AuthorizationPolicyBuilder().AddRequirements(requirement).Build(); + return Task.FromResult(policy); + } + return _fallback.GetPolicyAsync(policyName); + } +} diff --git a/Backend/ERPCore/Infra/Auth/ShadowUserClaimsTransformation.cs b/Backend/ERPCore/Infra/Auth/ShadowUserClaimsTransformation.cs index e163895..c98e049 100644 --- a/Backend/ERPCore/Infra/Auth/ShadowUserClaimsTransformation.cs +++ b/Backend/ERPCore/Infra/Auth/ShadowUserClaimsTransformation.cs @@ -37,6 +37,14 @@ public sealed class ShadowUserClaimsTransformation : IClaimsTransformation var localId = await ResolveOrProvisionAsync(authUserId, nic); identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, localId.ToString())); + + var branchId = await _db.Employees.AsNoTracking() + .Where(e => e.UserId == localId) + .Select(e => (int?)e.BranchId) + .FirstOrDefaultAsync(); + if (branchId is not null) + identity.AddClaim(new Claim(AuthHexClaims.BranchId, branchId.Value.ToString())); + return principal; } diff --git a/Backend/ERPCore/Infra/Persistence/Configurations/BatchSerialConfiguration.cs b/Backend/ERPCore/Infra/Persistence/Configurations/BatchSerialConfiguration.cs index 8de6adf..db9ea87 100644 --- a/Backend/ERPCore/Infra/Persistence/Configurations/BatchSerialConfiguration.cs +++ b/Backend/ERPCore/Infra/Persistence/Configurations/BatchSerialConfiguration.cs @@ -13,6 +13,9 @@ public sealed class BatchConfiguration : IEntityTypeConfiguration builder.Property(b => b.BatchNo).IsRequired().HasMaxLength(50); + builder.Property(b => b.Barcode).HasMaxLength(100); + builder.HasIndex(b => b.Barcode).IsUnique(); + builder.HasOne(b => b.Item) .WithMany() .HasForeignKey(b => b.ItemId) @@ -33,6 +36,9 @@ public sealed class SerialConfiguration : IEntityTypeConfiguration builder.Property(s => s.SerialNo).IsRequired().HasMaxLength(100); builder.Property(s => s.Status).IsRequired().HasMaxLength(20); + builder.Property(s => s.Barcode).HasMaxLength(100); + builder.HasIndex(s => s.Barcode).IsUnique(); + builder.HasOne(s => s.Item) .WithMany() .HasForeignKey(s => s.ItemId) diff --git a/Backend/ERPCore/Infra/Persistence/Configurations/CustomerConfiguration.cs b/Backend/ERPCore/Infra/Persistence/Configurations/CustomerConfiguration.cs index a52b327..9b3a8c8 100644 --- a/Backend/ERPCore/Infra/Persistence/Configurations/CustomerConfiguration.cs +++ b/Backend/ERPCore/Infra/Persistence/Configurations/CustomerConfiguration.cs @@ -46,5 +46,9 @@ public sealed class CustomerConfiguration : IEntityTypeConfiguration builder.HasIndex(c => c.Status); builder.HasIndex(c => c.CustomerType); + + builder.HasOne(c => c.Branch).WithMany() + .HasForeignKey(c => c.BranchId).OnDelete(DeleteBehavior.Restrict); + builder.HasIndex(c => c.BranchId); } } diff --git a/Backend/ERPCore/Infra/Persistence/Configurations/ItemConfiguration.cs b/Backend/ERPCore/Infra/Persistence/Configurations/ItemConfiguration.cs index 79d409e..ada84e7 100644 --- a/Backend/ERPCore/Infra/Persistence/Configurations/ItemConfiguration.cs +++ b/Backend/ERPCore/Infra/Persistence/Configurations/ItemConfiguration.cs @@ -15,9 +15,13 @@ public sealed class ItemConfiguration : IEntityTypeConfiguration builder.Property(i => i.Sku).IsRequired().HasMaxLength(50); builder.HasIndex(i => i.Sku).IsUnique(); + // Postgres unique indexes treat multiple NULLs as distinct, so plain IsUnique() is + // correct here — no filter needed for the optional scan code. + builder.Property(i => i.Barcode).HasMaxLength(100); + builder.HasIndex(i => i.Barcode).IsUnique(); + builder.Property(i => i.Name).IsRequired().HasMaxLength(200); builder.Property(i => i.Description).HasMaxLength(1000); - builder.Property(i => i.TaxClass).HasMaxLength(20); // Sales-only fixed selling price; nullable (null ⇒ sell at stock/FIFO value). builder.Property(i => i.SellingMinPrice).HasPrecision(18, 4); @@ -75,6 +79,11 @@ public sealed class ItemConfiguration : IEntityTypeConfiguration .HasForeignKey(i => i.DefaultVendorId) .OnDelete(DeleteBehavior.Restrict); + builder.HasOne(i => i.TaxRate) + .WithMany() + .HasForeignKey(i => i.TaxRateId) + .OnDelete(DeleteBehavior.Restrict); + builder.HasIndex(i => i.Status); builder.HasIndex(i => i.CategoryId); builder.HasIndex(i => i.BrandId); diff --git a/Backend/ERPCore/Infra/Persistence/Configurations/NotificationConfiguration.cs b/Backend/ERPCore/Infra/Persistence/Configurations/NotificationConfiguration.cs new file mode 100644 index 0000000..23776c3 --- /dev/null +++ b/Backend/ERPCore/Infra/Persistence/Configurations/NotificationConfiguration.cs @@ -0,0 +1,26 @@ +using ERPCore.Domain.Entities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace ERPCore.Infra.Persistence.Configurations; + +public sealed class NotificationConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("notifications"); + builder.HasKey(n => n.NotificationId); + + builder.Property(n => n.ModuleKey).IsRequired().HasMaxLength(100); + builder.Property(n => n.Title).IsRequired().HasMaxLength(200); + builder.Property(n => n.Message).IsRequired().HasMaxLength(1000); + builder.Property(n => n.RelatedEntityType).HasMaxLength(100); + + builder.HasIndex(n => n.CreatedAt); + + builder.HasMany(n => n.Recipients) + .WithOne(r => r.Notification) + .HasForeignKey(r => r.NotificationId) + .OnDelete(DeleteBehavior.Cascade); + } +} diff --git a/Backend/ERPCore/Infra/Persistence/Configurations/NotificationRecipientConfiguration.cs b/Backend/ERPCore/Infra/Persistence/Configurations/NotificationRecipientConfiguration.cs new file mode 100644 index 0000000..bca8e11 --- /dev/null +++ b/Backend/ERPCore/Infra/Persistence/Configurations/NotificationRecipientConfiguration.cs @@ -0,0 +1,21 @@ +using ERPCore.Domain.Entities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace ERPCore.Infra.Persistence.Configurations; + +public sealed class NotificationRecipientConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("notification_recipients"); + builder.HasKey(r => r.NotificationRecipientId); + + builder.HasIndex(r => new { r.UserId, r.IsRead, r.NotificationId }); + + builder.HasOne(r => r.User) + .WithMany() + .HasForeignKey(r => r.UserId) + .OnDelete(DeleteBehavior.Cascade); + } +} diff --git a/Backend/ERPCore/Infra/Persistence/Configurations/NumberSequenceConfiguration.cs b/Backend/ERPCore/Infra/Persistence/Configurations/NumberSequenceConfiguration.cs index 45282a2..881b2fe 100644 --- a/Backend/ERPCore/Infra/Persistence/Configurations/NumberSequenceConfiguration.cs +++ b/Backend/ERPCore/Infra/Persistence/Configurations/NumberSequenceConfiguration.cs @@ -12,10 +12,14 @@ public sealed class NumberSequenceConfiguration : IEntityTypeConfiguration s.SequenceId); builder.Property(s => s.DocType).HasColumnName("doc_type").IsRequired().HasMaxLength(10); + builder.Property(s => s.BranchId).HasColumnName("branch_id").IsRequired(); builder.Property(s => s.Year).HasColumnName("year").IsRequired(); builder.Property(s => s.LastNumber).HasColumnName("last_number").IsRequired(); - // One counter per (doc type, year); also the ON CONFLICT target for atomic issue. - builder.HasIndex(s => new { s.DocType, s.Year }).IsUnique(); + builder.HasOne(s => s.Branch).WithMany() + .HasForeignKey(s => s.BranchId).OnDelete(DeleteBehavior.Restrict); + + // One counter per (doc type, branch, year); also the ON CONFLICT target for atomic issue. + builder.HasIndex(s => new { s.DocType, s.BranchId, s.Year }).IsUnique(); } } diff --git a/Backend/ERPCore/Infra/Persistence/Configurations/PermissionConfiguration.cs b/Backend/ERPCore/Infra/Persistence/Configurations/PermissionConfiguration.cs index 2b1bd42..843a3b8 100644 --- a/Backend/ERPCore/Infra/Persistence/Configurations/PermissionConfiguration.cs +++ b/Backend/ERPCore/Infra/Persistence/Configurations/PermissionConfiguration.cs @@ -83,7 +83,8 @@ public sealed class PermissionConfiguration : IEntityTypeConfiguration x.Status); builder.HasIndex(x => x.VendorId); + builder.HasOne(x => x.Branch).WithMany() + .HasForeignKey(x => x.BranchId).OnDelete(DeleteBehavior.Restrict); + builder.HasIndex(x => x.BranchId); + builder.HasMany(x => x.Lines) .WithOne(x => x.PurchaseInvoice) .HasForeignKey(x => x.PurchaseInvoiceId) diff --git a/Backend/ERPCore/Infra/Persistence/Configurations/PurchaseOrderConfiguration.cs b/Backend/ERPCore/Infra/Persistence/Configurations/PurchaseOrderConfiguration.cs index d5f3cd3..9aa8588 100644 --- a/Backend/ERPCore/Infra/Persistence/Configurations/PurchaseOrderConfiguration.cs +++ b/Backend/ERPCore/Infra/Persistence/Configurations/PurchaseOrderConfiguration.cs @@ -38,6 +38,10 @@ public sealed class PurchaseOrderConfiguration : IEntityTypeConfiguration p.Status); builder.HasIndex(p => p.VendorId); + + builder.HasOne(p => p.Branch).WithMany() + .HasForeignKey(p => p.BranchId).OnDelete(DeleteBehavior.Restrict); + builder.HasIndex(p => p.BranchId); } } diff --git a/Backend/ERPCore/Infra/Persistence/Configurations/RequisitionConfiguration.cs b/Backend/ERPCore/Infra/Persistence/Configurations/RequisitionConfiguration.cs index 492d786..06564e2 100644 --- a/Backend/ERPCore/Infra/Persistence/Configurations/RequisitionConfiguration.cs +++ b/Backend/ERPCore/Infra/Persistence/Configurations/RequisitionConfiguration.cs @@ -24,6 +24,10 @@ public sealed class RequisitionConfiguration : IEntityTypeConfiguration r.Status); + + builder.HasOne(r => r.Branch).WithMany() + .HasForeignKey(r => r.BranchId).OnDelete(DeleteBehavior.Restrict); + builder.HasIndex(r => r.BranchId); } } diff --git a/Backend/ERPCore/Infra/Persistence/Configurations/RfqConfiguration.cs b/Backend/ERPCore/Infra/Persistence/Configurations/RfqConfiguration.cs index 6a95ef3..5a65a05 100644 --- a/Backend/ERPCore/Infra/Persistence/Configurations/RfqConfiguration.cs +++ b/Backend/ERPCore/Infra/Persistence/Configurations/RfqConfiguration.cs @@ -22,6 +22,10 @@ public sealed class RfqConfiguration : IEntityTypeConfiguration .WithMany() .HasForeignKey(r => r.RequisitionId) .OnDelete(DeleteBehavior.Restrict); + + builder.HasOne(r => r.Branch).WithMany() + .HasForeignKey(r => r.BranchId).OnDelete(DeleteBehavior.Restrict); + builder.HasIndex(r => r.BranchId); } } diff --git a/Backend/ERPCore/Infra/Persistence/Configurations/RolePermissionConfiguration.cs b/Backend/ERPCore/Infra/Persistence/Configurations/RolePermissionConfiguration.cs index 62c903f..101fb96 100644 --- a/Backend/ERPCore/Infra/Persistence/Configurations/RolePermissionConfiguration.cs +++ b/Backend/ERPCore/Infra/Persistence/Configurations/RolePermissionConfiguration.cs @@ -1,4 +1,5 @@ using ERPCore.Domain.Entities; +using ERPCore.Domain.Enums; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; @@ -11,6 +12,11 @@ public sealed class RolePermissionConfiguration : IEntityTypeConfiguration new { rp.RoleId, rp.PermissionId }); + builder.Property(rp => rp.Actions) + .HasConversion() + .IsRequired() + .HasDefaultValue(RolePermissionAction.All); + builder.HasOne(rp => rp.Role).WithMany() .HasForeignKey(rp => rp.RoleId).OnDelete(DeleteBehavior.Cascade); builder.HasOne(rp => rp.Permission).WithMany() diff --git a/Backend/ERPCore/Infra/Persistence/Configurations/SalesDayEndConfiguration.cs b/Backend/ERPCore/Infra/Persistence/Configurations/SalesDayEndConfiguration.cs index 89211e4..301cfc7 100644 --- a/Backend/ERPCore/Infra/Persistence/Configurations/SalesDayEndConfiguration.cs +++ b/Backend/ERPCore/Infra/Persistence/Configurations/SalesDayEndConfiguration.cs @@ -16,7 +16,10 @@ public sealed class SalesDayEndConfiguration : IEntityTypeConfiguration x.BusinessDate).IsRequired(); - foreach (var p in new[] { nameof(SalesDayEnd.Subtotal), nameof(SalesDayEnd.DiscountTotal), nameof(SalesDayEnd.TaxTotal), nameof(SalesDayEnd.GrandTotal), nameof(SalesDayEnd.CostOfGoodsSold) }) + foreach (var p in new[] { + nameof(SalesDayEnd.Subtotal), nameof(SalesDayEnd.DiscountTotal), nameof(SalesDayEnd.TaxTotal), nameof(SalesDayEnd.GrandTotal), + nameof(SalesDayEnd.PaidTotal), nameof(SalesDayEnd.BalanceTotal), nameof(SalesDayEnd.CostOfGoodsSold) + }) builder.Property(p).HasPrecision(18, 4); builder.Property(x => x.BundleCount).HasDefaultValue(0); diff --git a/Backend/ERPCore/Infra/Persistence/Configurations/SalesSlipConfiguration.cs b/Backend/ERPCore/Infra/Persistence/Configurations/SalesSlipConfiguration.cs index 3d25507..d86c132 100644 --- a/Backend/ERPCore/Infra/Persistence/Configurations/SalesSlipConfiguration.cs +++ b/Backend/ERPCore/Infra/Persistence/Configurations/SalesSlipConfiguration.cs @@ -84,6 +84,16 @@ public sealed class SalesSlipLineConfiguration : IEntityTypeConfiguration x.WarehouseId) .OnDelete(DeleteBehavior.Restrict); + builder.HasOne(x => x.Batch) + .WithMany() + .HasForeignKey(x => x.BatchId) + .OnDelete(DeleteBehavior.Restrict); + + builder.HasOne(x => x.Serial) + .WithMany() + .HasForeignKey(x => x.SerialId) + .OnDelete(DeleteBehavior.Restrict); + builder.Property(x => x.PriceSource).HasMaxLength(50); builder.Property(x => x.RowVersion).IsRowVersion(); } diff --git a/Backend/ERPCore/Infra/Persistence/Configurations/StockCountConfiguration.cs b/Backend/ERPCore/Infra/Persistence/Configurations/StockCountConfiguration.cs index 1aa2979..9f8b870 100644 --- a/Backend/ERPCore/Infra/Persistence/Configurations/StockCountConfiguration.cs +++ b/Backend/ERPCore/Infra/Persistence/Configurations/StockCountConfiguration.cs @@ -42,5 +42,7 @@ public sealed class StockCountLineConfiguration : IEntityTypeConfiguration l.Count).WithMany(c => c.Lines).HasForeignKey(l => l.CountId).OnDelete(DeleteBehavior.Cascade); builder.HasOne(l => l.Item).WithMany().HasForeignKey(l => l.ItemId).OnDelete(DeleteBehavior.Restrict); builder.HasOne().WithMany().HasForeignKey(l => l.BinId).OnDelete(DeleteBehavior.Restrict); + builder.HasOne(l => l.Batch).WithMany().HasForeignKey(l => l.BatchId).OnDelete(DeleteBehavior.Restrict); + builder.HasOne(l => l.Serial).WithMany().HasForeignKey(l => l.SerialId).OnDelete(DeleteBehavior.Restrict); } } diff --git a/Backend/ERPCore/Infra/Persistence/Configurations/SubNavItemConfiguration.cs b/Backend/ERPCore/Infra/Persistence/Configurations/SubNavItemConfiguration.cs index 8eca2f4..5ce6c9e 100644 --- a/Backend/ERPCore/Infra/Persistence/Configurations/SubNavItemConfiguration.cs +++ b/Backend/ERPCore/Infra/Persistence/Configurations/SubNavItemConfiguration.cs @@ -31,6 +31,7 @@ public sealed class SubNavItemConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("support_tickets"); + builder.HasKey(t => t.TicketId); + + builder.Property(t => t.Subject).IsRequired().HasMaxLength(200); + builder.Property(t => t.Status).IsRequired().HasConversion().HasMaxLength(20); + builder.Property(t => t.RowVersion).IsRowVersion(); + + builder.HasIndex(t => t.CreatedBy); + builder.HasIndex(t => t.Status); + + builder.HasMany(t => t.Messages) + .WithOne(m => m.Ticket) + .HasForeignKey(m => m.TicketId) + .OnDelete(DeleteBehavior.Cascade); + } +} diff --git a/Backend/ERPCore/Infra/Persistence/Configurations/SupportTicketMessageConfiguration.cs b/Backend/ERPCore/Infra/Persistence/Configurations/SupportTicketMessageConfiguration.cs new file mode 100644 index 0000000..af7a65d --- /dev/null +++ b/Backend/ERPCore/Infra/Persistence/Configurations/SupportTicketMessageConfiguration.cs @@ -0,0 +1,18 @@ +using ERPCore.Domain.Entities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace ERPCore.Infra.Persistence.Configurations; + +public sealed class SupportTicketMessageConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("support_ticket_messages"); + builder.HasKey(m => m.MessageId); + + builder.Property(m => m.Message).IsRequired().HasMaxLength(2000); + + builder.HasIndex(m => new { m.TicketId, m.CreatedAt }); + } +} diff --git a/Backend/ERPCore/Infra/Persistence/Configurations/TaxRateConfiguration.cs b/Backend/ERPCore/Infra/Persistence/Configurations/TaxRateConfiguration.cs new file mode 100644 index 0000000..1c75659 --- /dev/null +++ b/Backend/ERPCore/Infra/Persistence/Configurations/TaxRateConfiguration.cs @@ -0,0 +1,42 @@ +using ERPCore.Domain.Entities; +using ERPCore.Domain.Enums; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace ERPCore.Infra.Persistence.Configurations; + +public sealed class TaxRateConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("tax_rates"); + builder.HasKey(t => t.TaxRateId); + + builder.Property(t => t.Code).IsRequired().HasMaxLength(20); + builder.HasIndex(t => t.Code).IsUnique(); + + builder.Property(t => t.Name).IsRequired().HasMaxLength(100); + builder.Property(t => t.Percentage).HasPrecision(5, 2); + + builder.Property(t => t.Status) + .HasConversion().HasMaxLength(20).IsRequired() + .HasDefaultValue(EntityStatus.Active); + + builder.Property(t => t.CreatedAt).IsRequired(); + + // PostgreSQL xmin system column as the optimistic concurrency token (ETag). + builder.Property(t => t.RowVersion).IsRowVersion(); + + builder.HasIndex(t => t.Status); + + // Seeded so Item.TaxRateId has something real to point at immediately — codes + // match common VAT/GST categories; admins can rename, add, or retire rates + // afterward (percentages are typically jurisdiction-specific). + var seededAt = new DateTime(2026, 1, 1, 0, 0, 0, DateTimeKind.Utc); + builder.HasData( + new TaxRate { TaxRateId = 1, Code = "STANDARD", Name = "Standard", Percentage = 15m, CreatedAt = seededAt }, + new TaxRate { TaxRateId = 2, Code = "ZERO", Name = "Zero-Rated", Percentage = 0m, CreatedAt = seededAt }, + new TaxRate { TaxRateId = 3, Code = "EXEMPT", Name = "Exempt", Percentage = 0m, CreatedAt = seededAt } + ); + } +} diff --git a/Backend/ERPCore/Infra/Persistence/Configurations/UomConfiguration.cs b/Backend/ERPCore/Infra/Persistence/Configurations/UomConfiguration.cs index 3425885..bb1235f 100644 --- a/Backend/ERPCore/Infra/Persistence/Configurations/UomConfiguration.cs +++ b/Backend/ERPCore/Infra/Persistence/Configurations/UomConfiguration.cs @@ -1,4 +1,5 @@ using ERPCore.Domain.Entities; +using ERPCore.Domain.Enums; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; @@ -13,5 +14,13 @@ public sealed class UomConfiguration : IEntityTypeConfiguration builder.Property(u => u.Name).IsRequired().HasMaxLength(50); builder.HasIndex(u => u.Name).IsUnique(); + + builder.Property(u => u.Status) + .HasConversion().HasMaxLength(20).IsRequired() + .HasDefaultValue(EntityStatus.Active); + + builder.Property(u => u.CreatedAt).IsRequired(); + + builder.HasIndex(u => u.Status); } } diff --git a/Backend/ERPCore/Infra/Persistence/Configurations/VendorConfiguration.cs b/Backend/ERPCore/Infra/Persistence/Configurations/VendorConfiguration.cs index b8dffed..3dc19b5 100644 --- a/Backend/ERPCore/Infra/Persistence/Configurations/VendorConfiguration.cs +++ b/Backend/ERPCore/Infra/Persistence/Configurations/VendorConfiguration.cs @@ -30,5 +30,9 @@ public sealed class VendorConfiguration : IEntityTypeConfiguration builder.Property(v => v.RowVersion).IsRowVersion(); builder.HasIndex(v => v.Status); + + builder.HasOne(v => v.Branch).WithMany() + .HasForeignKey(v => v.BranchId).OnDelete(DeleteBehavior.Restrict); + builder.HasIndex(v => v.BranchId); } } diff --git a/Backend/ERPCore/Infra/Persistence/ErpDbContext.cs b/Backend/ERPCore/Infra/Persistence/ErpDbContext.cs index cf5832b..8f1c0df 100644 --- a/Backend/ERPCore/Infra/Persistence/ErpDbContext.cs +++ b/Backend/ERPCore/Infra/Persistence/ErpDbContext.cs @@ -15,11 +15,13 @@ namespace ERPCore.Infra.Persistence; public class ErpDbContext : DbContext { private readonly ICurrentUser _currentUser; + private readonly ICurrentBranchContext _currentBranch; private bool _writingAuditLogs; - public ErpDbContext(DbContextOptions options, ICurrentUser currentUser) : base(options) + public ErpDbContext(DbContextOptions options, ICurrentUser currentUser, ICurrentBranchContext currentBranch) : base(options) { _currentUser = currentUser; + _currentBranch = currentBranch; } // --- Master Data (docs/10 Part C.1) --- @@ -30,6 +32,7 @@ public class ErpDbContext : DbContext /// Color/Size/Material dimension names. Unlinked to Item by design (docs/10 C.9). public DbSet ItemTypes => Set(); public DbSet Uoms => Set(); + public DbSet TaxRates => Set(); public DbSet Items => Set(); public DbSet ItemReorders => Set(); public DbSet Vendors => Set(); @@ -43,6 +46,12 @@ public class ErpDbContext : DbContext /// Singleton row for notification delivery preferences. public DbSet NotificationConfig => Set(); public DbSet NotificationConfigModules => Set(); + public DbSet Notifications => Set(); + public DbSet NotificationRecipients => Set(); + + /// Help-desk tickets raised from the dashboard Help page. + public DbSet SupportTickets => Set(); + public DbSet SupportTicketMessages => Set(); // --- Cross-cutting (docs/10 Part C.7) --- public DbSet Users => Set(); @@ -176,6 +185,19 @@ public class ErpDbContext : DbContext // (Infra/Persistence/Configurations/*). modelBuilder.ApplyConfigurationsFromAssembly(typeof(ErpDbContext).Assembly); + // Global read-side branch scoping (docs/BRANCH_ISOLATION_PLAN.md). Only for entities + // that carry an explicit BranchId directly — warehouse-inherited entities (Grn, + // StockLayer, StockTransfer, ...) are NOT covered here (would need an extra join in + // the filter) and remain a follow-up. !IsActive short-circuits for admins/system + // contexts so the filter becomes a no-op rather than excluding everything. + modelBuilder.Entity().HasQueryFilter(e => !_currentBranch.IsActive || e.BranchId == _currentBranch.BranchId); + modelBuilder.Entity().HasQueryFilter(e => !_currentBranch.IsActive || e.BranchId == _currentBranch.BranchId); + modelBuilder.Entity().HasQueryFilter(e => !_currentBranch.IsActive || e.BranchId == _currentBranch.BranchId); + modelBuilder.Entity().HasQueryFilter(e => !_currentBranch.IsActive || e.BranchId == _currentBranch.BranchId); + modelBuilder.Entity().HasQueryFilter(e => !_currentBranch.IsActive || e.BranchId == _currentBranch.BranchId); + modelBuilder.Entity().HasQueryFilter(e => !_currentBranch.IsActive || e.BranchId == _currentBranch.BranchId); + modelBuilder.Entity().HasQueryFilter(e => !_currentBranch.IsActive || e.BranchId == _currentBranch.BranchId); + // Npgsql requires DateTime values written to `timestamp with time zone` columns // to have Kind=Utc; dates deserialized from a JSON request body (hire date, // salary-structure effective date, etc.) come in as Kind=Unspecified and would diff --git a/Backend/ERPCore/Migrations/20260914061147_AddNotificationFeed.Designer.cs b/Backend/ERPCore/Migrations/20260914061147_AddNotificationFeed.Designer.cs new file mode 100644 index 0000000..d9e9544 --- /dev/null +++ b/Backend/ERPCore/Migrations/20260914061147_AddNotificationFeed.Designer.cs @@ -0,0 +1,8324 @@ +// +using System; +using ERPCore.Infra.Persistence; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace ERPCore.Migrations +{ + [DbContext(typeof(ErpDbContext))] + [Migration("20260914061147_AddNotificationFeed")] + partial class AddNotificationFeed + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.9") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceRecord", b => + { + b.Property("AttendanceRecordId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AttendanceRecordId")); + + b.Property("AttendanceDate") + .HasColumnType("timestamp with time zone"); + + b.Property("AttendanceStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("AttendanceUploadBatchId") + .HasColumnType("integer"); + + b.Property("CheckIn") + .HasColumnType("interval"); + + b.Property("CheckOut") + .HasColumnType("interval"); + + b.Property("DuplicateOfAttendanceRecordId") + .HasColumnType("integer"); + + b.Property("EarlyLeaveMinutes") + .HasColumnType("integer"); + + b.Property("EditedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EditedBy") + .HasColumnType("integer"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("IsManualOverride") + .HasColumnType("boolean"); + + b.Property("LateMinutes") + .HasColumnType("integer"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("OvertimeMinutes") + .HasColumnType("integer"); + + b.Property("RowValidationStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("WorkShiftId") + .HasColumnType("integer"); + + b.Property("WorkingMinutes") + .HasColumnType("integer"); + + b.HasKey("AttendanceRecordId"); + + b.HasIndex("AttendanceUploadBatchId"); + + b.HasIndex("WorkShiftId"); + + b.HasIndex("EmployeeId", "AttendanceDate"); + + b.ToTable("hr_attendance_records", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceUploadBatch", b => + { + b.Property("AttendanceUploadBatchId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AttendanceUploadBatchId")); + + b.Property("ConfirmedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ConfirmedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("OriginalFileName") + .HasMaxLength(260) + .HasColumnType("character varying(260)"); + + b.Property("PeriodEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("PeriodStart") + .HasColumnType("timestamp with time zone"); + + b.Property("RowCountDuplicate") + .HasColumnType("integer"); + + b.Property("RowCountError") + .HasColumnType("integer"); + + b.Property("RowCountTotal") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SourceType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UploadedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UploadedBy") + .HasColumnType("integer"); + + b.HasKey("AttendanceUploadBatchId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("PeriodStart", "PeriodEnd"); + + b.ToTable("hr_attendance_upload_batches", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AuditLog", b => + { + b.Property("AuditId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AuditId")); + + b.Property("Action") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("ChangeSet") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EntityId") + .HasColumnType("integer"); + + b.Property("EntityType") + .IsRequired() + .HasMaxLength(80) + .HasColumnType("character varying(80)"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("AuditId"); + + b.HasIndex("CreatedAt"); + + b.HasIndex("UserId"); + + b.HasIndex("EntityType", "EntityId"); + + b.ToTable("audit_logs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Batch", b => + { + b.Property("BatchId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BatchId")); + + b.Property("BatchNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ExpiryDate") + .HasColumnType("date"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.HasKey("BatchId"); + + b.HasIndex("ItemId", "BatchNo") + .IsUnique(); + + b.ToTable("batches", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Bin", b => + { + b.Property("BinId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BinId")); + + b.Property("BinType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BinId"); + + b.HasIndex("WarehouseId", "Code") + .IsUnique(); + + b.ToTable("bins", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Branch", b => + { + b.Property("BranchId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BranchId")); + + b.Property("Address") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("PhoneNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_branches", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BranchConfig", b => + { + b.Property("ConfigId") + .HasColumnType("integer"); + + b.Property("BranchingEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.HasKey("ConfigId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("branch_config", null, t => + { + t.HasCheckConstraint("ck_branch_config_singleton", "\"ConfigId\" = 1"); + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Brand", b => + { + b.Property("BrandId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BrandId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("BrandId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("brands", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSale", b => + { + b.Property("BundleSaleId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleId")); + + b.Property("BundleCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BundleDate") + .HasColumnType("timestamp with time zone"); + + b.Property("BundleName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("BundleNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BundlePrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BundleSaleTemplateId") + .HasColumnType("integer"); + + b.Property("CashierUserId") + .HasColumnType("integer"); + + b.Property("ComponentSubtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("CustomerSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DayEndId") + .HasColumnType("integer"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("MarginAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BundleSaleId"); + + b.HasIndex("BundleNo") + .IsUnique(); + + b.HasIndex("BundleSaleTemplateId"); + + b.HasIndex("CashierUserId"); + + b.HasIndex("CustomerId"); + + b.HasIndex("DayEndId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("bundle_sales", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleLine", b => + { + b.Property("BundleSaleLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleLineId")); + + b.Property("BundleSaleId") + .HasColumnType("integer"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("IncludeInBundle") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("IsComponent") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ParentLineId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BundleSaleLineId"); + + b.HasIndex("BundleSaleId"); + + b.HasIndex("ItemId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("bundle_sale_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplate", b => + { + b.Property("BundleSaleTemplateId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleTemplateId")); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TemplateCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("TemplateName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("BundleSaleTemplateId"); + + b.HasIndex("TemplateCode") + .IsUnique(); + + b.ToTable("bundle_sale_templates", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplateLine", b => + { + b.Property("BundleSaleTemplateLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleTemplateLineId")); + + b.Property("BundleSaleTemplateId") + .HasColumnType("integer"); + + b.Property("IncludeInBundle") + .HasColumnType("boolean"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SortOrder") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BundleSaleTemplateLineId"); + + b.HasIndex("BundleSaleTemplateId"); + + b.HasIndex("ItemId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("bundle_sale_template_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Category", b => + { + b.Property("CategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CategoryId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("CategoryId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("categories", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Customer", b => + { + b.Property("CustomerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CustomerId")); + + b.Property("AddressLine1") + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("AddressLine2") + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("City") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Country") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreditDays") + .HasColumnType("integer"); + + b.Property("CreditLimit") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CustomerCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CustomerType") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("B2C"); + + b.Property("DefaultWarehouseId") + .HasColumnType("integer"); + + b.Property("DisplayName") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Email") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Phone") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TaxRegistrationNo") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("CustomerId"); + + b.HasIndex("CustomerCode") + .IsUnique(); + + b.HasIndex("CustomerType"); + + b.HasIndex("DefaultWarehouseId"); + + b.HasIndex("Status"); + + b.ToTable("customers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Department", b => + { + b.Property("DepartmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("DepartmentId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("HeadEmployeeId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("ParentDepartmentId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("DepartmentId"); + + b.HasIndex("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("HeadEmployeeId"); + + b.HasIndex("ParentDepartmentId"); + + b.HasIndex("Status"); + + b.ToTable("hr_departments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Designation", b => + { + b.Property("DesignationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("DesignationId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("DesignationId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_designations", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Employee", b => + { + b.Property("EmployeeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeId")); + + b.Property("AddressLine1") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("AddressLine2") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("City") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ConfirmationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Country") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DateOfBirth") + .HasColumnType("timestamp with time zone"); + + b.Property("DepartmentId") + .HasColumnType("integer"); + + b.Property("DesignationId") + .HasColumnType("integer"); + + b.Property("Email") + .HasMaxLength(320) + .HasColumnType("character varying(320)"); + + b.Property("EmergencyContactName") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("EmergencyContactPhone") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmergencyContactRelationship") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("EmployeeCode") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmploymentTypeId") + .HasColumnType("integer"); + + b.Property("EpfNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EtfNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Gender") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("HireDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LastWorkingDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Nationality") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Nic") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PersonalMobile") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PostalCode") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ProfilePhotoPath") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("ReportingManagerId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TaxIdentificationNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.Property("WorkShiftId") + .HasColumnType("integer"); + + b.HasKey("EmployeeId"); + + b.HasIndex("BranchId"); + + b.HasIndex("DepartmentId"); + + b.HasIndex("DesignationId"); + + b.HasIndex("Email"); + + b.HasIndex("EmployeeCode") + .IsUnique(); + + b.HasIndex("EmploymentTypeId"); + + b.HasIndex("ReportingManagerId"); + + b.HasIndex("Status"); + + b.HasIndex("UserId") + .IsUnique(); + + b.HasIndex("WorkShiftId"); + + b.ToTable("hr_employees", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeBankDetail", b => + { + b.Property("EmployeeBankDetailId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeBankDetailId")); + + b.Property("AccountHolderName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("AccountNumber") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BankName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("BranchName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("IsPrimary") + .HasColumnType("boolean"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("SwiftCode") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("EmployeeBankDetailId"); + + b.HasIndex("EmployeeId"); + + b.ToTable("hr_employee_bank_details", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeDocument", b => + { + b.Property("EmployeeDocumentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeDocumentId")); + + b.Property("ContentType") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("ExpiryDate") + .HasColumnType("timestamp with time zone"); + + b.Property("HrDocumentTypeId") + .HasColumnType("integer"); + + b.Property("IssueDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("OriginalFileName") + .IsRequired() + .HasMaxLength(260) + .HasColumnType("character varying(260)"); + + b.Property("RelativePath") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SizeBytes") + .HasColumnType("bigint"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("StoredFileName") + .IsRequired() + .HasMaxLength(260) + .HasColumnType("character varying(260)"); + + b.Property("UploadedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UploadedBy") + .HasColumnType("integer"); + + b.Property("VerifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VerifiedBy") + .HasColumnType("integer"); + + b.HasKey("EmployeeDocumentId"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("ExpiryDate"); + + b.HasIndex("HrDocumentTypeId"); + + b.ToTable("hr_employee_documents", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeLoan", b => + { + b.Property("EmployeeLoanId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeLoanId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("InstallmentAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("InterestRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("LoanKind") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("NumberOfInstallments") + .HasColumnType("integer"); + + b.Property("OutstandingBalance") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("PrincipalAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("StartMonth") + .HasColumnType("integer"); + + b.Property("StartYear") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("EmployeeLoanId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("EmployeeId"); + + b.HasIndex("Status"); + + b.ToTable("hr_employee_loans", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructure", b => + { + b.Property("EmployeeSalaryStructureId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeSalaryStructureId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("BasicSalary") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("Currency") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("character varying(3)"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveTo") + .HasColumnType("timestamp with time zone"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("EmployeeSalaryStructureId"); + + b.HasIndex("EmployeeId", "EffectiveTo"); + + b.ToTable("hr_employee_salary_structures", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructureLine", b => + { + b.Property("EmployeeSalaryStructureLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeSalaryStructureLineId")); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("EmployeeSalaryStructureId") + .HasColumnType("integer"); + + b.Property("SalaryComponentId") + .HasColumnType("integer"); + + b.HasKey("EmployeeSalaryStructureLineId"); + + b.HasIndex("EmployeeSalaryStructureId"); + + b.HasIndex("SalaryComponentId"); + + b.ToTable("hr_employee_salary_structure_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmploymentType", b => + { + b.Property("EmploymentTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmploymentTypeId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("EmploymentTypeId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_employment_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Grn", b => + { + b.Property("GrnId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("GrnId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PoId") + .HasColumnType("integer"); + + b.Property("PostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PurchaseInvoiceId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("GrnId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("PoId"); + + b.HasIndex("PurchaseInvoiceId"); + + b.HasIndex("Status"); + + b.HasIndex("VendorId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("grns", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLine", b => + { + b.Property("GrnLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("GrnLineId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("DiscountPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("GrnId") + .HasColumnType("integer"); + + b.Property("HoldStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("NetUnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("PoLineId") + .HasColumnType("integer"); + + b.Property("PoUnitPrice") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReceivedValue") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("VatAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("VatPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.HasKey("GrnLineId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("GrnId"); + + b.HasIndex("ItemId"); + + b.HasIndex("PoLineId"); + + b.ToTable("grn_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLineWarrantyNumber", b => + { + b.Property("GrnLineWarrantyNumberId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("GrnLineWarrantyNumberId")); + + b.Property("GrnLineId") + .HasColumnType("integer"); + + b.Property("WarrantyNo") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("WarrantyPeriodMonths") + .HasColumnType("integer"); + + b.HasKey("GrnLineWarrantyNumberId"); + + b.HasIndex("GrnLineId", "WarrantyNo") + .IsUnique(); + + b.ToTable("grn_line_warranty_numbers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.HrDocumentType", b => + { + b.Property("HrDocumentTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("HrDocumentTypeId")); + + b.Property("Category") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpiryTracked") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RequiredAtOnboarding") + .HasColumnType("boolean"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("HrDocumentTypeId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_document_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Item", b => + { + b.Property("ItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ItemId")); + + b.Property("BaseUomId") + .HasColumnType("integer"); + + b.Property("BrandId") + .HasColumnType("integer"); + + b.Property("CategoryId") + .HasColumnType("integer"); + + b.Property("ContentBaseQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ContentBaseUnit") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ContentQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ContentUnit") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DefaultVendorId") + .HasColumnType("integer"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SellingFlatPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SellingMaxPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SellingMinPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Sku") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("StockNature") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("SubCategoryId") + .HasColumnType("integer"); + + b.Property("TaxClass") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("TrackingMode") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Warranty") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("NonWarranty"); + + b.Property("WarrantyPeriodMonths") + .HasColumnType("integer"); + + b.HasKey("ItemId"); + + b.HasIndex("BaseUomId"); + + b.HasIndex("BrandId"); + + b.HasIndex("CategoryId"); + + b.HasIndex("DefaultVendorId"); + + b.HasIndex("Sku") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("SubCategoryId"); + + b.ToTable("items", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ItemReorder", b => + { + b.Property("ReorderId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReorderId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("ReorderPoint") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReorderQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("ReorderId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("ItemId", "WarehouseId") + .IsUnique(); + + b.ToTable("item_reorders", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ItemType", b => + { + b.Property("ItemTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ItemTypeId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsMeasurable") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("ItemTypeId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("item_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.JournalEntryStub", b => + { + b.Property("JournalId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("JournalId")); + + b.Property("Amount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CreditAccount") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("DebitAccount") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("SourceDocId") + .HasColumnType("integer"); + + b.Property("SourceDocType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.HasKey("JournalId"); + + b.HasIndex("SourceDocType", "SourceDocId"); + + b.ToTable("journal_entry_stubs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveBalance", b => + { + b.Property("LeaveBalanceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LeaveBalanceId")); + + b.Property("AdjustmentDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("CarriedForwardDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("EntitledDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("LeaveTypeId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("TakenDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Year") + .HasColumnType("integer"); + + b.HasKey("LeaveBalanceId"); + + b.HasIndex("LeaveTypeId"); + + b.HasIndex("EmployeeId", "LeaveTypeId", "Year") + .IsUnique(); + + b.ToTable("hr_leave_balances", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveRequest", b => + { + b.Property("LeaveRequestId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LeaveRequestId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DaysCount") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("EndDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LeaveTypeId") + .HasColumnType("integer"); + + b.Property("Reason") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("RejectionReason") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("StartDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("LeaveRequestId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("EmployeeId"); + + b.HasIndex("LeaveTypeId"); + + b.HasIndex("Status"); + + b.HasIndex("StartDate", "EndDate"); + + b.ToTable("hr_leave_requests", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveType", b => + { + b.Property("LeaveTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LeaveTypeId")); + + b.Property("AccrualPerYear") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("CarryForwardAllowed") + .HasColumnType("boolean"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CountsAsNoPay") + .HasColumnType("boolean"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsPaid") + .HasColumnType("boolean"); + + b.Property("MaxCarryForwardDays") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RequiresApproval") + .HasColumnType("boolean"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("LeaveTypeId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_leave_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoanInstallment", b => + { + b.Property("LoanInstallmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LoanInstallmentId")); + + b.Property("DueMonth") + .HasColumnType("integer"); + + b.Property("DueYear") + .HasColumnType("integer"); + + b.Property("EmployeeLoanId") + .HasColumnType("integer"); + + b.Property("InstallmentNumber") + .HasColumnType("integer"); + + b.Property("PaidAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("PayrollRunId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("ScheduledAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("LoanInstallmentId"); + + b.HasIndex("EmployeeLoanId"); + + b.HasIndex("PayrollRunId"); + + b.HasIndex("DueYear", "DueMonth"); + + b.ToTable("hr_loan_installments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoginActivity", b => + { + b.Property("LoginActivityId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LoginActivityId")); + + b.Property("DeviceLabel") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("IpAddress") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("LoginAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserAgent") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("LoginActivityId"); + + b.HasIndex("UserId", "LoginAt"); + + b.ToTable("login_activities", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NavItem", b => + { + b.Property("NavItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NavItemId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Href") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Icon") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.HasKey("NavItemId"); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("nav_items", (string)null); + + b.HasData( + new + { + NavItemId = 1, + Code = "dashboard", + Href = "/dashboard", + Label = "Dashboard", + SortOrder = 1, + Status = "Active" + }, + new + { + NavItemId = 2, + Code = "products", + Href = "/dashboard/products", + Label = "Products", + SortOrder = 2, + Status = "Active" + }, + new + { + NavItemId = 4, + Code = "procurement", + Href = "/dashboard/procurement", + Label = "Procurement", + SortOrder = 4, + Status = "Active" + }, + new + { + NavItemId = 5, + Code = "receiving", + Href = "/dashboard/receiving/grn", + Label = "Receiving", + SortOrder = 5, + Status = "Active" + }, + new + { + NavItemId = 6, + Code = "stock", + Href = "/dashboard/stock", + Label = "Stock", + SortOrder = 6, + Status = "Active" + }, + new + { + NavItemId = 7, + Code = "warehouses", + Href = "/dashboard/warehouse", + Label = "Warehouses", + SortOrder = 7, + Status = "Active" + }, + new + { + NavItemId = 8, + Code = "orders", + Href = "/dashboard/orders", + Label = "Orders", + SortOrder = 8, + Status = "Active" + }, + new + { + NavItemId = 9, + Code = "settings", + Href = "/dashboard/settings", + Label = "Settings", + SortOrder = 9, + Status = "Active" + }, + new + { + NavItemId = 10, + Code = "help", + Href = "/dashboard/help", + Label = "Help", + SortOrder = 10, + Status = "Active" + }, + new + { + NavItemId = 11, + Code = "ledgers", + Href = "/dashboard/ledgers", + Label = "Ledgers", + SortOrder = 11, + Status = "Active" + }, + new + { + NavItemId = 12, + Code = "accounts", + Href = "/dashboard/accounts", + Label = "Accounts", + SortOrder = 12, + Status = "Active" + }, + new + { + NavItemId = 13, + Code = "sales", + Href = "/dashboard/sales", + Label = "Sales", + SortOrder = 13, + Status = "Active" + }, + new + { + NavItemId = 14, + Code = "production", + Href = "/dashboard/production", + Label = "Production", + SortOrder = 14, + Status = "Active" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Notification", b => + { + b.Property("NotificationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NotificationId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("ModuleKey") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("RelatedEntityId") + .HasColumnType("integer"); + + b.Property("RelatedEntityType") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.HasKey("NotificationId"); + + b.HasIndex("CreatedAt"); + + b.ToTable("notifications", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => + { + b.Property("NotificationConfigId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.HasKey("NotificationConfigId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("notification_config", null, t => + { + t.HasCheckConstraint("ck_notification_config_singleton", "\"NotificationConfigId\" = 1"); + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfigModule", b => + { + b.Property("NotificationConfigModuleId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NotificationConfigModuleId")); + + b.Property("EmailEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("InAppEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("ModuleKey") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("NotificationConfigId") + .HasColumnType("integer"); + + b.Property("SmsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.HasKey("NotificationConfigModuleId"); + + b.HasIndex("ModuleKey") + .IsUnique(); + + b.HasIndex("NotificationConfigId"); + + b.ToTable("notification_config_modules", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationRecipient", b => + { + b.Property("NotificationRecipientId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NotificationRecipientId")); + + b.Property("IsRead") + .HasColumnType("boolean"); + + b.Property("NotificationId") + .HasColumnType("integer"); + + b.Property("ReadAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("NotificationRecipientId"); + + b.HasIndex("NotificationId"); + + b.HasIndex("UserId", "IsRead", "NotificationId"); + + b.ToTable("notification_recipients", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NumberSequence", b => + { + b.Property("SequenceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SequenceId")); + + b.Property("DocType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("doc_type"); + + b.Property("LastNumber") + .HasColumnType("integer") + .HasColumnName("last_number"); + + b.Property("Year") + .HasColumnType("integer") + .HasColumnName("year"); + + b.HasKey("SequenceId"); + + b.HasIndex("DocType", "Year") + .IsUnique(); + + b.ToTable("number_sequences", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => + { + b.Property("PayrollLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollLineId")); + + b.Property("AbsentDays") + .HasColumnType("integer"); + + b.Property("BasicSalary") + .HasColumnType("numeric(18,2)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("EpfEmployeeAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("EpfEmployerAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("EtfEmployerAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("GrossSalary") + .HasColumnType("numeric(18,2)"); + + b.Property("LateDeductionAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("LateMinutesTotal") + .HasColumnType("integer"); + + b.Property("LeaveDays") + .HasColumnType("integer"); + + b.Property("LoanDeductionAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("NetSalary") + .HasColumnType("numeric(18,2)"); + + b.Property("NoPayAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("OtMinutesTotal") + .HasColumnType("integer"); + + b.Property("OtherDeductionsAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("OvertimeAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("PayrollRunId") + .HasColumnType("integer"); + + b.Property("PresentDays") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("TaxAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("TotalAllowances") + .HasColumnType("numeric(18,2)"); + + b.Property("WorkingDays") + .HasColumnType("integer"); + + b.HasKey("PayrollLineId"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("PayrollRunId", "EmployeeId") + .IsUnique(); + + b.ToTable("hr_payroll_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLineComponent", b => + { + b.Property("PayrollLineComponentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollLineComponentId")); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("ComponentCategory") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("PayrollLineId") + .HasColumnType("integer"); + + b.Property("SalaryComponentId") + .HasColumnType("integer"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.HasKey("PayrollLineComponentId"); + + b.HasIndex("PayrollLineId"); + + b.HasIndex("SalaryComponentId"); + + b.ToTable("hr_payroll_line_components", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollRun", b => + { + b.Property("PayrollRunId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollRunId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GeneratedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GeneratedBy") + .HasColumnType("integer"); + + b.Property("LockedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("LockedBy") + .HasColumnType("integer"); + + b.Property("PeriodMonth") + .HasColumnType("integer"); + + b.Property("PeriodYear") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UnlockReason") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("UnlockedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UnlockedBy") + .HasColumnType("integer"); + + b.HasKey("PayrollRunId"); + + b.HasIndex("BranchId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("PeriodYear", "PeriodMonth", "BranchId"); + + b.ToTable("hr_payroll_runs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollStatutorySetting", b => + { + b.Property("PayrollStatutorySettingId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollStatutorySettingId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveTo") + .HasColumnType("timestamp with time zone"); + + b.Property("EpfEmployeeRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("EpfEmployerRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("EtfEmployerRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("OtMultiplierDefault") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.HasKey("PayrollStatutorySettingId"); + + b.HasIndex("EffectiveFrom"); + + b.ToTable("hr_payroll_statutory_settings", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Payslip", b => + { + b.Property("PayslipId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayslipId")); + + b.Property("GeneratedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PayrollLineId") + .HasColumnType("integer"); + + b.Property("ReleasedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReleasedBy") + .HasColumnType("integer"); + + b.HasKey("PayslipId"); + + b.HasIndex("PayrollLineId") + .IsUnique(); + + b.ToTable("hr_payslips", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Permission", b => + { + b.Property("PermissionId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PermissionId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(80) + .HasColumnType("character varying(80)"); + + b.Property("NavItemId") + .HasColumnType("integer"); + + b.Property("SubNavItemId") + .HasColumnType("integer"); + + b.HasKey("PermissionId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("NavItemId"); + + b.HasIndex("SubNavItemId"); + + b.ToTable("permissions", (string)null); + + b.HasData( + new + { + PermissionId = 1, + Code = "NAV:dashboard", + NavItemId = 1 + }, + new + { + PermissionId = 2, + Code = "NAV:products", + NavItemId = 2 + }, + new + { + PermissionId = 3, + Code = "NAV:procurement.vendors", + SubNavItemId = 30 + }, + new + { + PermissionId = 4, + Code = "NAV:procurement", + NavItemId = 4 + }, + new + { + PermissionId = 5, + Code = "NAV:receiving", + NavItemId = 5 + }, + new + { + PermissionId = 6, + Code = "NAV:stock", + NavItemId = 6 + }, + new + { + PermissionId = 7, + Code = "NAV:warehouses", + NavItemId = 7 + }, + new + { + PermissionId = 8, + Code = "NAV:orders", + NavItemId = 8 + }, + new + { + PermissionId = 9, + Code = "NAV:settings", + NavItemId = 9 + }, + new + { + PermissionId = 10, + Code = "NAV:help", + NavItemId = 10 + }, + new + { + PermissionId = 11, + Code = "NAV:products.item", + SubNavItemId = 1 + }, + new + { + PermissionId = 12, + Code = "NAV:products.category", + SubNavItemId = 2 + }, + new + { + PermissionId = 13, + Code = "NAV:products.brand", + SubNavItemId = 3 + }, + new + { + PermissionId = 14, + Code = "NAV:products.item-type", + SubNavItemId = 4 + }, + new + { + PermissionId = 15, + Code = "NAV:products.uom", + SubNavItemId = 5 + }, + new + { + PermissionId = 16, + Code = "NAV:products.configuration", + SubNavItemId = 6 + }, + new + { + PermissionId = 17, + Code = "NAV:settings.roles", + SubNavItemId = 7 + }, + new + { + PermissionId = 18, + Code = "NAV:settings.users", + SubNavItemId = 8 + }, + new + { + PermissionId = 28, + Code = "NAV:procurement.requisitions", + SubNavItemId = 17 + }, + new + { + PermissionId = 29, + Code = "NAV:procurement.rfqs", + SubNavItemId = 18 + }, + new + { + PermissionId = 30, + Code = "NAV:procurement.purchase-orders", + SubNavItemId = 19 + }, + new + { + PermissionId = 31, + Code = "NAV:procurement.purchase-returns", + SubNavItemId = 20 + }, + new + { + PermissionId = 19, + Code = "NAV:ledgers", + NavItemId = 11 + }, + new + { + PermissionId = 20, + Code = "NAV:ledgers.trial-balance", + SubNavItemId = 9 + }, + new + { + PermissionId = 21, + Code = "NAV:ledgers.balance-sheet", + SubNavItemId = 10 + }, + new + { + PermissionId = 22, + Code = "NAV:ledgers.general-ledger", + SubNavItemId = 11 + }, + new + { + PermissionId = 23, + Code = "NAV:ledgers.profit-and-loss", + SubNavItemId = 12 + }, + new + { + PermissionId = 24, + Code = "NAV:ledgers.cash-flow", + SubNavItemId = 13 + }, + new + { + PermissionId = 25, + Code = "NAV:ledgers.budget-vs-actual", + SubNavItemId = 14 + }, + new + { + PermissionId = 27, + Code = "NAV:ledgers.tax-report", + SubNavItemId = 16 + }, + new + { + PermissionId = 26, + Code = "NAV:accounts.bank-accounts", + SubNavItemId = 15 + }, + new + { + PermissionId = 32, + Code = "NAV:accounts", + NavItemId = 12 + }, + new + { + PermissionId = 33, + Code = "NAV:accounts.cheque-books", + SubNavItemId = 21 + }, + new + { + PermissionId = 34, + Code = "NAV:accounts.received-cheques", + SubNavItemId = 22 + }, + new + { + PermissionId = 35, + Code = "NAV:production", + NavItemId = 14 + }, + new + { + PermissionId = 36, + Code = "NAV:production.templates", + SubNavItemId = 27 + }, + new + { + PermissionId = 37, + Code = "NAV:production.runs", + SubNavItemId = 25 + }, + new + { + PermissionId = 38, + Code = "NAV:production.produced", + SubNavItemId = 26 + }, + new + { + PermissionId = 39, + Code = "NAV:procurement.purchase-invoices", + SubNavItemId = 28 + }, + new + { + PermissionId = 40, + Code = "NAV:settings.branches", + SubNavItemId = 29 + }, + new + { + PermissionId = 41, + Code = "NAV:stock.ledger", + SubNavItemId = 31 + }, + new + { + PermissionId = 42, + Code = "NAV:stock.enquiry", + SubNavItemId = 32 + }, + new + { + PermissionId = 43, + Code = "NAV:stock.valuation", + SubNavItemId = 33 + }, + new + { + PermissionId = 44, + Code = "NAV:stock.transfers", + SubNavItemId = 34 + }, + new + { + PermissionId = 45, + Code = "NAV:stock.adjustments", + SubNavItemId = 35 + }, + new + { + PermissionId = 46, + Code = "NAV:stock.counts", + SubNavItemId = 36 + }, + new + { + PermissionId = 47, + Code = "NAV:stock.reorder-alerts", + SubNavItemId = 37 + }, + new + { + PermissionId = 48, + Code = "NAV:stock.wastage", + SubNavItemId = 38 + }, + new + { + PermissionId = 49, + Code = "NAV:sales.bundle-templates", + SubNavItemId = 23 + }, + new + { + PermissionId = 50, + Code = "NAV:sales.invoices", + SubNavItemId = 40 + }, + new + { + PermissionId = 51, + Code = "NAV:sales.free-issues", + SubNavItemId = 41 + }, + new + { + PermissionId = 52, + Code = "NAV:sales.day-end", + SubNavItemId = 42 + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PoLine", b => + { + b.Property("PoLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PoLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("PoId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyReceived") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Tax") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("PoLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("PoId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("po_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductConfig", b => + { + b.Property("ConfigId") + .HasColumnType("integer"); + + b.Property("BatchListsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("BrandsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("ItemTypesEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SellingPricesEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("SerialNumbersEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("SubcategoriesEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.Property("WarrantyPeriodsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.HasKey("ConfigId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("product_config", null, t => + { + t.HasCheckConstraint("ck_product_config_singleton", "\"ConfigId\" = 1"); + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b => + { + b.Property("RunId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunId")); + + b.Property("CancelReasonCodeId") + .HasColumnType("integer"); + + b.Property("CompletedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("OutputBinId") + .HasColumnType("integer"); + + b.Property("ReworkCount") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("ScaleFactor") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("TargetQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TemplateId") + .HasColumnType("integer"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("RunId"); + + b.HasIndex("CancelReasonCodeId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("OutputBinId"); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("TemplateId", "Status"); + + b.ToTable("production_runs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionTemplate", b => + { + b.Property("TemplateId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TemplateId")); + + b.Property("Annotations") + .HasColumnType("jsonb"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("TemplateId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("CreatedBy"); + + b.HasIndex("Status"); + + b.ToTable("production_templates", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", b => + { + b.Property("PurchaseInvoiceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PurchaseInvoiceId")); + + b.Property("BalanceAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VatTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.Property("VendorInvoiceDate") + .HasColumnType("timestamp with time zone"); + + b.Property("VendorInvoiceNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("VendorSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("VendorSnapshotTaxNo") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("PurchaseInvoiceId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("VendorId"); + + b.HasIndex("VendorId", "VendorInvoiceNo"); + + b.ToTable("purchase_invoices", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoiceLine", b => + { + b.Property("PurchaseInvoiceLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PurchaseInvoiceLineId")); + + b.Property("GrnId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PurchaseInvoiceId") + .HasColumnType("integer"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("VatTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("PurchaseInvoiceLineId"); + + b.HasIndex("GrnId") + .IsUnique(); + + b.HasIndex("PurchaseInvoiceId"); + + b.ToTable("purchase_invoice_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoicePayment", b => + { + b.Property("PurchaseInvoicePaymentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PurchaseInvoicePaymentId")); + + b.Property("Amount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BankAccountName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("GlBankAccountId") + .HasColumnType("bigint"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PaymentDate") + .HasColumnType("timestamp with time zone"); + + b.Property("PurchaseInvoiceId") + .HasColumnType("integer"); + + b.Property("Reference") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("PurchaseInvoicePaymentId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("PurchaseInvoiceId"); + + b.ToTable("purchase_invoice_payments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => + { + b.Property("PoId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PoId")); + + b.Property("ApprovalRequired") + .HasColumnType("boolean"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RequisitionId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.HasKey("PoId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("RequisitionId"); + + b.HasIndex("Status"); + + b.HasIndex("VendorId"); + + b.ToTable("purchase_orders", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturn", b => + { + b.Property("ReturnId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReasonCodeId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("ReturnId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("ReasonCodeId"); + + b.HasIndex("VendorId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("purchase_returns", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturnLine", b => + { + b.Property("ReturnLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnLineId")); + + b.Property("GrnLineId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReturnId") + .HasColumnType("integer"); + + b.HasKey("ReturnLineId"); + + b.HasIndex("GrnLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("ReturnId"); + + b.ToTable("purchase_return_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ReasonCode", b => + { + b.Property("ReasonCodeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReasonCodeId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Context") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.HasKey("ReasonCodeId"); + + b.HasIndex("Context", "Code") + .IsUnique(); + + b.ToTable("reason_codes", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => + { + b.Property("RequisitionId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RequisitionId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RequestedBy") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("RequisitionId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("RequestedBy"); + + b.HasIndex("Status"); + + b.ToTable("requisitions", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RequisitionLine", b => + { + b.Property("ReqLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReqLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RequiredBy") + .HasColumnType("date"); + + b.Property("RequisitionId") + .HasColumnType("integer"); + + b.HasKey("ReqLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RequisitionId"); + + b.ToTable("requisition_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => + { + b.Property("RfqId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RfqId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RequisitionId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("RfqId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("RequisitionId"); + + b.ToTable("rfqs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RfqLine", b => + { + b.Property("RfqLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RfqLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RfqId") + .HasColumnType("integer"); + + b.HasKey("RfqLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RfqId"); + + b.ToTable("rfq_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Role", b => + { + b.Property("RoleId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RoleId")); + + b.Property("AuthRoleId") + .HasColumnType("uuid") + .HasColumnName("auth_role_id"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsSystemRole") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("RoleId"); + + b.HasIndex("AuthRoleId") + .IsUnique(); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("roles", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RolePermission", b => + { + b.Property("RoleId") + .HasColumnType("integer"); + + b.Property("PermissionId") + .HasColumnType("integer"); + + b.HasKey("RoleId", "PermissionId"); + + b.HasIndex("PermissionId"); + + b.ToTable("role_permissions", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunEdge", b => + { + b.Property("RunEdgeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunEdgeId")); + + b.Property("ChildRunStageId") + .HasColumnType("integer"); + + b.Property("ParentRunStageId") + .HasColumnType("integer"); + + b.Property("RunId") + .HasColumnType("integer"); + + b.HasKey("RunEdgeId"); + + b.HasIndex("ChildRunStageId"); + + b.HasIndex("RunId"); + + b.HasIndex("ParentRunStageId", "ChildRunStageId") + .IsUnique(); + + b.ToTable("run_edges", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStage", b => + { + b.Property("RunStageId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunStageId")); + + b.Property("ActualEndAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ActualStartAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EstimatedMinutes") + .HasColumnType("integer"); + + b.Property("FieldDefs") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("FieldValues") + .HasColumnType("jsonb"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("PosX") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PosY") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RoleLabel") + .HasMaxLength(60) + .HasColumnType("character varying(60)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("RunId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("TemplateStageId") + .HasColumnType("integer"); + + b.HasKey("RunStageId"); + + b.HasIndex("TemplateStageId"); + + b.HasIndex("RunId", "Status"); + + b.ToTable("run_stages", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageEvent", b => + { + b.Property("EventId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EventId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Note") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Payload") + .HasColumnType("jsonb"); + + b.Property("RunId") + .HasColumnType("integer"); + + b.Property("RunStageId") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("EventId"); + + b.HasIndex("RunStageId"); + + b.HasIndex("UserId"); + + b.HasIndex("RunId", "EventId"); + + b.ToTable("run_stage_events", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageInput", b => + { + b.Property("RunInputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunInputId")); + + b.Property("ConsumedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ConsumedValue") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DeliveredQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("FromRunOutputId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("PlannedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyUnit") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ReturnedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReturnedValue") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RunStageId") + .HasColumnType("integer"); + + b.Property("Source") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("RunInputId"); + + b.HasIndex("FromRunOutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RunStageId"); + + b.ToTable("run_stage_inputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageOutput", b => + { + b.Property("RunOutputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunOutputId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("PlannedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ProducedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RunStageId") + .HasColumnType("integer"); + + b.Property("ScrapReasonCodeId") + .HasColumnType("integer"); + + b.Property("ScrappedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TransferredQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UomId") + .HasColumnType("integer"); + + b.HasKey("RunOutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RunStageId"); + + b.HasIndex("ScrapReasonCodeId"); + + b.HasIndex("UomId"); + + b.ToTable("run_stage_outputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalaryComponent", b => + { + b.Property("SalaryComponentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalaryComponentId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ComponentType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsEpfEtfApplicable") + .HasColumnType("boolean"); + + b.Property("IsTaxable") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("SalaryComponentId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_salary_components", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesDayEnd", b => + { + b.Property("SalesDayEndId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesDayEndId")); + + b.Property("BundleCount") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("BusinessDate") + .HasColumnType("date"); + + b.Property("CashierUserId") + .HasColumnType("integer"); + + b.Property("ClosedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ClosedBy") + .HasColumnType("integer"); + + b.Property("CostOfGoodsSold") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SlipCount") + .HasColumnType("integer"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("SalesDayEndId"); + + b.HasIndex("ClosedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("CashierUserId", "BusinessDate") + .IsUnique(); + + b.ToTable("sales_day_ends", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoice", b => + { + b.Property("SalesInvoiceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesInvoiceId")); + + b.Property("BalanceAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("CreatorUserId") + .HasColumnType("integer"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("CustomerSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CustomerSnapshotTaxNo") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("InvoiceDate") + .HasColumnType("timestamp with time zone"); + + b.Property("InvoiceNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("InvoiceType") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("B2C"); + + b.Property("NetPayable") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RoundOff") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesInvoiceId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatorUserId"); + + b.HasIndex("CustomerId"); + + b.HasIndex("InvoiceDate"); + + b.HasIndex("InvoiceNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_invoices", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoiceLine", b => + { + b.Property("SalesInvoiceLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesInvoiceLineId")); + + b.Property("BaseCost") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DiscountAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DiscountMode") + .HasColumnType("integer"); + + b.Property("DiscountPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("FreeQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("IsFreeIssue") + .HasColumnType("boolean"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("NetUnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ParentLineId") + .HasColumnType("integer"); + + b.Property("PriceSource") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SalesInvoiceId") + .HasColumnType("integer"); + + b.Property("TaxAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesInvoiceLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SalesInvoiceId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_invoice_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoicePayment", b => + { + b.Property("SalesInvoicePaymentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesInvoicePaymentId")); + + b.Property("Amount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BankAccountName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("GlBankAccountId") + .HasColumnType("bigint"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PaymentDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Reference") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("SalesInvoiceId") + .HasColumnType("integer"); + + b.HasKey("SalesInvoicePaymentId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("SalesInvoiceId"); + + b.ToTable("sales_invoice_payments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturn", b => + { + b.Property("ReturnId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReasonCodeId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("ReturnId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("CustomerId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("ReasonCodeId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_returns", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturnLine", b => + { + b.Property("ReturnLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReturnId") + .HasColumnType("integer"); + + b.Property("SalesInvoiceLineId") + .HasColumnType("integer"); + + b.HasKey("ReturnLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("ReturnId"); + + b.HasIndex("SalesInvoiceLineId"); + + b.ToTable("sales_return_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlip", b => + { + b.Property("SalesSlipId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesSlipId")); + + b.Property("BalanceAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CashierUserId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("CustomerSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DayEndId") + .HasColumnType("integer"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SlipDate") + .HasColumnType("timestamp with time zone"); + + b.Property("SlipNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesSlipId"); + + b.HasIndex("CashierUserId"); + + b.HasIndex("CustomerId"); + + b.HasIndex("DayEndId"); + + b.HasIndex("SlipDate"); + + b.HasIndex("SlipNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_slips", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlipLine", b => + { + b.Property("SalesSlipLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesSlipLineId")); + + b.Property("BaseCost") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DiscountAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DiscountMode") + .HasColumnType("integer"); + + b.Property("DiscountPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("FreeQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("IsFreeIssue") + .HasColumnType("boolean"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("NetUnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ParentLineId") + .HasColumnType("integer"); + + b.Property("PriceSource") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SalesSlipId") + .HasColumnType("integer"); + + b.Property("TaxAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesSlipLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SalesSlipId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_slip_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Serial", b => + { + b.Property("SerialId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SerialId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("SerialNo") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("SerialId"); + + b.HasIndex("ItemId", "SerialNo") + .IsUnique(); + + b.ToTable("serials", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageEdge", b => + { + b.Property("EdgeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EdgeId")); + + b.Property("ChildStageId") + .HasColumnType("integer"); + + b.Property("ParentStageId") + .HasColumnType("integer"); + + b.Property("TemplateId") + .HasColumnType("integer"); + + b.HasKey("EdgeId"); + + b.HasIndex("ChildStageId"); + + b.HasIndex("TemplateId"); + + b.HasIndex("ParentStageId", "ChildStageId") + .IsUnique(); + + b.ToTable("stage_edges", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageInput", b => + { + b.Property("InputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("InputId")); + + b.Property("FromOutputId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyPerBatch") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyUnit") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Source") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("StageId") + .HasColumnType("integer"); + + b.HasKey("InputId"); + + b.HasIndex("FromOutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("StageId"); + + b.ToTable("stage_inputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageOutput", b => + { + b.Property("OutputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("OutputId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("QtyPerBatch") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("StageId") + .HasColumnType("integer"); + + b.Property("UomId") + .HasColumnType("integer"); + + b.HasKey("OutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("StageId"); + + b.HasIndex("UomId"); + + b.ToTable("stage_outputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustment", b => + { + b.Property("AdjustmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AdjustmentId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReasonCodeId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("AdjustmentId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("ReasonCodeId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("stock_adjustments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustmentLine", b => + { + b.Property("AdjLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AdjLineId")); + + b.Property("AdjustmentId") + .HasColumnType("integer"); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyDelta") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.HasKey("AdjLineId"); + + b.HasIndex("AdjustmentId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SerialId"); + + b.ToTable("stock_adjustment_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCount", b => + { + b.Property("CountId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CountId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CountType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("CountId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("stock_counts", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCountLine", b => + { + b.Property("CountLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CountLineId")); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("CountId") + .HasColumnType("integer"); + + b.Property("CountedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("SystemQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Variance") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("CountLineId"); + + b.HasIndex("BinId"); + + b.HasIndex("CountId"); + + b.HasIndex("ItemId"); + + b.ToTable("stock_count_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLayer", b => + { + b.Property("LayerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LayerId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("GrnLineId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyReceived") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyRemaining") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReceiptDate") + .HasColumnType("timestamp with time zone"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("LayerId"); + + b.HasIndex("BatchId"); + + b.HasIndex("GrnLineId"); + + b.HasIndex("SerialId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("ItemId", "WarehouseId", "ReceiptDate", "LayerId"); + + b.ToTable("stock_layers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLedger", b => + { + b.Property("LedgerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LedgerId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Direction") + .IsRequired() + .HasMaxLength(5) + .HasColumnType("character varying(5)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyBase") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RunningBalance") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("SourceDocId") + .HasColumnType("integer"); + + b.Property("SourceDocType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.Property("Value") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("LedgerId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("SerialId"); + + b.HasIndex("UserId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("SourceDocType", "SourceDocId"); + + b.HasIndex("ItemId", "WarehouseId", "CreatedAt"); + + b.HasIndex("ItemId", "WarehouseId", "LedgerId"); + + b.ToTable("stock_ledger", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransfer", b => + { + b.Property("TransferId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TransferId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DestWarehouseId") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SrcWarehouseId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("TransferId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DestWarehouseId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("SrcWarehouseId"); + + b.HasIndex("Status"); + + b.ToTable("stock_transfers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransferLine", b => + { + b.Property("TransferLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TransferLineId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("DestBinId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyReceived") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("SrcBinId") + .HasColumnType("integer"); + + b.Property("TransferId") + .HasColumnType("integer"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.HasKey("TransferLineId"); + + b.HasIndex("BatchId"); + + b.HasIndex("DestBinId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SerialId"); + + b.HasIndex("SrcBinId"); + + b.HasIndex("TransferId"); + + b.ToTable("stock_transfer_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubCategory", b => + { + b.Property("SubCategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SubCategoryId")); + + b.Property("CategoryId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("SubCategoryId"); + + b.HasIndex("Status"); + + b.HasIndex("CategoryId", "Name") + .IsUnique(); + + b.ToTable("subcategories", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubNavItem", b => + { + b.Property("SubNavItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SubNavItemId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Href") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Icon") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("NavItemId") + .HasColumnType("integer"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.HasKey("SubNavItemId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("NavItemId"); + + b.ToTable("sub_nav_items", (string)null); + + b.HasData( + new + { + SubNavItemId = 1, + Code = "products.item", + Href = "/dashboard/products", + Label = "Item", + NavItemId = 2, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 2, + Code = "products.category", + Href = "/dashboard/products/categories", + Label = "Category", + NavItemId = 2, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 3, + Code = "products.brand", + Href = "/dashboard/products/brands", + Label = "Brand", + NavItemId = 2, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 4, + Code = "products.item-type", + Href = "/dashboard/products/item-types", + Label = "Item Type", + NavItemId = 2, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 5, + Code = "products.uom", + Href = "/dashboard/products/uoms", + Label = "UOM", + NavItemId = 2, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 6, + Code = "products.configuration", + Href = "/dashboard/products/settings", + Label = "Configuration", + NavItemId = 2, + SortOrder = 6, + Status = "Active" + }, + new + { + SubNavItemId = 29, + Code = "settings.branches", + Href = "/dashboard/settings/branches", + Label = "Branches", + NavItemId = 9, + SortOrder = 0, + Status = "Active" + }, + new + { + SubNavItemId = 7, + Code = "settings.roles", + Href = "/dashboard/settings/roles", + Label = "Roles", + NavItemId = 9, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 8, + Code = "settings.users", + Href = "/dashboard/settings/users", + Label = "Users", + NavItemId = 9, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 24, + Code = "settings.notification-config", + Href = "/dashboard/settings/notification-config", + Label = "Notification Config", + NavItemId = 9, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 40, + Code = "sales.invoices", + Href = "/dashboard/sales/invoices", + Label = "Sales", + NavItemId = 13, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 23, + Code = "sales.bundle-templates", + Href = "/dashboard/sales/bundles/templates", + Label = "Bundle Templates", + NavItemId = 13, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 41, + Code = "sales.free-issues", + Href = "/dashboard/sales/free-issues", + Label = "Free Issues", + NavItemId = 13, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 42, + Code = "sales.day-end", + Href = "/dashboard/sales/day-end", + Label = "Day End", + NavItemId = 13, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 30, + Code = "procurement.vendors", + Href = "/dashboard/vendors", + Label = "Vendors", + NavItemId = 4, + SortOrder = 0, + Status = "Active" + }, + new + { + SubNavItemId = 17, + Code = "procurement.requisitions", + Href = "/dashboard/procurement/requisitions", + Label = "Requisitions", + NavItemId = 4, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 18, + Code = "procurement.rfqs", + Href = "/dashboard/procurement/rfqs", + Label = "RFQs", + NavItemId = 4, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 19, + Code = "procurement.purchase-orders", + Href = "/dashboard/procurement/purchase-orders", + Label = "Purchase Orders", + NavItemId = 4, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 20, + Code = "procurement.purchase-returns", + Href = "/dashboard/procurement/purchase-returns", + Label = "Purchase Returns", + NavItemId = 4, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 28, + Code = "procurement.purchase-invoices", + Href = "/dashboard/procurement/purchase-invoices", + Label = "Purchase Invoices", + NavItemId = 4, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 9, + Code = "ledgers.trial-balance", + Href = "/dashboard/ledgers/trial-balance", + Label = "Trial Balance", + NavItemId = 11, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 10, + Code = "ledgers.balance-sheet", + Href = "/dashboard/ledgers/balance-sheet", + Label = "Balance Sheet", + NavItemId = 11, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 11, + Code = "ledgers.general-ledger", + Href = "/dashboard/ledgers/general-ledger", + Label = "General Ledger", + NavItemId = 11, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 12, + Code = "ledgers.profit-and-loss", + Href = "/dashboard/ledgers/profit-and-loss", + Label = "Profit & Loss", + NavItemId = 11, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 13, + Code = "ledgers.cash-flow", + Href = "/dashboard/ledgers/cash-flow", + Label = "Cash Flow", + NavItemId = 11, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 14, + Code = "ledgers.budget-vs-actual", + Href = "/dashboard/ledgers/budget-vs-actual", + Label = "Budget vs Actual", + NavItemId = 11, + SortOrder = 6, + Status = "Active" + }, + new + { + SubNavItemId = 16, + Code = "ledgers.tax-report", + Href = "/dashboard/ledgers/tax-report", + Label = "Tax Report", + NavItemId = 11, + SortOrder = 7, + Status = "Active" + }, + new + { + SubNavItemId = 15, + Code = "accounts.bank-accounts", + Href = "/dashboard/accounts/bank-accounts", + Label = "Cash / Bank Accounts", + NavItemId = 12, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 21, + Code = "accounts.cheque-books", + Href = "/dashboard/accounts/cheque-books", + Label = "Cheque Books", + NavItemId = 12, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 22, + Code = "accounts.received-cheques", + Href = "/dashboard/accounts/received-cheques", + Label = "Received Cheques", + NavItemId = 12, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 27, + Code = "production.templates", + Href = "/dashboard/production/templates", + Label = "Templates", + NavItemId = 14, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 25, + Code = "production.runs", + Href = "/dashboard/production/runs", + Label = "Runs", + NavItemId = 14, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 26, + Code = "production.produced", + Href = "/dashboard/production/produced", + Label = "Produced", + NavItemId = 14, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 31, + Code = "stock.ledger", + Href = "/dashboard/stock/ledger", + Label = "Stock Ledger", + NavItemId = 6, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 32, + Code = "stock.enquiry", + Href = "/dashboard/stock/enquiry", + Label = "Stock Enquiry", + NavItemId = 6, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 33, + Code = "stock.valuation", + Href = "/dashboard/stock/valuation", + Label = "Valuation", + NavItemId = 6, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 34, + Code = "stock.transfers", + Href = "/dashboard/stock/transfers", + Label = "Transfers", + NavItemId = 6, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 35, + Code = "stock.adjustments", + Href = "/dashboard/stock/adjustments", + Label = "Adjustments", + NavItemId = 6, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 36, + Code = "stock.counts", + Href = "/dashboard/stock/counts", + Label = "Counts", + NavItemId = 6, + SortOrder = 6, + Status = "Active" + }, + new + { + SubNavItemId = 37, + Code = "stock.reorder-alerts", + Href = "/dashboard/stock/reorder-alerts", + Label = "Reorder Alerts", + NavItemId = 6, + SortOrder = 7, + Status = "Active" + }, + new + { + SubNavItemId = 38, + Code = "stock.wastage", + Href = "/dashboard/stock/wastage", + Label = "Wastage", + NavItemId = 6, + SortOrder = 8, + Status = "Active" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TaxSlab", b => + { + b.Property("TaxSlabId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TaxSlabId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveTo") + .HasColumnType("timestamp with time zone"); + + b.Property("LowerBound") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("Rate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("UpperBound") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.HasKey("TaxSlabId"); + + b.HasIndex("EffectiveFrom"); + + b.ToTable("hr_tax_slabs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => + { + b.Property("StageId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("StageId")); + + b.Property("EstimatedMinutes") + .HasColumnType("integer"); + + b.Property("FieldDefs") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("PosX") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PosY") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RoleLabel") + .HasMaxLength(60) + .HasColumnType("character varying(60)"); + + b.Property("TemplateId") + .HasColumnType("integer"); + + b.HasKey("StageId"); + + b.HasIndex("TemplateId"); + + b.ToTable("template_stages", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Uom", b => + { + b.Property("UomId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("UomId")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("UomId"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("uoms", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.User", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("UserId")); + + b.Property("AuthUserId") + .HasColumnType("uuid") + .HasColumnName("auth_user_id"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Email") + .HasMaxLength(320) + .HasColumnType("character varying(320)"); + + b.Property("RoleId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("UserId"); + + b.HasIndex("AuthUserId") + .IsUnique(); + + b.HasIndex("Email") + .IsUnique(); + + b.HasIndex("RoleId"); + + b.HasIndex("Username") + .IsUnique(); + + b.ToTable("users", (string)null); + + b.HasData( + new + { + UserId = 1, + DisplayName = "System", + Status = "Active", + Username = "system" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Vendor", b => + { + b.Property("VendorId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("VendorId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Currency") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(3) + .HasColumnType("character varying(3)") + .HasDefaultValue("LKR"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TaxReg") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Terms") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("VendorId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("vendors", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => + { + b.Property("QuotationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("QuotationId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("RfqId") + .HasColumnType("integer"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.HasKey("QuotationId"); + + b.HasIndex("VendorId"); + + b.HasIndex("RfqId", "VendorId") + .IsUnique(); + + b.ToTable("vendor_quotations", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotationLine", b => + { + b.Property("QuotationLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("QuotationLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LeadDays") + .HasColumnType("integer"); + + b.Property("QuotationId") + .HasColumnType("integer"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("QuotationLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("QuotationId"); + + b.ToTable("vendor_quotation_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Warehouse", b => + { + b.Property("WarehouseId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("WarehouseId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.HasKey("WarehouseId"); + + b.HasIndex("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("warehouses", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.WorkShift", b => + { + b.Property("WorkShiftId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("WorkShiftId")); + + b.Property("BreakMinutes") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EndTime") + .HasColumnType("interval"); + + b.Property("GraceMinutes") + .HasColumnType("integer"); + + b.Property("IsOvernight") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("OtMultiplier") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("StandardWorkingMinutes") + .HasColumnType("integer"); + + b.Property("StartTime") + .HasColumnType("interval"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WorkingDaysMask") + .HasColumnType("integer"); + + b.HasKey("WorkShiftId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_work_shifts", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceRecord", b => + { + b.HasOne("ERPCore.Domain.Entities.AttendanceUploadBatch", "AttendanceUploadBatch") + .WithMany() + .HasForeignKey("AttendanceUploadBatchId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.WorkShift", "WorkShift") + .WithMany() + .HasForeignKey("WorkShiftId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("AttendanceUploadBatch"); + + b.Navigation("Employee"); + + b.Navigation("WorkShift"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AuditLog", b => + { + b.HasOne("ERPCore.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Batch", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Bin", b => + { + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany("Bins") + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BranchConfig", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSale", b => + { + b.HasOne("ERPCore.Domain.Entities.BundleSaleTemplate", "BundleSaleTemplate") + .WithMany() + .HasForeignKey("BundleSaleTemplateId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "CashierUser") + .WithMany() + .HasForeignKey("CashierUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesDayEnd", "DayEnd") + .WithMany("BundleSales") + .HasForeignKey("DayEndId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BundleSaleTemplate"); + + b.Navigation("CashierUser"); + + b.Navigation("Customer"); + + b.Navigation("DayEnd"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleLine", b => + { + b.HasOne("ERPCore.Domain.Entities.BundleSale", "BundleSale") + .WithMany("Lines") + .HasForeignKey("BundleSaleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BundleSale"); + + b.Navigation("Item"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplateLine", b => + { + b.HasOne("ERPCore.Domain.Entities.BundleSaleTemplate", "BundleSaleTemplate") + .WithMany("Lines") + .HasForeignKey("BundleSaleTemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BundleSaleTemplate"); + + b.Navigation("Item"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Customer", b => + { + b.HasOne("ERPCore.Domain.Entities.Warehouse", "DefaultWarehouse") + .WithMany() + .HasForeignKey("DefaultWarehouseId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("DefaultWarehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Department", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Employee", "HeadEmployee") + .WithMany() + .HasForeignKey("HeadEmployeeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Department", "ParentDepartment") + .WithMany() + .HasForeignKey("ParentDepartmentId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Branch"); + + b.Navigation("HeadEmployee"); + + b.Navigation("ParentDepartment"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Employee", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Department", "Department") + .WithMany() + .HasForeignKey("DepartmentId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Designation", "Designation") + .WithMany() + .HasForeignKey("DesignationId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.EmploymentType", "EmploymentType") + .WithMany() + .HasForeignKey("EmploymentTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Employee", "ReportingManager") + .WithMany() + .HasForeignKey("ReportingManagerId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithOne() + .HasForeignKey("ERPCore.Domain.Entities.Employee", "UserId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.WorkShift", "WorkShift") + .WithMany() + .HasForeignKey("WorkShiftId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Department"); + + b.Navigation("Designation"); + + b.Navigation("EmploymentType"); + + b.Navigation("ReportingManager"); + + b.Navigation("User"); + + b.Navigation("WorkShift"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeBankDetail", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeDocument", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.HrDocumentType", "HrDocumentType") + .WithMany() + .HasForeignKey("HrDocumentTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("HrDocumentType"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeLoan", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructure", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructureLine", b => + { + b.HasOne("ERPCore.Domain.Entities.EmployeeSalaryStructure", "EmployeeSalaryStructure") + .WithMany("Lines") + .HasForeignKey("EmployeeSalaryStructureId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalaryComponent", "SalaryComponent") + .WithMany() + .HasForeignKey("SalaryComponentId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("EmployeeSalaryStructure"); + + b.Navigation("SalaryComponent"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Grn", 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.HasOne("ERPCore.Domain.Entities.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("PoId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.PurchaseInvoice", "PurchaseInvoice") + .WithMany() + .HasForeignKey("PurchaseInvoiceId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("PurchaseInvoice"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Vendor"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", "Batch") + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", "Bin") + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Grn", "Grn") + .WithMany("Lines") + .HasForeignKey("GrnId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PoLine", "PoLine") + .WithMany() + .HasForeignKey("PoLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Batch"); + + b.Navigation("Bin"); + + b.Navigation("Grn"); + + b.Navigation("Item"); + + b.Navigation("PoLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLineWarrantyNumber", b => + { + b.HasOne("ERPCore.Domain.Entities.GrnLine", "GrnLine") + .WithMany("WarrantyNumbers") + .HasForeignKey("GrnLineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GrnLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Item", b => + { + b.HasOne("ERPCore.Domain.Entities.Uom", "BaseUom") + .WithMany() + .HasForeignKey("BaseUomId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Brand", "Brand") + .WithMany() + .HasForeignKey("BrandId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Category", "Category") + .WithMany() + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "DefaultVendor") + .WithMany() + .HasForeignKey("DefaultVendorId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.SubCategory", "SubCategory") + .WithMany() + .HasForeignKey("SubCategoryId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("BaseUom"); + + b.Navigation("Brand"); + + b.Navigation("Category"); + + b.Navigation("DefaultVendor"); + + b.Navigation("SubCategory"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ItemReorder", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany("ReorderSettings") + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveBalance", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.LeaveType", "LeaveType") + .WithMany() + .HasForeignKey("LeaveTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("LeaveType"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveRequest", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.LeaveType", "LeaveType") + .WithMany() + .HasForeignKey("LeaveTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("LeaveType"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoanInstallment", b => + { + b.HasOne("ERPCore.Domain.Entities.EmployeeLoan", "EmployeeLoan") + .WithMany("Installments") + .HasForeignKey("EmployeeLoanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PayrollRun", "PayrollRun") + .WithMany() + .HasForeignKey("PayrollRunId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("EmployeeLoan"); + + b.Navigation("PayrollRun"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoginActivity", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfigModule", b => + { + b.HasOne("ERPCore.Domain.Entities.NotificationConfig", "NotificationConfig") + .WithMany("Modules") + .HasForeignKey("NotificationConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("NotificationConfig"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationRecipient", b => + { + b.HasOne("ERPCore.Domain.Entities.Notification", "Notification") + .WithMany("Recipients") + .HasForeignKey("NotificationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Notification"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PayrollRun", "PayrollRun") + .WithMany("Lines") + .HasForeignKey("PayrollRunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("PayrollRun"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLineComponent", b => + { + b.HasOne("ERPCore.Domain.Entities.PayrollLine", "PayrollLine") + .WithMany("Components") + .HasForeignKey("PayrollLineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalaryComponent", "SalaryComponent") + .WithMany() + .HasForeignKey("SalaryComponentId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("PayrollLine"); + + b.Navigation("SalaryComponent"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollRun", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Branch"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Payslip", b => + { + b.HasOne("ERPCore.Domain.Entities.PayrollLine", "PayrollLine") + .WithOne() + .HasForeignKey("ERPCore.Domain.Entities.Payslip", "PayrollLineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PayrollLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Permission", b => + { + b.HasOne("ERPCore.Domain.Entities.NavItem", "NavItem") + .WithMany() + .HasForeignKey("NavItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ERPCore.Domain.Entities.SubNavItem", "SubNavItem") + .WithMany() + .HasForeignKey("SubNavItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("NavItem"); + + b.Navigation("SubNavItem"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PoLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseOrder", "PurchaseOrder") + .WithMany("Lines") + .HasForeignKey("PoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductConfig", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b => + { + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "CancelReason") + .WithMany() + .HasForeignKey("CancelReasonCodeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Bin", "OutputBin") + .WithMany() + .HasForeignKey("OutputBinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") + .WithMany("Runs") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CancelReason"); + + b.Navigation("Creator"); + + b.Navigation("OutputBin"); + + b.Navigation("Template"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionTemplate", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoiceLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Grn", "Grn") + .WithMany() + .HasForeignKey("GrnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseInvoice", "PurchaseInvoice") + .WithMany("Lines") + .HasForeignKey("PurchaseInvoiceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Grn"); + + b.Navigation("PurchaseInvoice"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoicePayment", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseInvoice", "PurchaseInvoice") + .WithMany("Payments") + .HasForeignKey("PurchaseInvoiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("PurchaseInvoice"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") + .WithMany() + .HasForeignKey("RequisitionId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("Requisition"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturn", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ReasonCode") + .WithMany() + .HasForeignKey("ReasonCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("ReasonCode"); + + b.Navigation("Vendor"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturnLine", b => + { + b.HasOne("ERPCore.Domain.Entities.GrnLine", "GrnLine") + .WithMany() + .HasForeignKey("GrnLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseReturn", "Return") + .WithMany("Lines") + .HasForeignKey("ReturnId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GrnLine"); + + b.Navigation("Item"); + + b.Navigation("Return"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Requester") + .WithMany() + .HasForeignKey("RequestedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Requester"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RequisitionLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") + .WithMany("Lines") + .HasForeignKey("RequisitionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Requisition"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => + { + b.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") + .WithMany() + .HasForeignKey("RequisitionId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Requisition"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RfqLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Rfq", "Rfq") + .WithMany("Lines") + .HasForeignKey("RfqId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Rfq"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RolePermission", b => + { + b.HasOne("ERPCore.Domain.Entities.Permission", "Permission") + .WithMany() + .HasForeignKey("PermissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Role", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Permission"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunEdge", b => + { + b.HasOne("ERPCore.Domain.Entities.RunStage", "ChildRunStage") + .WithMany() + .HasForeignKey("ChildRunStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "ParentRunStage") + .WithMany() + .HasForeignKey("ParentRunStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ProductionRun", "Run") + .WithMany("Edges") + .HasForeignKey("RunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildRunStage"); + + b.Navigation("ParentRunStage"); + + b.Navigation("Run"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStage", b => + { + b.HasOne("ERPCore.Domain.Entities.ProductionRun", "Run") + .WithMany("Stages") + .HasForeignKey("RunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "TemplateStage") + .WithMany() + .HasForeignKey("TemplateStageId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Run"); + + b.Navigation("TemplateStage"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageEvent", b => + { + b.HasOne("ERPCore.Domain.Entities.ProductionRun", "Run") + .WithMany("Events") + .HasForeignKey("RunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "RunStage") + .WithMany("Events") + .HasForeignKey("RunStageId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Run"); + + b.Navigation("RunStage"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageInput", b => + { + b.HasOne("ERPCore.Domain.Entities.RunStageOutput", "FromRunOutput") + .WithMany() + .HasForeignKey("FromRunOutputId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "RunStage") + .WithMany("Inputs") + .HasForeignKey("RunStageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromRunOutput"); + + b.Navigation("Item"); + + b.Navigation("RunStage"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageOutput", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "RunStage") + .WithMany("Outputs") + .HasForeignKey("RunStageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ScrapReason") + .WithMany() + .HasForeignKey("ScrapReasonCodeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Uom", "Uom") + .WithMany() + .HasForeignKey("UomId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Item"); + + b.Navigation("RunStage"); + + b.Navigation("ScrapReason"); + + b.Navigation("Uom"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesDayEnd", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "CashierUser") + .WithMany() + .HasForeignKey("CashierUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "ClosedByUser") + .WithMany() + .HasForeignKey("ClosedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CashierUser"); + + b.Navigation("ClosedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoice", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatorUserId"); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("Customer"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoiceLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesInvoice", "SalesInvoice") + .WithMany("Lines") + .HasForeignKey("SalesInvoiceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SalesInvoice"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoicePayment", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesInvoice", "SalesInvoice") + .WithMany("Payments") + .HasForeignKey("SalesInvoiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("SalesInvoice"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturn", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ReasonCode") + .WithMany() + .HasForeignKey("ReasonCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("Customer"); + + b.Navigation("ReasonCode"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturnLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesReturn", "Return") + .WithMany("Lines") + .HasForeignKey("ReturnId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesInvoiceLine", "SalesInvoiceLine") + .WithMany() + .HasForeignKey("SalesInvoiceLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Item"); + + b.Navigation("Return"); + + b.Navigation("SalesInvoiceLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlip", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "CashierUser") + .WithMany() + .HasForeignKey("CashierUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesDayEnd", "DayEnd") + .WithMany("Slips") + .HasForeignKey("DayEndId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CashierUser"); + + b.Navigation("Customer"); + + b.Navigation("DayEnd"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlipLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesSlip", "SalesSlip") + .WithMany("Lines") + .HasForeignKey("SalesSlipId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SalesSlip"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Serial", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageEdge", b => + { + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "ChildStage") + .WithMany() + .HasForeignKey("ChildStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "ParentStage") + .WithMany() + .HasForeignKey("ParentStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") + .WithMany("Edges") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildStage"); + + b.Navigation("ParentStage"); + + b.Navigation("Template"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageInput", b => + { + b.HasOne("ERPCore.Domain.Entities.StageOutput", "FromOutput") + .WithMany() + .HasForeignKey("FromOutputId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "Stage") + .WithMany("Inputs") + .HasForeignKey("StageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromOutput"); + + b.Navigation("Item"); + + b.Navigation("Stage"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageOutput", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "Stage") + .WithMany("Outputs") + .HasForeignKey("StageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Uom", "Uom") + .WithMany() + .HasForeignKey("UomId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Item"); + + b.Navigation("Stage"); + + b.Navigation("Uom"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustment", 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.HasOne("ERPCore.Domain.Entities.ReasonCode", "ReasonCode") + .WithMany() + .HasForeignKey("ReasonCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("ReasonCode"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustmentLine", b => + { + b.HasOne("ERPCore.Domain.Entities.StockAdjustment", "Adjustment") + .WithMany("Lines") + .HasForeignKey("AdjustmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Batch", null) + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", null) + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Adjustment"); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCount", 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.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCountLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.StockCount", "Count") + .WithMany("Lines") + .HasForeignKey("CountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Count"); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLayer", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", "Batch") + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.GrnLine", "GrnLine") + .WithMany() + .HasForeignKey("GrnLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", "Serial") + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Batch"); + + b.Navigation("GrnLine"); + + b.Navigation("Item"); + + b.Navigation("Serial"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLedger", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", null) + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", null) + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", null) + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", null) + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransfer", 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.HasOne("ERPCore.Domain.Entities.Warehouse", "DestWarehouse") + .WithMany() + .HasForeignKey("DestWarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "SrcWarehouse") + .WithMany() + .HasForeignKey("SrcWarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("DestWarehouse"); + + b.Navigation("SrcWarehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransferLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", null) + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("DestBinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", null) + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("SrcBinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.StockTransfer", "Transfer") + .WithMany("Lines") + .HasForeignKey("TransferId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Transfer"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubCategory", b => + { + b.HasOne("ERPCore.Domain.Entities.Category", "Category") + .WithMany("SubCategories") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubNavItem", b => + { + b.HasOne("ERPCore.Domain.Entities.NavItem", "NavItem") + .WithMany("Children") + .HasForeignKey("NavItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("NavItem"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => + { + b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") + .WithMany("Stages") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Template"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.User", b => + { + b.HasOne("ERPCore.Domain.Entities.Role", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => + { + b.HasOne("ERPCore.Domain.Entities.Rfq", "Rfq") + .WithMany("Quotations") + .HasForeignKey("RfqId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Rfq"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotationLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.VendorQuotation", "Quotation") + .WithMany("Lines") + .HasForeignKey("QuotationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Quotation"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Warehouse", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSale", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplate", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Category", b => + { + b.Navigation("SubCategories"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeLoan", b => + { + b.Navigation("Installments"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructure", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Grn", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLine", b => + { + b.Navigation("WarrantyNumbers"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Item", b => + { + b.Navigation("ReorderSettings"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NavItem", b => + { + b.Navigation("Children"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Notification", b => + { + b.Navigation("Recipients"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => + { + b.Navigation("Modules"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => + { + b.Navigation("Components"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollRun", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b => + { + b.Navigation("Edges"); + + b.Navigation("Events"); + + b.Navigation("Stages"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionTemplate", b => + { + b.Navigation("Edges"); + + b.Navigation("Runs"); + + b.Navigation("Stages"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", b => + { + b.Navigation("Lines"); + + b.Navigation("Payments"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturn", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => + { + b.Navigation("Lines"); + + b.Navigation("Quotations"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStage", b => + { + b.Navigation("Events"); + + b.Navigation("Inputs"); + + b.Navigation("Outputs"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesDayEnd", b => + { + b.Navigation("BundleSales"); + + b.Navigation("Slips"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoice", b => + { + b.Navigation("Lines"); + + b.Navigation("Payments"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturn", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlip", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustment", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCount", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransfer", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => + { + b.Navigation("Inputs"); + + b.Navigation("Outputs"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Warehouse", b => + { + b.Navigation("Bins"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Backend/ERPCore/Migrations/20260914061147_AddNotificationFeed.cs b/Backend/ERPCore/Migrations/20260914061147_AddNotificationFeed.cs new file mode 100644 index 0000000..8b06707 --- /dev/null +++ b/Backend/ERPCore/Migrations/20260914061147_AddNotificationFeed.cs @@ -0,0 +1,87 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace ERPCore.Migrations +{ + /// + public partial class AddNotificationFeed : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "notifications", + columns: table => new + { + NotificationId = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + ModuleKey = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + Title = table.Column(type: "character varying(200)", maxLength: 200, nullable: false), + Message = table.Column(type: "character varying(1000)", maxLength: 1000, nullable: false), + RelatedEntityType = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), + RelatedEntityId = table.Column(type: "integer", nullable: true), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_notifications", x => x.NotificationId); + }); + + migrationBuilder.CreateTable( + name: "notification_recipients", + columns: table => new + { + NotificationRecipientId = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + NotificationId = table.Column(type: "integer", nullable: false), + UserId = table.Column(type: "integer", nullable: false), + IsRead = table.Column(type: "boolean", nullable: false), + ReadAt = table.Column(type: "timestamp with time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_notification_recipients", x => x.NotificationRecipientId); + table.ForeignKey( + name: "FK_notification_recipients_notifications_NotificationId", + column: x => x.NotificationId, + principalTable: "notifications", + principalColumn: "NotificationId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_notification_recipients_users_UserId", + column: x => x.UserId, + principalTable: "users", + principalColumn: "UserId", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_notification_recipients_NotificationId", + table: "notification_recipients", + column: "NotificationId"); + + migrationBuilder.CreateIndex( + name: "IX_notification_recipients_UserId_IsRead_NotificationId", + table: "notification_recipients", + columns: new[] { "UserId", "IsRead", "NotificationId" }); + + migrationBuilder.CreateIndex( + name: "IX_notifications_CreatedAt", + table: "notifications", + column: "CreatedAt"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "notification_recipients"); + + migrationBuilder.DropTable( + name: "notifications"); + } + } +} diff --git a/Backend/ERPCore/Migrations/20260914061430_AddUomLifecycleColumnsLocal.Designer.cs b/Backend/ERPCore/Migrations/20260914061430_AddUomLifecycleColumnsLocal.Designer.cs new file mode 100644 index 0000000..e75e99b --- /dev/null +++ b/Backend/ERPCore/Migrations/20260914061430_AddUomLifecycleColumnsLocal.Designer.cs @@ -0,0 +1,7954 @@ +// +using System; +using ERPCore.Infra.Persistence; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace ERPCore.Migrations +{ + [DbContext(typeof(ErpDbContext))] + [Migration("20260914061430_AddUomLifecycleColumnsLocal")] + partial class AddUomLifecycleColumnsLocal + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.9") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceRecord", b => + { + b.Property("AttendanceRecordId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AttendanceRecordId")); + + b.Property("AttendanceDate") + .HasColumnType("timestamp with time zone"); + + b.Property("AttendanceStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("AttendanceUploadBatchId") + .HasColumnType("integer"); + + b.Property("CheckIn") + .HasColumnType("interval"); + + b.Property("CheckOut") + .HasColumnType("interval"); + + b.Property("DuplicateOfAttendanceRecordId") + .HasColumnType("integer"); + + b.Property("EarlyLeaveMinutes") + .HasColumnType("integer"); + + b.Property("EditedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EditedBy") + .HasColumnType("integer"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("IsManualOverride") + .HasColumnType("boolean"); + + b.Property("LateMinutes") + .HasColumnType("integer"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("OvertimeMinutes") + .HasColumnType("integer"); + + b.Property("RowValidationStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("WorkShiftId") + .HasColumnType("integer"); + + b.Property("WorkingMinutes") + .HasColumnType("integer"); + + b.HasKey("AttendanceRecordId"); + + b.HasIndex("AttendanceUploadBatchId"); + + b.HasIndex("WorkShiftId"); + + b.HasIndex("EmployeeId", "AttendanceDate"); + + b.ToTable("hr_attendance_records", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceUploadBatch", b => + { + b.Property("AttendanceUploadBatchId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AttendanceUploadBatchId")); + + b.Property("ConfirmedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ConfirmedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("OriginalFileName") + .HasMaxLength(260) + .HasColumnType("character varying(260)"); + + b.Property("PeriodEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("PeriodStart") + .HasColumnType("timestamp with time zone"); + + b.Property("RowCountDuplicate") + .HasColumnType("integer"); + + b.Property("RowCountError") + .HasColumnType("integer"); + + b.Property("RowCountTotal") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SourceType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UploadedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UploadedBy") + .HasColumnType("integer"); + + b.HasKey("AttendanceUploadBatchId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("PeriodStart", "PeriodEnd"); + + b.ToTable("hr_attendance_upload_batches", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AuditLog", b => + { + b.Property("AuditId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AuditId")); + + b.Property("Action") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("ChangeSet") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EntityId") + .HasColumnType("integer"); + + b.Property("EntityType") + .IsRequired() + .HasMaxLength(80) + .HasColumnType("character varying(80)"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("AuditId"); + + b.HasIndex("CreatedAt"); + + b.HasIndex("UserId"); + + b.HasIndex("EntityType", "EntityId"); + + b.ToTable("audit_logs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Batch", b => + { + b.Property("BatchId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BatchId")); + + b.Property("BatchNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ExpiryDate") + .HasColumnType("date"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.HasKey("BatchId"); + + b.HasIndex("ItemId", "BatchNo") + .IsUnique(); + + b.ToTable("batches", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Bin", b => + { + b.Property("BinId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BinId")); + + b.Property("BinType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BinId"); + + b.HasIndex("WarehouseId", "Code") + .IsUnique(); + + b.ToTable("bins", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Branch", b => + { + b.Property("BranchId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BranchId")); + + b.Property("Address") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("PhoneNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_branches", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BranchConfig", b => + { + b.Property("ConfigId") + .HasColumnType("integer"); + + b.Property("BranchingEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.HasKey("ConfigId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("branch_config", null, t => + { + t.HasCheckConstraint("ck_branch_config_singleton", "\"ConfigId\" = 1"); + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Brand", b => + { + b.Property("BrandId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BrandId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("BrandId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("brands", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSale", b => + { + b.Property("BundleSaleId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleId")); + + b.Property("BundleCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BundleDate") + .HasColumnType("timestamp with time zone"); + + b.Property("BundleName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("BundleNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BundlePrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BundleSaleTemplateId") + .HasColumnType("integer"); + + b.Property("CashierUserId") + .HasColumnType("integer"); + + b.Property("ComponentSubtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("CustomerSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DayEndId") + .HasColumnType("integer"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("MarginAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BundleSaleId"); + + b.HasIndex("BundleNo") + .IsUnique(); + + b.HasIndex("BundleSaleTemplateId"); + + b.HasIndex("CashierUserId"); + + b.HasIndex("CustomerId"); + + b.HasIndex("DayEndId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("bundle_sales", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleLine", b => + { + b.Property("BundleSaleLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleLineId")); + + b.Property("BundleSaleId") + .HasColumnType("integer"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("IncludeInBundle") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("IsComponent") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ParentLineId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BundleSaleLineId"); + + b.HasIndex("BundleSaleId"); + + b.HasIndex("ItemId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("bundle_sale_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplate", b => + { + b.Property("BundleSaleTemplateId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleTemplateId")); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TemplateCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("TemplateName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("BundleSaleTemplateId"); + + b.HasIndex("TemplateCode") + .IsUnique(); + + b.ToTable("bundle_sale_templates", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplateLine", b => + { + b.Property("BundleSaleTemplateLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleTemplateLineId")); + + b.Property("BundleSaleTemplateId") + .HasColumnType("integer"); + + b.Property("IncludeInBundle") + .HasColumnType("boolean"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SortOrder") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BundleSaleTemplateLineId"); + + b.HasIndex("BundleSaleTemplateId"); + + b.HasIndex("ItemId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("bundle_sale_template_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Category", b => + { + b.Property("CategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CategoryId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("CategoryId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("categories", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Customer", b => + { + b.Property("CustomerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CustomerId")); + + b.Property("AddressLine1") + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("AddressLine2") + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("City") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Country") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreditDays") + .HasColumnType("integer"); + + b.Property("CreditLimit") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CustomerCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CustomerType") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("B2C"); + + b.Property("DefaultWarehouseId") + .HasColumnType("integer"); + + b.Property("DisplayName") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Email") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Phone") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TaxRegistrationNo") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("CustomerId"); + + b.HasIndex("CustomerCode") + .IsUnique(); + + b.HasIndex("CustomerType"); + + b.HasIndex("DefaultWarehouseId"); + + b.HasIndex("Status"); + + b.ToTable("customers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Department", b => + { + b.Property("DepartmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("DepartmentId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("HeadEmployeeId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("ParentDepartmentId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("DepartmentId"); + + b.HasIndex("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("HeadEmployeeId"); + + b.HasIndex("ParentDepartmentId"); + + b.HasIndex("Status"); + + b.ToTable("hr_departments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Designation", b => + { + b.Property("DesignationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("DesignationId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("DesignationId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_designations", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Employee", b => + { + b.Property("EmployeeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeId")); + + b.Property("AddressLine1") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("AddressLine2") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("City") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ConfirmationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Country") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DateOfBirth") + .HasColumnType("timestamp with time zone"); + + b.Property("DepartmentId") + .HasColumnType("integer"); + + b.Property("DesignationId") + .HasColumnType("integer"); + + b.Property("Email") + .HasMaxLength(320) + .HasColumnType("character varying(320)"); + + b.Property("EmergencyContactName") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("EmergencyContactPhone") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmergencyContactRelationship") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("EmployeeCode") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmploymentTypeId") + .HasColumnType("integer"); + + b.Property("EpfNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EtfNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Gender") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("HireDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LastWorkingDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Nationality") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Nic") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PersonalMobile") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PostalCode") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ProfilePhotoPath") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("ReportingManagerId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TaxIdentificationNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.Property("WorkShiftId") + .HasColumnType("integer"); + + b.HasKey("EmployeeId"); + + b.HasIndex("BranchId"); + + b.HasIndex("DepartmentId"); + + b.HasIndex("DesignationId"); + + b.HasIndex("Email"); + + b.HasIndex("EmployeeCode") + .IsUnique(); + + b.HasIndex("EmploymentTypeId"); + + b.HasIndex("ReportingManagerId"); + + b.HasIndex("Status"); + + b.HasIndex("UserId") + .IsUnique(); + + b.HasIndex("WorkShiftId"); + + b.ToTable("hr_employees", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeBankDetail", b => + { + b.Property("EmployeeBankDetailId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeBankDetailId")); + + b.Property("AccountHolderName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("AccountNumber") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BankName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("BranchName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("IsPrimary") + .HasColumnType("boolean"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("SwiftCode") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("EmployeeBankDetailId"); + + b.HasIndex("EmployeeId"); + + b.ToTable("hr_employee_bank_details", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeDocument", b => + { + b.Property("EmployeeDocumentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeDocumentId")); + + b.Property("ContentType") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("ExpiryDate") + .HasColumnType("timestamp with time zone"); + + b.Property("HrDocumentTypeId") + .HasColumnType("integer"); + + b.Property("IssueDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("OriginalFileName") + .IsRequired() + .HasMaxLength(260) + .HasColumnType("character varying(260)"); + + b.Property("RelativePath") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SizeBytes") + .HasColumnType("bigint"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("StoredFileName") + .IsRequired() + .HasMaxLength(260) + .HasColumnType("character varying(260)"); + + b.Property("UploadedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UploadedBy") + .HasColumnType("integer"); + + b.Property("VerifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VerifiedBy") + .HasColumnType("integer"); + + b.HasKey("EmployeeDocumentId"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("ExpiryDate"); + + b.HasIndex("HrDocumentTypeId"); + + b.ToTable("hr_employee_documents", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeLoan", b => + { + b.Property("EmployeeLoanId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeLoanId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("InstallmentAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("InterestRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("LoanKind") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("NumberOfInstallments") + .HasColumnType("integer"); + + b.Property("OutstandingBalance") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("PrincipalAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("StartMonth") + .HasColumnType("integer"); + + b.Property("StartYear") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("EmployeeLoanId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("EmployeeId"); + + b.HasIndex("Status"); + + b.ToTable("hr_employee_loans", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructure", b => + { + b.Property("EmployeeSalaryStructureId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeSalaryStructureId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("BasicSalary") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("Currency") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("character varying(3)"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveTo") + .HasColumnType("timestamp with time zone"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("EmployeeSalaryStructureId"); + + b.HasIndex("EmployeeId", "EffectiveTo"); + + b.ToTable("hr_employee_salary_structures", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructureLine", b => + { + b.Property("EmployeeSalaryStructureLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeSalaryStructureLineId")); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("EmployeeSalaryStructureId") + .HasColumnType("integer"); + + b.Property("SalaryComponentId") + .HasColumnType("integer"); + + b.HasKey("EmployeeSalaryStructureLineId"); + + b.HasIndex("EmployeeSalaryStructureId"); + + b.HasIndex("SalaryComponentId"); + + b.ToTable("hr_employee_salary_structure_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmploymentType", b => + { + b.Property("EmploymentTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmploymentTypeId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("EmploymentTypeId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_employment_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Grn", b => + { + b.Property("GrnId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("GrnId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PoId") + .HasColumnType("integer"); + + b.Property("PostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PurchaseInvoiceId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("GrnId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("PoId"); + + b.HasIndex("PurchaseInvoiceId"); + + b.HasIndex("Status"); + + b.HasIndex("VendorId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("grns", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLine", b => + { + b.Property("GrnLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("GrnLineId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("DiscountPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("GrnId") + .HasColumnType("integer"); + + b.Property("HoldStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("NetUnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("PoLineId") + .HasColumnType("integer"); + + b.Property("PoUnitPrice") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReceivedValue") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("VatAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("VatPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.HasKey("GrnLineId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("GrnId"); + + b.HasIndex("ItemId"); + + b.HasIndex("PoLineId"); + + b.ToTable("grn_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLineWarrantyNumber", b => + { + b.Property("GrnLineWarrantyNumberId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("GrnLineWarrantyNumberId")); + + b.Property("GrnLineId") + .HasColumnType("integer"); + + b.Property("WarrantyNo") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("WarrantyPeriodMonths") + .HasColumnType("integer"); + + b.HasKey("GrnLineWarrantyNumberId"); + + b.HasIndex("GrnLineId", "WarrantyNo") + .IsUnique(); + + b.ToTable("grn_line_warranty_numbers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.HrDocumentType", b => + { + b.Property("HrDocumentTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("HrDocumentTypeId")); + + b.Property("Category") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpiryTracked") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RequiredAtOnboarding") + .HasColumnType("boolean"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("HrDocumentTypeId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_document_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Item", b => + { + b.Property("ItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ItemId")); + + b.Property("BaseUomId") + .HasColumnType("integer"); + + b.Property("BrandId") + .HasColumnType("integer"); + + b.Property("CategoryId") + .HasColumnType("integer"); + + b.Property("ContentBaseQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ContentBaseUnit") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ContentQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ContentUnit") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DefaultVendorId") + .HasColumnType("integer"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SellingFlatPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SellingMaxPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SellingMinPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Sku") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("StockNature") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("SubCategoryId") + .HasColumnType("integer"); + + b.Property("TaxClass") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("TrackingMode") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Warranty") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("NonWarranty"); + + b.Property("WarrantyPeriodMonths") + .HasColumnType("integer"); + + b.HasKey("ItemId"); + + b.HasIndex("BaseUomId"); + + b.HasIndex("BrandId"); + + b.HasIndex("CategoryId"); + + b.HasIndex("DefaultVendorId"); + + b.HasIndex("Sku") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("SubCategoryId"); + + b.ToTable("items", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ItemReorder", b => + { + b.Property("ReorderId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReorderId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("ReorderPoint") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReorderQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("ReorderId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("ItemId", "WarehouseId") + .IsUnique(); + + b.ToTable("item_reorders", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ItemType", b => + { + b.Property("ItemTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ItemTypeId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsMeasurable") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("ItemTypeId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("item_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.JournalEntryStub", b => + { + b.Property("JournalId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("JournalId")); + + b.Property("Amount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CreditAccount") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("DebitAccount") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("SourceDocId") + .HasColumnType("integer"); + + b.Property("SourceDocType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.HasKey("JournalId"); + + b.HasIndex("SourceDocType", "SourceDocId"); + + b.ToTable("journal_entry_stubs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveBalance", b => + { + b.Property("LeaveBalanceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LeaveBalanceId")); + + b.Property("AdjustmentDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("CarriedForwardDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("EntitledDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("LeaveTypeId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("TakenDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Year") + .HasColumnType("integer"); + + b.HasKey("LeaveBalanceId"); + + b.HasIndex("LeaveTypeId"); + + b.HasIndex("EmployeeId", "LeaveTypeId", "Year") + .IsUnique(); + + b.ToTable("hr_leave_balances", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveRequest", b => + { + b.Property("LeaveRequestId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LeaveRequestId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DaysCount") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("EndDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LeaveTypeId") + .HasColumnType("integer"); + + b.Property("Reason") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("RejectionReason") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("StartDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("LeaveRequestId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("EmployeeId"); + + b.HasIndex("LeaveTypeId"); + + b.HasIndex("Status"); + + b.HasIndex("StartDate", "EndDate"); + + b.ToTable("hr_leave_requests", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveType", b => + { + b.Property("LeaveTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LeaveTypeId")); + + b.Property("AccrualPerYear") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("CarryForwardAllowed") + .HasColumnType("boolean"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CountsAsNoPay") + .HasColumnType("boolean"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsPaid") + .HasColumnType("boolean"); + + b.Property("MaxCarryForwardDays") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RequiresApproval") + .HasColumnType("boolean"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("LeaveTypeId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_leave_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoanInstallment", b => + { + b.Property("LoanInstallmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LoanInstallmentId")); + + b.Property("DueMonth") + .HasColumnType("integer"); + + b.Property("DueYear") + .HasColumnType("integer"); + + b.Property("EmployeeLoanId") + .HasColumnType("integer"); + + b.Property("InstallmentNumber") + .HasColumnType("integer"); + + b.Property("PaidAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("PayrollRunId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("ScheduledAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("LoanInstallmentId"); + + b.HasIndex("EmployeeLoanId"); + + b.HasIndex("PayrollRunId"); + + b.HasIndex("DueYear", "DueMonth"); + + b.ToTable("hr_loan_installments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NavItem", b => + { + b.Property("NavItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NavItemId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Href") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Icon") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.HasKey("NavItemId"); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("nav_items", (string)null); + + b.HasData( + new + { + NavItemId = 1, + Code = "dashboard", + Href = "/dashboard", + Label = "Dashboard", + SortOrder = 1, + Status = "Active" + }, + new + { + NavItemId = 2, + Code = "products", + Href = "/dashboard/products", + Label = "Products", + SortOrder = 2, + Status = "Active" + }, + new + { + NavItemId = 3, + Code = "vendors", + Href = "/dashboard/vendors", + Label = "Vendors", + SortOrder = 3, + Status = "Active" + }, + new + { + NavItemId = 4, + Code = "procurement", + Href = "/dashboard/procurement", + Label = "Procurement", + SortOrder = 4, + Status = "Active" + }, + new + { + NavItemId = 5, + Code = "receiving", + Href = "/dashboard/receiving/grn", + Label = "Receiving", + SortOrder = 5, + Status = "Active" + }, + new + { + NavItemId = 6, + Code = "stock", + Href = "/dashboard/stock", + Label = "Stock", + SortOrder = 6, + Status = "Active" + }, + new + { + NavItemId = 7, + Code = "warehouses", + Href = "/dashboard/warehouse", + Label = "Warehouses", + SortOrder = 7, + Status = "Active" + }, + new + { + NavItemId = 8, + Code = "orders", + Href = "/dashboard/orders", + Label = "Orders", + SortOrder = 8, + Status = "Active" + }, + new + { + NavItemId = 9, + Code = "settings", + Href = "/dashboard/settings", + Label = "Settings", + SortOrder = 9, + Status = "Active" + }, + new + { + NavItemId = 10, + Code = "help", + Href = "/dashboard/help", + Label = "Help", + SortOrder = 10, + Status = "Active" + }, + new + { + NavItemId = 11, + Code = "ledgers", + Href = "/dashboard/ledgers", + Label = "Ledgers", + SortOrder = 11, + Status = "Active" + }, + new + { + NavItemId = 12, + Code = "accounts", + Href = "/dashboard/accounts", + Label = "Accounts", + SortOrder = 12, + Status = "Active" + }, + new + { + NavItemId = 13, + Code = "sales", + Href = "/dashboard/sales", + Label = "Sales", + SortOrder = 13, + Status = "Active" + }, + new + { + NavItemId = 14, + Code = "production", + Href = "/dashboard/production", + Label = "Production", + SortOrder = 14, + Status = "Active" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => + { + b.Property("NotificationConfigId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.HasKey("NotificationConfigId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("notification_config", null, t => + { + t.HasCheckConstraint("ck_notification_config_singleton", "\"NotificationConfigId\" = 1"); + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfigModule", b => + { + b.Property("NotificationConfigModuleId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NotificationConfigModuleId")); + + b.Property("EmailEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("InAppEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("ModuleKey") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("NotificationConfigId") + .HasColumnType("integer"); + + b.Property("SmsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.HasKey("NotificationConfigModuleId"); + + b.HasIndex("ModuleKey") + .IsUnique(); + + b.HasIndex("NotificationConfigId"); + + b.ToTable("notification_config_modules", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NumberSequence", b => + { + b.Property("SequenceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SequenceId")); + + b.Property("DocType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("doc_type"); + + b.Property("LastNumber") + .HasColumnType("integer") + .HasColumnName("last_number"); + + b.Property("Year") + .HasColumnType("integer") + .HasColumnName("year"); + + b.HasKey("SequenceId"); + + b.HasIndex("DocType", "Year") + .IsUnique(); + + b.ToTable("number_sequences", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => + { + b.Property("PayrollLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollLineId")); + + b.Property("AbsentDays") + .HasColumnType("integer"); + + b.Property("BasicSalary") + .HasColumnType("numeric(18,2)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("EpfEmployeeAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("EpfEmployerAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("EtfEmployerAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("GrossSalary") + .HasColumnType("numeric(18,2)"); + + b.Property("LateDeductionAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("LateMinutesTotal") + .HasColumnType("integer"); + + b.Property("LeaveDays") + .HasColumnType("integer"); + + b.Property("LoanDeductionAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("NetSalary") + .HasColumnType("numeric(18,2)"); + + b.Property("NoPayAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("OtMinutesTotal") + .HasColumnType("integer"); + + b.Property("OtherDeductionsAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("OvertimeAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("PayrollRunId") + .HasColumnType("integer"); + + b.Property("PresentDays") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("TaxAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("TotalAllowances") + .HasColumnType("numeric(18,2)"); + + b.Property("WorkingDays") + .HasColumnType("integer"); + + b.HasKey("PayrollLineId"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("PayrollRunId", "EmployeeId") + .IsUnique(); + + b.ToTable("hr_payroll_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLineComponent", b => + { + b.Property("PayrollLineComponentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollLineComponentId")); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("ComponentCategory") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("PayrollLineId") + .HasColumnType("integer"); + + b.Property("SalaryComponentId") + .HasColumnType("integer"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.HasKey("PayrollLineComponentId"); + + b.HasIndex("PayrollLineId"); + + b.HasIndex("SalaryComponentId"); + + b.ToTable("hr_payroll_line_components", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollRun", b => + { + b.Property("PayrollRunId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollRunId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GeneratedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GeneratedBy") + .HasColumnType("integer"); + + b.Property("LockedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("LockedBy") + .HasColumnType("integer"); + + b.Property("PeriodMonth") + .HasColumnType("integer"); + + b.Property("PeriodYear") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UnlockReason") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("UnlockedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UnlockedBy") + .HasColumnType("integer"); + + b.HasKey("PayrollRunId"); + + b.HasIndex("BranchId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("PeriodYear", "PeriodMonth", "BranchId"); + + b.ToTable("hr_payroll_runs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollStatutorySetting", b => + { + b.Property("PayrollStatutorySettingId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollStatutorySettingId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveTo") + .HasColumnType("timestamp with time zone"); + + b.Property("EpfEmployeeRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("EpfEmployerRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("EtfEmployerRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("OtMultiplierDefault") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.HasKey("PayrollStatutorySettingId"); + + b.HasIndex("EffectiveFrom"); + + b.ToTable("hr_payroll_statutory_settings", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Payslip", b => + { + b.Property("PayslipId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayslipId")); + + b.Property("GeneratedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PayrollLineId") + .HasColumnType("integer"); + + b.Property("ReleasedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReleasedBy") + .HasColumnType("integer"); + + b.HasKey("PayslipId"); + + b.HasIndex("PayrollLineId") + .IsUnique(); + + b.ToTable("hr_payslips", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Permission", b => + { + b.Property("PermissionId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PermissionId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(80) + .HasColumnType("character varying(80)"); + + b.Property("NavItemId") + .HasColumnType("integer"); + + b.Property("SubNavItemId") + .HasColumnType("integer"); + + b.HasKey("PermissionId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("NavItemId"); + + b.HasIndex("SubNavItemId"); + + b.ToTable("permissions", (string)null); + + b.HasData( + new + { + PermissionId = 1, + Code = "NAV:dashboard", + NavItemId = 1 + }, + new + { + PermissionId = 2, + Code = "NAV:products", + NavItemId = 2 + }, + new + { + PermissionId = 3, + Code = "NAV:vendors", + NavItemId = 3 + }, + new + { + PermissionId = 4, + Code = "NAV:procurement", + NavItemId = 4 + }, + new + { + PermissionId = 5, + Code = "NAV:receiving", + NavItemId = 5 + }, + new + { + PermissionId = 6, + Code = "NAV:stock", + NavItemId = 6 + }, + new + { + PermissionId = 7, + Code = "NAV:warehouses", + NavItemId = 7 + }, + new + { + PermissionId = 8, + Code = "NAV:orders", + NavItemId = 8 + }, + new + { + PermissionId = 9, + Code = "NAV:settings", + NavItemId = 9 + }, + new + { + PermissionId = 10, + Code = "NAV:help", + NavItemId = 10 + }, + new + { + PermissionId = 11, + Code = "NAV:products.item", + SubNavItemId = 1 + }, + new + { + PermissionId = 12, + Code = "NAV:products.category", + SubNavItemId = 2 + }, + new + { + PermissionId = 13, + Code = "NAV:products.brand", + SubNavItemId = 3 + }, + new + { + PermissionId = 14, + Code = "NAV:products.item-type", + SubNavItemId = 4 + }, + new + { + PermissionId = 15, + Code = "NAV:products.uom", + SubNavItemId = 5 + }, + new + { + PermissionId = 16, + Code = "NAV:products.configuration", + SubNavItemId = 6 + }, + new + { + PermissionId = 17, + Code = "NAV:settings.roles", + SubNavItemId = 7 + }, + new + { + PermissionId = 18, + Code = "NAV:settings.users", + SubNavItemId = 8 + }, + new + { + PermissionId = 28, + Code = "NAV:procurement.requisitions", + SubNavItemId = 17 + }, + new + { + PermissionId = 29, + Code = "NAV:procurement.rfqs", + SubNavItemId = 18 + }, + new + { + PermissionId = 30, + Code = "NAV:procurement.purchase-orders", + SubNavItemId = 19 + }, + new + { + PermissionId = 31, + Code = "NAV:procurement.purchase-returns", + SubNavItemId = 20 + }, + new + { + PermissionId = 19, + Code = "NAV:ledgers", + NavItemId = 11 + }, + new + { + PermissionId = 20, + Code = "NAV:ledgers.trial-balance", + SubNavItemId = 9 + }, + new + { + PermissionId = 21, + Code = "NAV:ledgers.balance-sheet", + SubNavItemId = 10 + }, + new + { + PermissionId = 22, + Code = "NAV:ledgers.general-ledger", + SubNavItemId = 11 + }, + new + { + PermissionId = 23, + Code = "NAV:ledgers.profit-and-loss", + SubNavItemId = 12 + }, + new + { + PermissionId = 24, + Code = "NAV:ledgers.cash-flow", + SubNavItemId = 13 + }, + new + { + PermissionId = 25, + Code = "NAV:ledgers.budget-vs-actual", + SubNavItemId = 14 + }, + new + { + PermissionId = 27, + Code = "NAV:ledgers.tax-report", + SubNavItemId = 16 + }, + new + { + PermissionId = 26, + Code = "NAV:accounts.bank-accounts", + SubNavItemId = 15 + }, + new + { + PermissionId = 32, + Code = "NAV:accounts", + NavItemId = 12 + }, + new + { + PermissionId = 33, + Code = "NAV:accounts.cheque-books", + SubNavItemId = 21 + }, + new + { + PermissionId = 34, + Code = "NAV:accounts.received-cheques", + SubNavItemId = 22 + }, + new + { + PermissionId = 35, + Code = "NAV:production", + NavItemId = 14 + }, + new + { + PermissionId = 36, + Code = "NAV:production.templates", + SubNavItemId = 27 + }, + new + { + PermissionId = 37, + Code = "NAV:production.runs", + SubNavItemId = 25 + }, + new + { + PermissionId = 38, + Code = "NAV:production.produced", + SubNavItemId = 26 + }, + new + { + PermissionId = 39, + Code = "NAV:procurement.purchase-invoices", + SubNavItemId = 28 + }, + new + { + PermissionId = 40, + Code = "NAV:settings.branches", + SubNavItemId = 29 + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PoLine", b => + { + b.Property("PoLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PoLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("PoId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyReceived") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Tax") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("PoLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("PoId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("po_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductConfig", b => + { + b.Property("ConfigId") + .HasColumnType("integer"); + + b.Property("BatchListsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("BrandsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("ItemTypesEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SellingPricesEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("SerialNumbersEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("SubcategoriesEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.Property("WarrantyPeriodsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.HasKey("ConfigId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("product_config", null, t => + { + t.HasCheckConstraint("ck_product_config_singleton", "\"ConfigId\" = 1"); + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b => + { + b.Property("RunId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunId")); + + b.Property("CancelReasonCodeId") + .HasColumnType("integer"); + + b.Property("CompletedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("OutputBinId") + .HasColumnType("integer"); + + b.Property("ReworkCount") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("ScaleFactor") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("TargetQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TemplateId") + .HasColumnType("integer"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("RunId"); + + b.HasIndex("CancelReasonCodeId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("OutputBinId"); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("TemplateId", "Status"); + + b.ToTable("production_runs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionTemplate", b => + { + b.Property("TemplateId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TemplateId")); + + b.Property("Annotations") + .HasColumnType("jsonb"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("TemplateId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("CreatedBy"); + + b.HasIndex("Status"); + + b.ToTable("production_templates", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", b => + { + b.Property("PurchaseInvoiceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PurchaseInvoiceId")); + + b.Property("BalanceAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VatTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.Property("VendorInvoiceDate") + .HasColumnType("timestamp with time zone"); + + b.Property("VendorInvoiceNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("VendorSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("VendorSnapshotTaxNo") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("PurchaseInvoiceId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("VendorId"); + + b.HasIndex("VendorId", "VendorInvoiceNo"); + + b.ToTable("purchase_invoices", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoiceLine", b => + { + b.Property("PurchaseInvoiceLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PurchaseInvoiceLineId")); + + b.Property("GrnId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PurchaseInvoiceId") + .HasColumnType("integer"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("VatTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("PurchaseInvoiceLineId"); + + b.HasIndex("GrnId") + .IsUnique(); + + b.HasIndex("PurchaseInvoiceId"); + + b.ToTable("purchase_invoice_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoicePayment", b => + { + b.Property("PurchaseInvoicePaymentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PurchaseInvoicePaymentId")); + + b.Property("Amount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BankAccountName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("GlBankAccountId") + .HasColumnType("bigint"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PaymentDate") + .HasColumnType("timestamp with time zone"); + + b.Property("PurchaseInvoiceId") + .HasColumnType("integer"); + + b.Property("Reference") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("PurchaseInvoicePaymentId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("PurchaseInvoiceId"); + + b.ToTable("purchase_invoice_payments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => + { + b.Property("PoId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PoId")); + + b.Property("ApprovalRequired") + .HasColumnType("boolean"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RequisitionId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.HasKey("PoId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("RequisitionId"); + + b.HasIndex("Status"); + + b.HasIndex("VendorId"); + + b.ToTable("purchase_orders", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturn", b => + { + b.Property("ReturnId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReasonCodeId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("ReturnId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("ReasonCodeId"); + + b.HasIndex("VendorId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("purchase_returns", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturnLine", b => + { + b.Property("ReturnLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnLineId")); + + b.Property("GrnLineId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReturnId") + .HasColumnType("integer"); + + b.HasKey("ReturnLineId"); + + b.HasIndex("GrnLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("ReturnId"); + + b.ToTable("purchase_return_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ReasonCode", b => + { + b.Property("ReasonCodeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReasonCodeId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Context") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.HasKey("ReasonCodeId"); + + b.HasIndex("Context", "Code") + .IsUnique(); + + b.ToTable("reason_codes", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => + { + b.Property("RequisitionId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RequisitionId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RequestedBy") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("RequisitionId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("RequestedBy"); + + b.HasIndex("Status"); + + b.ToTable("requisitions", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RequisitionLine", b => + { + b.Property("ReqLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReqLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RequiredBy") + .HasColumnType("date"); + + b.Property("RequisitionId") + .HasColumnType("integer"); + + b.HasKey("ReqLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RequisitionId"); + + b.ToTable("requisition_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => + { + b.Property("RfqId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RfqId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RequisitionId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("RfqId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("RequisitionId"); + + b.ToTable("rfqs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RfqLine", b => + { + b.Property("RfqLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RfqLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RfqId") + .HasColumnType("integer"); + + b.HasKey("RfqLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RfqId"); + + b.ToTable("rfq_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Role", b => + { + b.Property("RoleId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RoleId")); + + b.Property("AuthRoleId") + .HasColumnType("uuid") + .HasColumnName("auth_role_id"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsSystemRole") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("RoleId"); + + b.HasIndex("AuthRoleId") + .IsUnique(); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("roles", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RolePermission", b => + { + b.Property("RoleId") + .HasColumnType("integer"); + + b.Property("PermissionId") + .HasColumnType("integer"); + + b.HasKey("RoleId", "PermissionId"); + + b.HasIndex("PermissionId"); + + b.ToTable("role_permissions", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunEdge", b => + { + b.Property("RunEdgeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunEdgeId")); + + b.Property("ChildRunStageId") + .HasColumnType("integer"); + + b.Property("ParentRunStageId") + .HasColumnType("integer"); + + b.Property("RunId") + .HasColumnType("integer"); + + b.HasKey("RunEdgeId"); + + b.HasIndex("ChildRunStageId"); + + b.HasIndex("RunId"); + + b.HasIndex("ParentRunStageId", "ChildRunStageId") + .IsUnique(); + + b.ToTable("run_edges", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStage", b => + { + b.Property("RunStageId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunStageId")); + + b.Property("ActualEndAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ActualStartAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EstimatedMinutes") + .HasColumnType("integer"); + + b.Property("FieldDefs") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("FieldValues") + .HasColumnType("jsonb"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("PosX") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PosY") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RoleLabel") + .HasMaxLength(60) + .HasColumnType("character varying(60)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("RunId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("TemplateStageId") + .HasColumnType("integer"); + + b.HasKey("RunStageId"); + + b.HasIndex("TemplateStageId"); + + b.HasIndex("RunId", "Status"); + + b.ToTable("run_stages", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageEvent", b => + { + b.Property("EventId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EventId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Note") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Payload") + .HasColumnType("jsonb"); + + b.Property("RunId") + .HasColumnType("integer"); + + b.Property("RunStageId") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("EventId"); + + b.HasIndex("RunStageId"); + + b.HasIndex("UserId"); + + b.HasIndex("RunId", "EventId"); + + b.ToTable("run_stage_events", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageInput", b => + { + b.Property("RunInputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunInputId")); + + b.Property("ConsumedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ConsumedValue") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DeliveredQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("FromRunOutputId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("PlannedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyUnit") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ReturnedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReturnedValue") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RunStageId") + .HasColumnType("integer"); + + b.Property("Source") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("RunInputId"); + + b.HasIndex("FromRunOutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RunStageId"); + + b.ToTable("run_stage_inputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageOutput", b => + { + b.Property("RunOutputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunOutputId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("PlannedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ProducedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RunStageId") + .HasColumnType("integer"); + + b.Property("ScrapReasonCodeId") + .HasColumnType("integer"); + + b.Property("ScrappedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TransferredQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UomId") + .HasColumnType("integer"); + + b.HasKey("RunOutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RunStageId"); + + b.HasIndex("ScrapReasonCodeId"); + + b.HasIndex("UomId"); + + b.ToTable("run_stage_outputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalaryComponent", b => + { + b.Property("SalaryComponentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalaryComponentId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ComponentType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsEpfEtfApplicable") + .HasColumnType("boolean"); + + b.Property("IsTaxable") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("SalaryComponentId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_salary_components", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesDayEnd", b => + { + b.Property("SalesDayEndId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesDayEndId")); + + b.Property("BundleCount") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("BusinessDate") + .HasColumnType("date"); + + b.Property("CashierUserId") + .HasColumnType("integer"); + + b.Property("ClosedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ClosedBy") + .HasColumnType("integer"); + + b.Property("CostOfGoodsSold") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SlipCount") + .HasColumnType("integer"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("SalesDayEndId"); + + b.HasIndex("ClosedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("CashierUserId", "BusinessDate") + .IsUnique(); + + b.ToTable("sales_day_ends", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoice", b => + { + b.Property("SalesInvoiceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesInvoiceId")); + + b.Property("BalanceAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("CreatorUserId") + .HasColumnType("integer"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("CustomerSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CustomerSnapshotTaxNo") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("InvoiceDate") + .HasColumnType("timestamp with time zone"); + + b.Property("InvoiceNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("InvoiceType") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("B2C"); + + b.Property("NetPayable") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RoundOff") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesInvoiceId"); + + b.HasIndex("CreatorUserId"); + + b.HasIndex("CustomerId"); + + b.HasIndex("InvoiceDate"); + + b.HasIndex("InvoiceNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_invoices", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoiceLine", b => + { + b.Property("SalesInvoiceLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesInvoiceLineId")); + + b.Property("BaseCost") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DiscountAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DiscountMode") + .HasColumnType("integer"); + + b.Property("DiscountPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("FreeQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("IsFreeIssue") + .HasColumnType("boolean"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("NetUnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ParentLineId") + .HasColumnType("integer"); + + b.Property("PriceSource") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SalesInvoiceId") + .HasColumnType("integer"); + + b.Property("TaxAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesInvoiceLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SalesInvoiceId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_invoice_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoicePayment", b => + { + b.Property("SalesInvoicePaymentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesInvoicePaymentId")); + + b.Property("Amount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BankAccountName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("GlBankAccountId") + .HasColumnType("bigint"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PaymentDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Reference") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("SalesInvoiceId") + .HasColumnType("integer"); + + b.HasKey("SalesInvoicePaymentId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("SalesInvoiceId"); + + b.ToTable("sales_invoice_payments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturn", b => + { + b.Property("ReturnId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReasonCodeId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("ReturnId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("CustomerId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("ReasonCodeId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_returns", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturnLine", b => + { + b.Property("ReturnLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReturnId") + .HasColumnType("integer"); + + b.Property("SalesInvoiceLineId") + .HasColumnType("integer"); + + b.HasKey("ReturnLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("ReturnId"); + + b.HasIndex("SalesInvoiceLineId"); + + b.ToTable("sales_return_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlip", b => + { + b.Property("SalesSlipId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesSlipId")); + + b.Property("BalanceAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CashierUserId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("CustomerSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DayEndId") + .HasColumnType("integer"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SlipDate") + .HasColumnType("timestamp with time zone"); + + b.Property("SlipNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesSlipId"); + + b.HasIndex("CashierUserId"); + + b.HasIndex("CustomerId"); + + b.HasIndex("DayEndId"); + + b.HasIndex("SlipDate"); + + b.HasIndex("SlipNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_slips", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlipLine", b => + { + b.Property("SalesSlipLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesSlipLineId")); + + b.Property("BaseCost") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DiscountAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DiscountMode") + .HasColumnType("integer"); + + b.Property("DiscountPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("FreeQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("IsFreeIssue") + .HasColumnType("boolean"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("NetUnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ParentLineId") + .HasColumnType("integer"); + + b.Property("PriceSource") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SalesSlipId") + .HasColumnType("integer"); + + b.Property("TaxAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesSlipLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SalesSlipId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_slip_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Serial", b => + { + b.Property("SerialId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SerialId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("SerialNo") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("SerialId"); + + b.HasIndex("ItemId", "SerialNo") + .IsUnique(); + + b.ToTable("serials", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageEdge", b => + { + b.Property("EdgeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EdgeId")); + + b.Property("ChildStageId") + .HasColumnType("integer"); + + b.Property("ParentStageId") + .HasColumnType("integer"); + + b.Property("TemplateId") + .HasColumnType("integer"); + + b.HasKey("EdgeId"); + + b.HasIndex("ChildStageId"); + + b.HasIndex("TemplateId"); + + b.HasIndex("ParentStageId", "ChildStageId") + .IsUnique(); + + b.ToTable("stage_edges", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageInput", b => + { + b.Property("InputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("InputId")); + + b.Property("FromOutputId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyPerBatch") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyUnit") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Source") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("StageId") + .HasColumnType("integer"); + + b.HasKey("InputId"); + + b.HasIndex("FromOutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("StageId"); + + b.ToTable("stage_inputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageOutput", b => + { + b.Property("OutputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("OutputId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("QtyPerBatch") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("StageId") + .HasColumnType("integer"); + + b.Property("UomId") + .HasColumnType("integer"); + + b.HasKey("OutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("StageId"); + + b.HasIndex("UomId"); + + b.ToTable("stage_outputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustment", b => + { + b.Property("AdjustmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AdjustmentId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReasonCodeId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("AdjustmentId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("ReasonCodeId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("stock_adjustments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustmentLine", b => + { + b.Property("AdjLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AdjLineId")); + + b.Property("AdjustmentId") + .HasColumnType("integer"); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyDelta") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.HasKey("AdjLineId"); + + b.HasIndex("AdjustmentId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SerialId"); + + b.ToTable("stock_adjustment_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCount", b => + { + b.Property("CountId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CountId")); + + b.Property("CountType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("CountId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("stock_counts", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCountLine", b => + { + b.Property("CountLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CountLineId")); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("CountId") + .HasColumnType("integer"); + + b.Property("CountedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("SystemQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Variance") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("CountLineId"); + + b.HasIndex("BinId"); + + b.HasIndex("CountId"); + + b.HasIndex("ItemId"); + + b.ToTable("stock_count_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLayer", b => + { + b.Property("LayerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LayerId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("GrnLineId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyReceived") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyRemaining") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReceiptDate") + .HasColumnType("timestamp with time zone"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("LayerId"); + + b.HasIndex("BatchId"); + + b.HasIndex("GrnLineId"); + + b.HasIndex("SerialId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("ItemId", "WarehouseId", "ReceiptDate", "LayerId"); + + b.ToTable("stock_layers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLedger", b => + { + b.Property("LedgerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LedgerId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Direction") + .IsRequired() + .HasMaxLength(5) + .HasColumnType("character varying(5)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyBase") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RunningBalance") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("SourceDocId") + .HasColumnType("integer"); + + b.Property("SourceDocType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.Property("Value") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("LedgerId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("SerialId"); + + b.HasIndex("UserId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("SourceDocType", "SourceDocId"); + + b.HasIndex("ItemId", "WarehouseId", "CreatedAt"); + + b.HasIndex("ItemId", "WarehouseId", "LedgerId"); + + b.ToTable("stock_ledger", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransfer", b => + { + b.Property("TransferId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TransferId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DestWarehouseId") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SrcWarehouseId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("TransferId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DestWarehouseId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("SrcWarehouseId"); + + b.HasIndex("Status"); + + b.ToTable("stock_transfers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransferLine", b => + { + b.Property("TransferLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TransferLineId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("DestBinId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyReceived") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("SrcBinId") + .HasColumnType("integer"); + + b.Property("TransferId") + .HasColumnType("integer"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.HasKey("TransferLineId"); + + b.HasIndex("BatchId"); + + b.HasIndex("DestBinId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SerialId"); + + b.HasIndex("SrcBinId"); + + b.HasIndex("TransferId"); + + b.ToTable("stock_transfer_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubCategory", b => + { + b.Property("SubCategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SubCategoryId")); + + b.Property("CategoryId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("SubCategoryId"); + + b.HasIndex("Status"); + + b.HasIndex("CategoryId", "Name") + .IsUnique(); + + b.ToTable("subcategories", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubNavItem", b => + { + b.Property("SubNavItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SubNavItemId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Href") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Icon") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("NavItemId") + .HasColumnType("integer"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.HasKey("SubNavItemId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("NavItemId"); + + b.ToTable("sub_nav_items", (string)null); + + b.HasData( + new + { + SubNavItemId = 1, + Code = "products.item", + Href = "/dashboard/products", + Label = "Item", + NavItemId = 2, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 2, + Code = "products.category", + Href = "/dashboard/products/categories", + Label = "Category", + NavItemId = 2, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 3, + Code = "products.brand", + Href = "/dashboard/products/brands", + Label = "Brand", + NavItemId = 2, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 4, + Code = "products.item-type", + Href = "/dashboard/products/item-types", + Label = "Item Type", + NavItemId = 2, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 5, + Code = "products.uom", + Href = "/dashboard/products/uoms", + Label = "UOM", + NavItemId = 2, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 6, + Code = "products.configuration", + Href = "/dashboard/products/settings", + Label = "Configuration", + NavItemId = 2, + SortOrder = 6, + Status = "Active" + }, + new + { + SubNavItemId = 29, + Code = "settings.branches", + Href = "/dashboard/settings/branches", + Label = "Branches", + NavItemId = 9, + SortOrder = 0, + Status = "Active" + }, + new + { + SubNavItemId = 7, + Code = "settings.roles", + Href = "/dashboard/settings/roles", + Label = "Roles", + NavItemId = 9, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 8, + Code = "settings.users", + Href = "/dashboard/settings/users", + Label = "Users", + NavItemId = 9, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 24, + Code = "settings.notification-config", + Href = "/dashboard/settings/notification-config", + Label = "Notification Config", + NavItemId = 9, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 23, + Code = "sales.bundle-sales", + Href = "/dashboard/sales/bundles", + Label = "Bundle Sales", + NavItemId = 13, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 17, + Code = "procurement.requisitions", + Href = "/dashboard/procurement/requisitions", + Label = "Requisitions", + NavItemId = 4, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 18, + Code = "procurement.rfqs", + Href = "/dashboard/procurement/rfqs", + Label = "RFQs", + NavItemId = 4, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 19, + Code = "procurement.purchase-orders", + Href = "/dashboard/procurement/purchase-orders", + Label = "Purchase Orders", + NavItemId = 4, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 20, + Code = "procurement.purchase-returns", + Href = "/dashboard/procurement/purchase-returns", + Label = "Purchase Returns", + NavItemId = 4, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 28, + Code = "procurement.purchase-invoices", + Href = "/dashboard/procurement/purchase-invoices", + Label = "Purchase Invoices", + NavItemId = 4, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 9, + Code = "ledgers.trial-balance", + Href = "/dashboard/ledgers/trial-balance", + Label = "Trial Balance", + NavItemId = 11, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 10, + Code = "ledgers.balance-sheet", + Href = "/dashboard/ledgers/balance-sheet", + Label = "Balance Sheet", + NavItemId = 11, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 11, + Code = "ledgers.general-ledger", + Href = "/dashboard/ledgers/general-ledger", + Label = "General Ledger", + NavItemId = 11, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 12, + Code = "ledgers.profit-and-loss", + Href = "/dashboard/ledgers/profit-and-loss", + Label = "Profit & Loss", + NavItemId = 11, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 13, + Code = "ledgers.cash-flow", + Href = "/dashboard/ledgers/cash-flow", + Label = "Cash Flow", + NavItemId = 11, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 14, + Code = "ledgers.budget-vs-actual", + Href = "/dashboard/ledgers/budget-vs-actual", + Label = "Budget vs Actual", + NavItemId = 11, + SortOrder = 6, + Status = "Active" + }, + new + { + SubNavItemId = 16, + Code = "ledgers.tax-report", + Href = "/dashboard/ledgers/tax-report", + Label = "Tax Report", + NavItemId = 11, + SortOrder = 7, + Status = "Active" + }, + new + { + SubNavItemId = 15, + Code = "accounts.bank-accounts", + Href = "/dashboard/accounts/bank-accounts", + Label = "Cash / Bank Accounts", + NavItemId = 12, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 21, + Code = "accounts.cheque-books", + Href = "/dashboard/accounts/cheque-books", + Label = "Cheque Books", + NavItemId = 12, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 22, + Code = "accounts.received-cheques", + Href = "/dashboard/accounts/received-cheques", + Label = "Received Cheques", + NavItemId = 12, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 27, + Code = "production.templates", + Href = "/dashboard/production/templates", + Label = "Templates", + NavItemId = 14, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 25, + Code = "production.runs", + Href = "/dashboard/production/runs", + Label = "Runs", + NavItemId = 14, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 26, + Code = "production.produced", + Href = "/dashboard/production/produced", + Label = "Produced", + NavItemId = 14, + SortOrder = 3, + Status = "Active" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TaxSlab", b => + { + b.Property("TaxSlabId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TaxSlabId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveTo") + .HasColumnType("timestamp with time zone"); + + b.Property("LowerBound") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("Rate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("UpperBound") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.HasKey("TaxSlabId"); + + b.HasIndex("EffectiveFrom"); + + b.ToTable("hr_tax_slabs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => + { + b.Property("StageId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("StageId")); + + b.Property("EstimatedMinutes") + .HasColumnType("integer"); + + b.Property("FieldDefs") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("PosX") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PosY") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RoleLabel") + .HasMaxLength(60) + .HasColumnType("character varying(60)"); + + b.Property("TemplateId") + .HasColumnType("integer"); + + b.HasKey("StageId"); + + b.HasIndex("TemplateId"); + + b.ToTable("template_stages", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Uom", b => + { + b.Property("UomId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("UomId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("UomId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("uoms", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.User", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("UserId")); + + b.Property("AuthUserId") + .HasColumnType("uuid") + .HasColumnName("auth_user_id"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Email") + .HasMaxLength(320) + .HasColumnType("character varying(320)"); + + b.Property("RoleId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("UserId"); + + b.HasIndex("AuthUserId") + .IsUnique(); + + b.HasIndex("Email") + .IsUnique(); + + b.HasIndex("RoleId"); + + b.HasIndex("Username") + .IsUnique(); + + b.ToTable("users", (string)null); + + b.HasData( + new + { + UserId = 1, + DisplayName = "System", + Status = "Active", + Username = "system" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Vendor", b => + { + b.Property("VendorId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("VendorId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Currency") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(3) + .HasColumnType("character varying(3)") + .HasDefaultValue("LKR"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TaxReg") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Terms") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("VendorId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("vendors", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => + { + b.Property("QuotationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("QuotationId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("RfqId") + .HasColumnType("integer"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.HasKey("QuotationId"); + + b.HasIndex("VendorId"); + + b.HasIndex("RfqId", "VendorId") + .IsUnique(); + + b.ToTable("vendor_quotations", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotationLine", b => + { + b.Property("QuotationLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("QuotationLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LeadDays") + .HasColumnType("integer"); + + b.Property("QuotationId") + .HasColumnType("integer"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("QuotationLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("QuotationId"); + + b.ToTable("vendor_quotation_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Warehouse", b => + { + b.Property("WarehouseId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("WarehouseId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.HasKey("WarehouseId"); + + b.HasIndex("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("warehouses", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.WorkShift", b => + { + b.Property("WorkShiftId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("WorkShiftId")); + + b.Property("BreakMinutes") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EndTime") + .HasColumnType("interval"); + + b.Property("GraceMinutes") + .HasColumnType("integer"); + + b.Property("IsOvernight") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("OtMultiplier") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("StandardWorkingMinutes") + .HasColumnType("integer"); + + b.Property("StartTime") + .HasColumnType("interval"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WorkingDaysMask") + .HasColumnType("integer"); + + b.HasKey("WorkShiftId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_work_shifts", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceRecord", b => + { + b.HasOne("ERPCore.Domain.Entities.AttendanceUploadBatch", "AttendanceUploadBatch") + .WithMany() + .HasForeignKey("AttendanceUploadBatchId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.WorkShift", "WorkShift") + .WithMany() + .HasForeignKey("WorkShiftId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("AttendanceUploadBatch"); + + b.Navigation("Employee"); + + b.Navigation("WorkShift"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AuditLog", b => + { + b.HasOne("ERPCore.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Batch", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Bin", b => + { + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany("Bins") + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BranchConfig", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSale", b => + { + b.HasOne("ERPCore.Domain.Entities.BundleSaleTemplate", "BundleSaleTemplate") + .WithMany() + .HasForeignKey("BundleSaleTemplateId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "CashierUser") + .WithMany() + .HasForeignKey("CashierUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesDayEnd", "DayEnd") + .WithMany("BundleSales") + .HasForeignKey("DayEndId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BundleSaleTemplate"); + + b.Navigation("CashierUser"); + + b.Navigation("Customer"); + + b.Navigation("DayEnd"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleLine", b => + { + b.HasOne("ERPCore.Domain.Entities.BundleSale", "BundleSale") + .WithMany("Lines") + .HasForeignKey("BundleSaleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BundleSale"); + + b.Navigation("Item"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplateLine", b => + { + b.HasOne("ERPCore.Domain.Entities.BundleSaleTemplate", "BundleSaleTemplate") + .WithMany("Lines") + .HasForeignKey("BundleSaleTemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BundleSaleTemplate"); + + b.Navigation("Item"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Customer", b => + { + b.HasOne("ERPCore.Domain.Entities.Warehouse", "DefaultWarehouse") + .WithMany() + .HasForeignKey("DefaultWarehouseId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("DefaultWarehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Department", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Employee", "HeadEmployee") + .WithMany() + .HasForeignKey("HeadEmployeeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Department", "ParentDepartment") + .WithMany() + .HasForeignKey("ParentDepartmentId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Branch"); + + b.Navigation("HeadEmployee"); + + b.Navigation("ParentDepartment"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Employee", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Department", "Department") + .WithMany() + .HasForeignKey("DepartmentId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Designation", "Designation") + .WithMany() + .HasForeignKey("DesignationId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.EmploymentType", "EmploymentType") + .WithMany() + .HasForeignKey("EmploymentTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Employee", "ReportingManager") + .WithMany() + .HasForeignKey("ReportingManagerId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithOne() + .HasForeignKey("ERPCore.Domain.Entities.Employee", "UserId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.WorkShift", "WorkShift") + .WithMany() + .HasForeignKey("WorkShiftId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Department"); + + b.Navigation("Designation"); + + b.Navigation("EmploymentType"); + + b.Navigation("ReportingManager"); + + b.Navigation("User"); + + b.Navigation("WorkShift"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeBankDetail", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeDocument", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.HrDocumentType", "HrDocumentType") + .WithMany() + .HasForeignKey("HrDocumentTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("HrDocumentType"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeLoan", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructure", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructureLine", b => + { + b.HasOne("ERPCore.Domain.Entities.EmployeeSalaryStructure", "EmployeeSalaryStructure") + .WithMany("Lines") + .HasForeignKey("EmployeeSalaryStructureId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalaryComponent", "SalaryComponent") + .WithMany() + .HasForeignKey("SalaryComponentId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("EmployeeSalaryStructure"); + + b.Navigation("SalaryComponent"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Grn", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("PoId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.PurchaseInvoice", "PurchaseInvoice") + .WithMany() + .HasForeignKey("PurchaseInvoiceId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("PurchaseInvoice"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Vendor"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", "Batch") + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", "Bin") + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Grn", "Grn") + .WithMany("Lines") + .HasForeignKey("GrnId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PoLine", "PoLine") + .WithMany() + .HasForeignKey("PoLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Batch"); + + b.Navigation("Bin"); + + b.Navigation("Grn"); + + b.Navigation("Item"); + + b.Navigation("PoLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLineWarrantyNumber", b => + { + b.HasOne("ERPCore.Domain.Entities.GrnLine", "GrnLine") + .WithMany("WarrantyNumbers") + .HasForeignKey("GrnLineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GrnLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Item", b => + { + b.HasOne("ERPCore.Domain.Entities.Uom", "BaseUom") + .WithMany() + .HasForeignKey("BaseUomId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Brand", "Brand") + .WithMany() + .HasForeignKey("BrandId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Category", "Category") + .WithMany() + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "DefaultVendor") + .WithMany() + .HasForeignKey("DefaultVendorId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.SubCategory", "SubCategory") + .WithMany() + .HasForeignKey("SubCategoryId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("BaseUom"); + + b.Navigation("Brand"); + + b.Navigation("Category"); + + b.Navigation("DefaultVendor"); + + b.Navigation("SubCategory"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ItemReorder", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany("ReorderSettings") + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveBalance", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.LeaveType", "LeaveType") + .WithMany() + .HasForeignKey("LeaveTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("LeaveType"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveRequest", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.LeaveType", "LeaveType") + .WithMany() + .HasForeignKey("LeaveTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("LeaveType"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoanInstallment", b => + { + b.HasOne("ERPCore.Domain.Entities.EmployeeLoan", "EmployeeLoan") + .WithMany("Installments") + .HasForeignKey("EmployeeLoanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PayrollRun", "PayrollRun") + .WithMany() + .HasForeignKey("PayrollRunId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("EmployeeLoan"); + + b.Navigation("PayrollRun"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfigModule", b => + { + b.HasOne("ERPCore.Domain.Entities.NotificationConfig", "NotificationConfig") + .WithMany("Modules") + .HasForeignKey("NotificationConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("NotificationConfig"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PayrollRun", "PayrollRun") + .WithMany("Lines") + .HasForeignKey("PayrollRunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("PayrollRun"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLineComponent", b => + { + b.HasOne("ERPCore.Domain.Entities.PayrollLine", "PayrollLine") + .WithMany("Components") + .HasForeignKey("PayrollLineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalaryComponent", "SalaryComponent") + .WithMany() + .HasForeignKey("SalaryComponentId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("PayrollLine"); + + b.Navigation("SalaryComponent"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollRun", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Branch"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Payslip", b => + { + b.HasOne("ERPCore.Domain.Entities.PayrollLine", "PayrollLine") + .WithOne() + .HasForeignKey("ERPCore.Domain.Entities.Payslip", "PayrollLineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PayrollLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Permission", b => + { + b.HasOne("ERPCore.Domain.Entities.NavItem", "NavItem") + .WithMany() + .HasForeignKey("NavItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ERPCore.Domain.Entities.SubNavItem", "SubNavItem") + .WithMany() + .HasForeignKey("SubNavItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("NavItem"); + + b.Navigation("SubNavItem"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PoLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseOrder", "PurchaseOrder") + .WithMany("Lines") + .HasForeignKey("PoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductConfig", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b => + { + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "CancelReason") + .WithMany() + .HasForeignKey("CancelReasonCodeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Bin", "OutputBin") + .WithMany() + .HasForeignKey("OutputBinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") + .WithMany("Runs") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CancelReason"); + + b.Navigation("Creator"); + + b.Navigation("OutputBin"); + + b.Navigation("Template"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionTemplate", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoiceLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Grn", "Grn") + .WithMany() + .HasForeignKey("GrnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseInvoice", "PurchaseInvoice") + .WithMany("Lines") + .HasForeignKey("PurchaseInvoiceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Grn"); + + b.Navigation("PurchaseInvoice"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoicePayment", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseInvoice", "PurchaseInvoice") + .WithMany("Payments") + .HasForeignKey("PurchaseInvoiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("PurchaseInvoice"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") + .WithMany() + .HasForeignKey("RequisitionId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("Requisition"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturn", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ReasonCode") + .WithMany() + .HasForeignKey("ReasonCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("ReasonCode"); + + b.Navigation("Vendor"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturnLine", b => + { + b.HasOne("ERPCore.Domain.Entities.GrnLine", "GrnLine") + .WithMany() + .HasForeignKey("GrnLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseReturn", "Return") + .WithMany("Lines") + .HasForeignKey("ReturnId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GrnLine"); + + b.Navigation("Item"); + + b.Navigation("Return"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Requester") + .WithMany() + .HasForeignKey("RequestedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Requester"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RequisitionLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") + .WithMany("Lines") + .HasForeignKey("RequisitionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Requisition"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => + { + b.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") + .WithMany() + .HasForeignKey("RequisitionId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Requisition"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RfqLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Rfq", "Rfq") + .WithMany("Lines") + .HasForeignKey("RfqId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Rfq"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RolePermission", b => + { + b.HasOne("ERPCore.Domain.Entities.Permission", "Permission") + .WithMany() + .HasForeignKey("PermissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Role", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Permission"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunEdge", b => + { + b.HasOne("ERPCore.Domain.Entities.RunStage", "ChildRunStage") + .WithMany() + .HasForeignKey("ChildRunStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "ParentRunStage") + .WithMany() + .HasForeignKey("ParentRunStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ProductionRun", "Run") + .WithMany("Edges") + .HasForeignKey("RunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildRunStage"); + + b.Navigation("ParentRunStage"); + + b.Navigation("Run"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStage", b => + { + b.HasOne("ERPCore.Domain.Entities.ProductionRun", "Run") + .WithMany("Stages") + .HasForeignKey("RunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "TemplateStage") + .WithMany() + .HasForeignKey("TemplateStageId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Run"); + + b.Navigation("TemplateStage"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageEvent", b => + { + b.HasOne("ERPCore.Domain.Entities.ProductionRun", "Run") + .WithMany("Events") + .HasForeignKey("RunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "RunStage") + .WithMany("Events") + .HasForeignKey("RunStageId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Run"); + + b.Navigation("RunStage"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageInput", b => + { + b.HasOne("ERPCore.Domain.Entities.RunStageOutput", "FromRunOutput") + .WithMany() + .HasForeignKey("FromRunOutputId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "RunStage") + .WithMany("Inputs") + .HasForeignKey("RunStageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromRunOutput"); + + b.Navigation("Item"); + + b.Navigation("RunStage"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageOutput", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "RunStage") + .WithMany("Outputs") + .HasForeignKey("RunStageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ScrapReason") + .WithMany() + .HasForeignKey("ScrapReasonCodeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Uom", "Uom") + .WithMany() + .HasForeignKey("UomId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Item"); + + b.Navigation("RunStage"); + + b.Navigation("ScrapReason"); + + b.Navigation("Uom"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesDayEnd", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "CashierUser") + .WithMany() + .HasForeignKey("CashierUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "ClosedByUser") + .WithMany() + .HasForeignKey("ClosedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CashierUser"); + + b.Navigation("ClosedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoice", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatorUserId"); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("Customer"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoiceLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesInvoice", "SalesInvoice") + .WithMany("Lines") + .HasForeignKey("SalesInvoiceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SalesInvoice"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoicePayment", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesInvoice", "SalesInvoice") + .WithMany("Payments") + .HasForeignKey("SalesInvoiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("SalesInvoice"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturn", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ReasonCode") + .WithMany() + .HasForeignKey("ReasonCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("Customer"); + + b.Navigation("ReasonCode"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturnLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesReturn", "Return") + .WithMany("Lines") + .HasForeignKey("ReturnId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesInvoiceLine", "SalesInvoiceLine") + .WithMany() + .HasForeignKey("SalesInvoiceLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Item"); + + b.Navigation("Return"); + + b.Navigation("SalesInvoiceLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlip", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "CashierUser") + .WithMany() + .HasForeignKey("CashierUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesDayEnd", "DayEnd") + .WithMany("Slips") + .HasForeignKey("DayEndId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CashierUser"); + + b.Navigation("Customer"); + + b.Navigation("DayEnd"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlipLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesSlip", "SalesSlip") + .WithMany("Lines") + .HasForeignKey("SalesSlipId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SalesSlip"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Serial", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageEdge", b => + { + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "ChildStage") + .WithMany() + .HasForeignKey("ChildStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "ParentStage") + .WithMany() + .HasForeignKey("ParentStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") + .WithMany("Edges") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildStage"); + + b.Navigation("ParentStage"); + + b.Navigation("Template"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageInput", b => + { + b.HasOne("ERPCore.Domain.Entities.StageOutput", "FromOutput") + .WithMany() + .HasForeignKey("FromOutputId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "Stage") + .WithMany("Inputs") + .HasForeignKey("StageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromOutput"); + + b.Navigation("Item"); + + b.Navigation("Stage"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageOutput", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "Stage") + .WithMany("Outputs") + .HasForeignKey("StageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Uom", "Uom") + .WithMany() + .HasForeignKey("UomId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Item"); + + b.Navigation("Stage"); + + b.Navigation("Uom"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustment", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ReasonCode") + .WithMany() + .HasForeignKey("ReasonCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("ReasonCode"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustmentLine", b => + { + b.HasOne("ERPCore.Domain.Entities.StockAdjustment", "Adjustment") + .WithMany("Lines") + .HasForeignKey("AdjustmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Batch", null) + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", null) + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Adjustment"); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCount", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCountLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.StockCount", "Count") + .WithMany("Lines") + .HasForeignKey("CountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Count"); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLayer", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", "Batch") + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.GrnLine", "GrnLine") + .WithMany() + .HasForeignKey("GrnLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", "Serial") + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Batch"); + + b.Navigation("GrnLine"); + + b.Navigation("Item"); + + b.Navigation("Serial"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLedger", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", null) + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", null) + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", null) + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", null) + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransfer", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "DestWarehouse") + .WithMany() + .HasForeignKey("DestWarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "SrcWarehouse") + .WithMany() + .HasForeignKey("SrcWarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("DestWarehouse"); + + b.Navigation("SrcWarehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransferLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", null) + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("DestBinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", null) + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("SrcBinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.StockTransfer", "Transfer") + .WithMany("Lines") + .HasForeignKey("TransferId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Transfer"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubCategory", b => + { + b.HasOne("ERPCore.Domain.Entities.Category", "Category") + .WithMany("SubCategories") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubNavItem", b => + { + b.HasOne("ERPCore.Domain.Entities.NavItem", "NavItem") + .WithMany("Children") + .HasForeignKey("NavItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("NavItem"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => + { + b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") + .WithMany("Stages") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Template"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.User", b => + { + b.HasOne("ERPCore.Domain.Entities.Role", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => + { + b.HasOne("ERPCore.Domain.Entities.Rfq", "Rfq") + .WithMany("Quotations") + .HasForeignKey("RfqId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Rfq"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotationLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.VendorQuotation", "Quotation") + .WithMany("Lines") + .HasForeignKey("QuotationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Quotation"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Warehouse", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSale", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplate", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Category", b => + { + b.Navigation("SubCategories"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeLoan", b => + { + b.Navigation("Installments"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructure", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Grn", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLine", b => + { + b.Navigation("WarrantyNumbers"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Item", b => + { + b.Navigation("ReorderSettings"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NavItem", b => + { + b.Navigation("Children"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => + { + b.Navigation("Modules"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => + { + b.Navigation("Components"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollRun", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b => + { + b.Navigation("Edges"); + + b.Navigation("Events"); + + b.Navigation("Stages"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionTemplate", b => + { + b.Navigation("Edges"); + + b.Navigation("Runs"); + + b.Navigation("Stages"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", b => + { + b.Navigation("Lines"); + + b.Navigation("Payments"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturn", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => + { + b.Navigation("Lines"); + + b.Navigation("Quotations"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStage", b => + { + b.Navigation("Events"); + + b.Navigation("Inputs"); + + b.Navigation("Outputs"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesDayEnd", b => + { + b.Navigation("BundleSales"); + + b.Navigation("Slips"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoice", b => + { + b.Navigation("Lines"); + + b.Navigation("Payments"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturn", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlip", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustment", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCount", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransfer", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => + { + b.Navigation("Inputs"); + + b.Navigation("Outputs"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Warehouse", b => + { + b.Navigation("Bins"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Backend/ERPCore/Migrations/20260914061430_AddUomLifecycleColumnsLocal.cs b/Backend/ERPCore/Migrations/20260914061430_AddUomLifecycleColumnsLocal.cs new file mode 100644 index 0000000..4c66e9c --- /dev/null +++ b/Backend/ERPCore/Migrations/20260914061430_AddUomLifecycleColumnsLocal.cs @@ -0,0 +1,61 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace ERPCore.Migrations +{ + /// + public partial class AddUomLifecycleColumnsLocal : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "CreatedAt", + table: "uoms", + type: "timestamp with time zone", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + + migrationBuilder.AddColumn( + name: "Status", + table: "uoms", + type: "character varying(20)", + maxLength: 20, + nullable: false, + defaultValue: "Active"); + + migrationBuilder.AddColumn( + name: "UpdatedAt", + table: "uoms", + type: "timestamp with time zone", + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_uoms_Status", + table: "uoms", + column: "Status"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_uoms_Status", + table: "uoms"); + + migrationBuilder.DropColumn( + name: "CreatedAt", + table: "uoms"); + + migrationBuilder.DropColumn( + name: "Status", + table: "uoms"); + + migrationBuilder.DropColumn( + name: "UpdatedAt", + table: "uoms"); + } + } +} diff --git a/Backend/ERPCore/Migrations/20260915044627_AddSupportTickets.Designer.cs b/Backend/ERPCore/Migrations/20260915044627_AddSupportTickets.Designer.cs new file mode 100644 index 0000000..27bb805 --- /dev/null +++ b/Backend/ERPCore/Migrations/20260915044627_AddSupportTickets.Designer.cs @@ -0,0 +1,8408 @@ +// +using System; +using ERPCore.Infra.Persistence; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace ERPCore.Migrations +{ + [DbContext(typeof(ErpDbContext))] + [Migration("20260915044627_AddSupportTickets")] + partial class AddSupportTickets + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.9") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceRecord", b => + { + b.Property("AttendanceRecordId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AttendanceRecordId")); + + b.Property("AttendanceDate") + .HasColumnType("timestamp with time zone"); + + b.Property("AttendanceStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("AttendanceUploadBatchId") + .HasColumnType("integer"); + + b.Property("CheckIn") + .HasColumnType("interval"); + + b.Property("CheckOut") + .HasColumnType("interval"); + + b.Property("DuplicateOfAttendanceRecordId") + .HasColumnType("integer"); + + b.Property("EarlyLeaveMinutes") + .HasColumnType("integer"); + + b.Property("EditedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EditedBy") + .HasColumnType("integer"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("IsManualOverride") + .HasColumnType("boolean"); + + b.Property("LateMinutes") + .HasColumnType("integer"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("OvertimeMinutes") + .HasColumnType("integer"); + + b.Property("RowValidationStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("WorkShiftId") + .HasColumnType("integer"); + + b.Property("WorkingMinutes") + .HasColumnType("integer"); + + b.HasKey("AttendanceRecordId"); + + b.HasIndex("AttendanceUploadBatchId"); + + b.HasIndex("WorkShiftId"); + + b.HasIndex("EmployeeId", "AttendanceDate"); + + b.ToTable("hr_attendance_records", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceUploadBatch", b => + { + b.Property("AttendanceUploadBatchId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AttendanceUploadBatchId")); + + b.Property("ConfirmedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ConfirmedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("OriginalFileName") + .HasMaxLength(260) + .HasColumnType("character varying(260)"); + + b.Property("PeriodEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("PeriodStart") + .HasColumnType("timestamp with time zone"); + + b.Property("RowCountDuplicate") + .HasColumnType("integer"); + + b.Property("RowCountError") + .HasColumnType("integer"); + + b.Property("RowCountTotal") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SourceType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UploadedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UploadedBy") + .HasColumnType("integer"); + + b.HasKey("AttendanceUploadBatchId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("PeriodStart", "PeriodEnd"); + + b.ToTable("hr_attendance_upload_batches", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AuditLog", b => + { + b.Property("AuditId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AuditId")); + + b.Property("Action") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("ChangeSet") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EntityId") + .HasColumnType("integer"); + + b.Property("EntityType") + .IsRequired() + .HasMaxLength(80) + .HasColumnType("character varying(80)"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("AuditId"); + + b.HasIndex("CreatedAt"); + + b.HasIndex("UserId"); + + b.HasIndex("EntityType", "EntityId"); + + b.ToTable("audit_logs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Batch", b => + { + b.Property("BatchId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BatchId")); + + b.Property("BatchNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ExpiryDate") + .HasColumnType("date"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.HasKey("BatchId"); + + b.HasIndex("ItemId", "BatchNo") + .IsUnique(); + + b.ToTable("batches", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Bin", b => + { + b.Property("BinId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BinId")); + + b.Property("BinType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BinId"); + + b.HasIndex("WarehouseId", "Code") + .IsUnique(); + + b.ToTable("bins", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Branch", b => + { + b.Property("BranchId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BranchId")); + + b.Property("Address") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("PhoneNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_branches", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BranchConfig", b => + { + b.Property("ConfigId") + .HasColumnType("integer"); + + b.Property("BranchingEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.HasKey("ConfigId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("branch_config", null, t => + { + t.HasCheckConstraint("ck_branch_config_singleton", "\"ConfigId\" = 1"); + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Brand", b => + { + b.Property("BrandId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BrandId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("BrandId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("brands", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSale", b => + { + b.Property("BundleSaleId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleId")); + + b.Property("BundleCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BundleDate") + .HasColumnType("timestamp with time zone"); + + b.Property("BundleName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("BundleNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BundlePrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BundleSaleTemplateId") + .HasColumnType("integer"); + + b.Property("CashierUserId") + .HasColumnType("integer"); + + b.Property("ComponentSubtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("CustomerSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DayEndId") + .HasColumnType("integer"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("MarginAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BundleSaleId"); + + b.HasIndex("BundleNo") + .IsUnique(); + + b.HasIndex("BundleSaleTemplateId"); + + b.HasIndex("CashierUserId"); + + b.HasIndex("CustomerId"); + + b.HasIndex("DayEndId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("bundle_sales", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleLine", b => + { + b.Property("BundleSaleLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleLineId")); + + b.Property("BundleSaleId") + .HasColumnType("integer"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("IncludeInBundle") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("IsComponent") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ParentLineId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BundleSaleLineId"); + + b.HasIndex("BundleSaleId"); + + b.HasIndex("ItemId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("bundle_sale_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplate", b => + { + b.Property("BundleSaleTemplateId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleTemplateId")); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TemplateCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("TemplateName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("BundleSaleTemplateId"); + + b.HasIndex("TemplateCode") + .IsUnique(); + + b.ToTable("bundle_sale_templates", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplateLine", b => + { + b.Property("BundleSaleTemplateLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleTemplateLineId")); + + b.Property("BundleSaleTemplateId") + .HasColumnType("integer"); + + b.Property("IncludeInBundle") + .HasColumnType("boolean"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SortOrder") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BundleSaleTemplateLineId"); + + b.HasIndex("BundleSaleTemplateId"); + + b.HasIndex("ItemId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("bundle_sale_template_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Category", b => + { + b.Property("CategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CategoryId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("CategoryId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("categories", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Customer", b => + { + b.Property("CustomerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CustomerId")); + + b.Property("AddressLine1") + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("AddressLine2") + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("City") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Country") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreditDays") + .HasColumnType("integer"); + + b.Property("CreditLimit") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CustomerCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CustomerType") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("B2C"); + + b.Property("DefaultWarehouseId") + .HasColumnType("integer"); + + b.Property("DisplayName") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Email") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Phone") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TaxRegistrationNo") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("CustomerId"); + + b.HasIndex("CustomerCode") + .IsUnique(); + + b.HasIndex("CustomerType"); + + b.HasIndex("DefaultWarehouseId"); + + b.HasIndex("Status"); + + b.ToTable("customers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Department", b => + { + b.Property("DepartmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("DepartmentId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("HeadEmployeeId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("ParentDepartmentId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("DepartmentId"); + + b.HasIndex("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("HeadEmployeeId"); + + b.HasIndex("ParentDepartmentId"); + + b.HasIndex("Status"); + + b.ToTable("hr_departments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Designation", b => + { + b.Property("DesignationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("DesignationId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("DesignationId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_designations", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Employee", b => + { + b.Property("EmployeeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeId")); + + b.Property("AddressLine1") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("AddressLine2") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("City") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ConfirmationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Country") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DateOfBirth") + .HasColumnType("timestamp with time zone"); + + b.Property("DepartmentId") + .HasColumnType("integer"); + + b.Property("DesignationId") + .HasColumnType("integer"); + + b.Property("Email") + .HasMaxLength(320) + .HasColumnType("character varying(320)"); + + b.Property("EmergencyContactName") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("EmergencyContactPhone") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmergencyContactRelationship") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("EmployeeCode") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmploymentTypeId") + .HasColumnType("integer"); + + b.Property("EpfNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EtfNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Gender") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("HireDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LastWorkingDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Nationality") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Nic") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PersonalMobile") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PostalCode") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ProfilePhotoPath") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("ReportingManagerId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TaxIdentificationNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.Property("WorkShiftId") + .HasColumnType("integer"); + + b.HasKey("EmployeeId"); + + b.HasIndex("BranchId"); + + b.HasIndex("DepartmentId"); + + b.HasIndex("DesignationId"); + + b.HasIndex("Email"); + + b.HasIndex("EmployeeCode") + .IsUnique(); + + b.HasIndex("EmploymentTypeId"); + + b.HasIndex("ReportingManagerId"); + + b.HasIndex("Status"); + + b.HasIndex("UserId") + .IsUnique(); + + b.HasIndex("WorkShiftId"); + + b.ToTable("hr_employees", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeBankDetail", b => + { + b.Property("EmployeeBankDetailId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeBankDetailId")); + + b.Property("AccountHolderName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("AccountNumber") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BankName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("BranchName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("IsPrimary") + .HasColumnType("boolean"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("SwiftCode") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("EmployeeBankDetailId"); + + b.HasIndex("EmployeeId"); + + b.ToTable("hr_employee_bank_details", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeDocument", b => + { + b.Property("EmployeeDocumentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeDocumentId")); + + b.Property("ContentType") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("ExpiryDate") + .HasColumnType("timestamp with time zone"); + + b.Property("HrDocumentTypeId") + .HasColumnType("integer"); + + b.Property("IssueDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("OriginalFileName") + .IsRequired() + .HasMaxLength(260) + .HasColumnType("character varying(260)"); + + b.Property("RelativePath") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SizeBytes") + .HasColumnType("bigint"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("StoredFileName") + .IsRequired() + .HasMaxLength(260) + .HasColumnType("character varying(260)"); + + b.Property("UploadedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UploadedBy") + .HasColumnType("integer"); + + b.Property("VerifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VerifiedBy") + .HasColumnType("integer"); + + b.HasKey("EmployeeDocumentId"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("ExpiryDate"); + + b.HasIndex("HrDocumentTypeId"); + + b.ToTable("hr_employee_documents", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeLoan", b => + { + b.Property("EmployeeLoanId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeLoanId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("InstallmentAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("InterestRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("LoanKind") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("NumberOfInstallments") + .HasColumnType("integer"); + + b.Property("OutstandingBalance") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("PrincipalAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("StartMonth") + .HasColumnType("integer"); + + b.Property("StartYear") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("EmployeeLoanId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("EmployeeId"); + + b.HasIndex("Status"); + + b.ToTable("hr_employee_loans", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructure", b => + { + b.Property("EmployeeSalaryStructureId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeSalaryStructureId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("BasicSalary") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("Currency") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("character varying(3)"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveTo") + .HasColumnType("timestamp with time zone"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("EmployeeSalaryStructureId"); + + b.HasIndex("EmployeeId", "EffectiveTo"); + + b.ToTable("hr_employee_salary_structures", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructureLine", b => + { + b.Property("EmployeeSalaryStructureLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeSalaryStructureLineId")); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("EmployeeSalaryStructureId") + .HasColumnType("integer"); + + b.Property("SalaryComponentId") + .HasColumnType("integer"); + + b.HasKey("EmployeeSalaryStructureLineId"); + + b.HasIndex("EmployeeSalaryStructureId"); + + b.HasIndex("SalaryComponentId"); + + b.ToTable("hr_employee_salary_structure_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmploymentType", b => + { + b.Property("EmploymentTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmploymentTypeId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("EmploymentTypeId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_employment_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Grn", b => + { + b.Property("GrnId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("GrnId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PoId") + .HasColumnType("integer"); + + b.Property("PostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PurchaseInvoiceId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("GrnId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("PoId"); + + b.HasIndex("PurchaseInvoiceId"); + + b.HasIndex("Status"); + + b.HasIndex("VendorId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("grns", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLine", b => + { + b.Property("GrnLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("GrnLineId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("DiscountPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("GrnId") + .HasColumnType("integer"); + + b.Property("HoldStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("NetUnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("PoLineId") + .HasColumnType("integer"); + + b.Property("PoUnitPrice") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReceivedValue") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("VatAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("VatPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.HasKey("GrnLineId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("GrnId"); + + b.HasIndex("ItemId"); + + b.HasIndex("PoLineId"); + + b.ToTable("grn_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLineWarrantyNumber", b => + { + b.Property("GrnLineWarrantyNumberId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("GrnLineWarrantyNumberId")); + + b.Property("GrnLineId") + .HasColumnType("integer"); + + b.Property("WarrantyNo") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("WarrantyPeriodMonths") + .HasColumnType("integer"); + + b.HasKey("GrnLineWarrantyNumberId"); + + b.HasIndex("GrnLineId", "WarrantyNo") + .IsUnique(); + + b.ToTable("grn_line_warranty_numbers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.HrDocumentType", b => + { + b.Property("HrDocumentTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("HrDocumentTypeId")); + + b.Property("Category") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpiryTracked") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RequiredAtOnboarding") + .HasColumnType("boolean"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("HrDocumentTypeId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_document_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Item", b => + { + b.Property("ItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ItemId")); + + b.Property("BaseUomId") + .HasColumnType("integer"); + + b.Property("BrandId") + .HasColumnType("integer"); + + b.Property("CategoryId") + .HasColumnType("integer"); + + b.Property("ContentBaseQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ContentBaseUnit") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ContentQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ContentUnit") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DefaultVendorId") + .HasColumnType("integer"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SellingFlatPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SellingMaxPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SellingMinPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Sku") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("StockNature") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("SubCategoryId") + .HasColumnType("integer"); + + b.Property("TaxClass") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("TrackingMode") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Warranty") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("NonWarranty"); + + b.Property("WarrantyPeriodMonths") + .HasColumnType("integer"); + + b.HasKey("ItemId"); + + b.HasIndex("BaseUomId"); + + b.HasIndex("BrandId"); + + b.HasIndex("CategoryId"); + + b.HasIndex("DefaultVendorId"); + + b.HasIndex("Sku") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("SubCategoryId"); + + b.ToTable("items", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ItemReorder", b => + { + b.Property("ReorderId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReorderId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("ReorderPoint") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReorderQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("ReorderId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("ItemId", "WarehouseId") + .IsUnique(); + + b.ToTable("item_reorders", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ItemType", b => + { + b.Property("ItemTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ItemTypeId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsMeasurable") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("ItemTypeId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("item_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.JournalEntryStub", b => + { + b.Property("JournalId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("JournalId")); + + b.Property("Amount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CreditAccount") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("DebitAccount") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("SourceDocId") + .HasColumnType("integer"); + + b.Property("SourceDocType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.HasKey("JournalId"); + + b.HasIndex("SourceDocType", "SourceDocId"); + + b.ToTable("journal_entry_stubs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveBalance", b => + { + b.Property("LeaveBalanceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LeaveBalanceId")); + + b.Property("AdjustmentDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("CarriedForwardDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("EntitledDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("LeaveTypeId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("TakenDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Year") + .HasColumnType("integer"); + + b.HasKey("LeaveBalanceId"); + + b.HasIndex("LeaveTypeId"); + + b.HasIndex("EmployeeId", "LeaveTypeId", "Year") + .IsUnique(); + + b.ToTable("hr_leave_balances", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveRequest", b => + { + b.Property("LeaveRequestId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LeaveRequestId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DaysCount") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("EndDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LeaveTypeId") + .HasColumnType("integer"); + + b.Property("Reason") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("RejectionReason") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("StartDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("LeaveRequestId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("EmployeeId"); + + b.HasIndex("LeaveTypeId"); + + b.HasIndex("Status"); + + b.HasIndex("StartDate", "EndDate"); + + b.ToTable("hr_leave_requests", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveType", b => + { + b.Property("LeaveTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LeaveTypeId")); + + b.Property("AccrualPerYear") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("CarryForwardAllowed") + .HasColumnType("boolean"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CountsAsNoPay") + .HasColumnType("boolean"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsPaid") + .HasColumnType("boolean"); + + b.Property("MaxCarryForwardDays") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RequiresApproval") + .HasColumnType("boolean"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("LeaveTypeId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_leave_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoanInstallment", b => + { + b.Property("LoanInstallmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LoanInstallmentId")); + + b.Property("DueMonth") + .HasColumnType("integer"); + + b.Property("DueYear") + .HasColumnType("integer"); + + b.Property("EmployeeLoanId") + .HasColumnType("integer"); + + b.Property("InstallmentNumber") + .HasColumnType("integer"); + + b.Property("PaidAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("PayrollRunId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("ScheduledAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("LoanInstallmentId"); + + b.HasIndex("EmployeeLoanId"); + + b.HasIndex("PayrollRunId"); + + b.HasIndex("DueYear", "DueMonth"); + + b.ToTable("hr_loan_installments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoginActivity", b => + { + b.Property("LoginActivityId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LoginActivityId")); + + b.Property("DeviceLabel") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("IpAddress") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("LoginAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserAgent") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("LoginActivityId"); + + b.HasIndex("UserId", "LoginAt"); + + b.ToTable("login_activities", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NavItem", b => + { + b.Property("NavItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NavItemId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Href") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Icon") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.HasKey("NavItemId"); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("nav_items", (string)null); + + b.HasData( + new + { + NavItemId = 1, + Code = "dashboard", + Href = "/dashboard", + Label = "Dashboard", + SortOrder = 1, + Status = "Active" + }, + new + { + NavItemId = 2, + Code = "products", + Href = "/dashboard/products", + Label = "Products", + SortOrder = 2, + Status = "Active" + }, + new + { + NavItemId = 4, + Code = "procurement", + Href = "/dashboard/procurement", + Label = "Procurement", + SortOrder = 4, + Status = "Active" + }, + new + { + NavItemId = 5, + Code = "receiving", + Href = "/dashboard/receiving/grn", + Label = "Receiving", + SortOrder = 5, + Status = "Active" + }, + new + { + NavItemId = 6, + Code = "stock", + Href = "/dashboard/stock", + Label = "Stock", + SortOrder = 6, + Status = "Active" + }, + new + { + NavItemId = 7, + Code = "warehouses", + Href = "/dashboard/warehouse", + Label = "Warehouses", + SortOrder = 7, + Status = "Active" + }, + new + { + NavItemId = 8, + Code = "orders", + Href = "/dashboard/orders", + Label = "Orders", + SortOrder = 8, + Status = "Active" + }, + new + { + NavItemId = 9, + Code = "settings", + Href = "/dashboard/settings", + Label = "Settings", + SortOrder = 9, + Status = "Active" + }, + new + { + NavItemId = 10, + Code = "help", + Href = "/dashboard/help", + Label = "Help", + SortOrder = 10, + Status = "Active" + }, + new + { + NavItemId = 11, + Code = "ledgers", + Href = "/dashboard/ledgers", + Label = "Ledgers", + SortOrder = 11, + Status = "Active" + }, + new + { + NavItemId = 12, + Code = "accounts", + Href = "/dashboard/accounts", + Label = "Accounts", + SortOrder = 12, + Status = "Active" + }, + new + { + NavItemId = 13, + Code = "sales", + Href = "/dashboard/sales", + Label = "Sales", + SortOrder = 13, + Status = "Active" + }, + new + { + NavItemId = 14, + Code = "production", + Href = "/dashboard/production", + Label = "Production", + SortOrder = 14, + Status = "Active" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Notification", b => + { + b.Property("NotificationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NotificationId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("ModuleKey") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("RelatedEntityId") + .HasColumnType("integer"); + + b.Property("RelatedEntityType") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.HasKey("NotificationId"); + + b.HasIndex("CreatedAt"); + + b.ToTable("notifications", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => + { + b.Property("NotificationConfigId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.HasKey("NotificationConfigId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("notification_config", null, t => + { + t.HasCheckConstraint("ck_notification_config_singleton", "\"NotificationConfigId\" = 1"); + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfigModule", b => + { + b.Property("NotificationConfigModuleId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NotificationConfigModuleId")); + + b.Property("EmailEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("InAppEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("ModuleKey") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("NotificationConfigId") + .HasColumnType("integer"); + + b.Property("SmsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.HasKey("NotificationConfigModuleId"); + + b.HasIndex("ModuleKey") + .IsUnique(); + + b.HasIndex("NotificationConfigId"); + + b.ToTable("notification_config_modules", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationRecipient", b => + { + b.Property("NotificationRecipientId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NotificationRecipientId")); + + b.Property("IsRead") + .HasColumnType("boolean"); + + b.Property("NotificationId") + .HasColumnType("integer"); + + b.Property("ReadAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("NotificationRecipientId"); + + b.HasIndex("NotificationId"); + + b.HasIndex("UserId", "IsRead", "NotificationId"); + + b.ToTable("notification_recipients", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NumberSequence", b => + { + b.Property("SequenceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SequenceId")); + + b.Property("DocType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("doc_type"); + + b.Property("LastNumber") + .HasColumnType("integer") + .HasColumnName("last_number"); + + b.Property("Year") + .HasColumnType("integer") + .HasColumnName("year"); + + b.HasKey("SequenceId"); + + b.HasIndex("DocType", "Year") + .IsUnique(); + + b.ToTable("number_sequences", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => + { + b.Property("PayrollLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollLineId")); + + b.Property("AbsentDays") + .HasColumnType("integer"); + + b.Property("BasicSalary") + .HasColumnType("numeric(18,2)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("EpfEmployeeAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("EpfEmployerAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("EtfEmployerAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("GrossSalary") + .HasColumnType("numeric(18,2)"); + + b.Property("LateDeductionAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("LateMinutesTotal") + .HasColumnType("integer"); + + b.Property("LeaveDays") + .HasColumnType("integer"); + + b.Property("LoanDeductionAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("NetSalary") + .HasColumnType("numeric(18,2)"); + + b.Property("NoPayAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("OtMinutesTotal") + .HasColumnType("integer"); + + b.Property("OtherDeductionsAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("OvertimeAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("PayrollRunId") + .HasColumnType("integer"); + + b.Property("PresentDays") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("TaxAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("TotalAllowances") + .HasColumnType("numeric(18,2)"); + + b.Property("WorkingDays") + .HasColumnType("integer"); + + b.HasKey("PayrollLineId"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("PayrollRunId", "EmployeeId") + .IsUnique(); + + b.ToTable("hr_payroll_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLineComponent", b => + { + b.Property("PayrollLineComponentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollLineComponentId")); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("ComponentCategory") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("PayrollLineId") + .HasColumnType("integer"); + + b.Property("SalaryComponentId") + .HasColumnType("integer"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.HasKey("PayrollLineComponentId"); + + b.HasIndex("PayrollLineId"); + + b.HasIndex("SalaryComponentId"); + + b.ToTable("hr_payroll_line_components", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollRun", b => + { + b.Property("PayrollRunId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollRunId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GeneratedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GeneratedBy") + .HasColumnType("integer"); + + b.Property("LockedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("LockedBy") + .HasColumnType("integer"); + + b.Property("PeriodMonth") + .HasColumnType("integer"); + + b.Property("PeriodYear") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UnlockReason") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("UnlockedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UnlockedBy") + .HasColumnType("integer"); + + b.HasKey("PayrollRunId"); + + b.HasIndex("BranchId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("PeriodYear", "PeriodMonth", "BranchId"); + + b.ToTable("hr_payroll_runs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollStatutorySetting", b => + { + b.Property("PayrollStatutorySettingId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollStatutorySettingId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveTo") + .HasColumnType("timestamp with time zone"); + + b.Property("EpfEmployeeRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("EpfEmployerRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("EtfEmployerRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("OtMultiplierDefault") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.HasKey("PayrollStatutorySettingId"); + + b.HasIndex("EffectiveFrom"); + + b.ToTable("hr_payroll_statutory_settings", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Payslip", b => + { + b.Property("PayslipId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayslipId")); + + b.Property("GeneratedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PayrollLineId") + .HasColumnType("integer"); + + b.Property("ReleasedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReleasedBy") + .HasColumnType("integer"); + + b.HasKey("PayslipId"); + + b.HasIndex("PayrollLineId") + .IsUnique(); + + b.ToTable("hr_payslips", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Permission", b => + { + b.Property("PermissionId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PermissionId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(80) + .HasColumnType("character varying(80)"); + + b.Property("NavItemId") + .HasColumnType("integer"); + + b.Property("SubNavItemId") + .HasColumnType("integer"); + + b.HasKey("PermissionId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("NavItemId"); + + b.HasIndex("SubNavItemId"); + + b.ToTable("permissions", (string)null); + + b.HasData( + new + { + PermissionId = 1, + Code = "NAV:dashboard", + NavItemId = 1 + }, + new + { + PermissionId = 2, + Code = "NAV:products", + NavItemId = 2 + }, + new + { + PermissionId = 3, + Code = "NAV:procurement.vendors", + SubNavItemId = 30 + }, + new + { + PermissionId = 4, + Code = "NAV:procurement", + NavItemId = 4 + }, + new + { + PermissionId = 5, + Code = "NAV:receiving", + NavItemId = 5 + }, + new + { + PermissionId = 6, + Code = "NAV:stock", + NavItemId = 6 + }, + new + { + PermissionId = 7, + Code = "NAV:warehouses", + NavItemId = 7 + }, + new + { + PermissionId = 8, + Code = "NAV:orders", + NavItemId = 8 + }, + new + { + PermissionId = 9, + Code = "NAV:settings", + NavItemId = 9 + }, + new + { + PermissionId = 10, + Code = "NAV:help", + NavItemId = 10 + }, + new + { + PermissionId = 11, + Code = "NAV:products.item", + SubNavItemId = 1 + }, + new + { + PermissionId = 12, + Code = "NAV:products.category", + SubNavItemId = 2 + }, + new + { + PermissionId = 13, + Code = "NAV:products.brand", + SubNavItemId = 3 + }, + new + { + PermissionId = 14, + Code = "NAV:products.item-type", + SubNavItemId = 4 + }, + new + { + PermissionId = 15, + Code = "NAV:products.uom", + SubNavItemId = 5 + }, + new + { + PermissionId = 16, + Code = "NAV:products.configuration", + SubNavItemId = 6 + }, + new + { + PermissionId = 17, + Code = "NAV:settings.roles", + SubNavItemId = 7 + }, + new + { + PermissionId = 18, + Code = "NAV:settings.users", + SubNavItemId = 8 + }, + new + { + PermissionId = 28, + Code = "NAV:procurement.requisitions", + SubNavItemId = 17 + }, + new + { + PermissionId = 29, + Code = "NAV:procurement.rfqs", + SubNavItemId = 18 + }, + new + { + PermissionId = 30, + Code = "NAV:procurement.purchase-orders", + SubNavItemId = 19 + }, + new + { + PermissionId = 31, + Code = "NAV:procurement.purchase-returns", + SubNavItemId = 20 + }, + new + { + PermissionId = 19, + Code = "NAV:ledgers", + NavItemId = 11 + }, + new + { + PermissionId = 20, + Code = "NAV:ledgers.trial-balance", + SubNavItemId = 9 + }, + new + { + PermissionId = 21, + Code = "NAV:ledgers.balance-sheet", + SubNavItemId = 10 + }, + new + { + PermissionId = 22, + Code = "NAV:ledgers.general-ledger", + SubNavItemId = 11 + }, + new + { + PermissionId = 23, + Code = "NAV:ledgers.profit-and-loss", + SubNavItemId = 12 + }, + new + { + PermissionId = 24, + Code = "NAV:ledgers.cash-flow", + SubNavItemId = 13 + }, + new + { + PermissionId = 25, + Code = "NAV:ledgers.budget-vs-actual", + SubNavItemId = 14 + }, + new + { + PermissionId = 27, + Code = "NAV:ledgers.tax-report", + SubNavItemId = 16 + }, + new + { + PermissionId = 26, + Code = "NAV:accounts.bank-accounts", + SubNavItemId = 15 + }, + new + { + PermissionId = 32, + Code = "NAV:accounts", + NavItemId = 12 + }, + new + { + PermissionId = 33, + Code = "NAV:accounts.cheque-books", + SubNavItemId = 21 + }, + new + { + PermissionId = 34, + Code = "NAV:accounts.received-cheques", + SubNavItemId = 22 + }, + new + { + PermissionId = 35, + Code = "NAV:production", + NavItemId = 14 + }, + new + { + PermissionId = 36, + Code = "NAV:production.templates", + SubNavItemId = 27 + }, + new + { + PermissionId = 37, + Code = "NAV:production.runs", + SubNavItemId = 25 + }, + new + { + PermissionId = 38, + Code = "NAV:production.produced", + SubNavItemId = 26 + }, + new + { + PermissionId = 39, + Code = "NAV:procurement.purchase-invoices", + SubNavItemId = 28 + }, + new + { + PermissionId = 40, + Code = "NAV:settings.branches", + SubNavItemId = 29 + }, + new + { + PermissionId = 41, + Code = "NAV:stock.ledger", + SubNavItemId = 31 + }, + new + { + PermissionId = 42, + Code = "NAV:stock.enquiry", + SubNavItemId = 32 + }, + new + { + PermissionId = 43, + Code = "NAV:stock.valuation", + SubNavItemId = 33 + }, + new + { + PermissionId = 44, + Code = "NAV:stock.transfers", + SubNavItemId = 34 + }, + new + { + PermissionId = 45, + Code = "NAV:stock.adjustments", + SubNavItemId = 35 + }, + new + { + PermissionId = 46, + Code = "NAV:stock.counts", + SubNavItemId = 36 + }, + new + { + PermissionId = 47, + Code = "NAV:stock.reorder-alerts", + SubNavItemId = 37 + }, + new + { + PermissionId = 48, + Code = "NAV:stock.wastage", + SubNavItemId = 38 + }, + new + { + PermissionId = 49, + Code = "NAV:sales.bundle-templates", + SubNavItemId = 23 + }, + new + { + PermissionId = 50, + Code = "NAV:sales.invoices", + SubNavItemId = 40 + }, + new + { + PermissionId = 51, + Code = "NAV:sales.free-issues", + SubNavItemId = 41 + }, + new + { + PermissionId = 52, + Code = "NAV:sales.day-end", + SubNavItemId = 42 + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PoLine", b => + { + b.Property("PoLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PoLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("PoId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyReceived") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Tax") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("PoLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("PoId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("po_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductConfig", b => + { + b.Property("ConfigId") + .HasColumnType("integer"); + + b.Property("BatchListsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("BrandsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("ItemTypesEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SellingPricesEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("SerialNumbersEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("SubcategoriesEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.Property("WarrantyPeriodsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.HasKey("ConfigId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("product_config", null, t => + { + t.HasCheckConstraint("ck_product_config_singleton", "\"ConfigId\" = 1"); + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b => + { + b.Property("RunId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunId")); + + b.Property("CancelReasonCodeId") + .HasColumnType("integer"); + + b.Property("CompletedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("OutputBinId") + .HasColumnType("integer"); + + b.Property("ReworkCount") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("ScaleFactor") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("TargetQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TemplateId") + .HasColumnType("integer"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("RunId"); + + b.HasIndex("CancelReasonCodeId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("OutputBinId"); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("TemplateId", "Status"); + + b.ToTable("production_runs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionTemplate", b => + { + b.Property("TemplateId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TemplateId")); + + b.Property("Annotations") + .HasColumnType("jsonb"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("TemplateId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("CreatedBy"); + + b.HasIndex("Status"); + + b.ToTable("production_templates", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", b => + { + b.Property("PurchaseInvoiceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PurchaseInvoiceId")); + + b.Property("BalanceAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VatTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.Property("VendorInvoiceDate") + .HasColumnType("timestamp with time zone"); + + b.Property("VendorInvoiceNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("VendorSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("VendorSnapshotTaxNo") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("PurchaseInvoiceId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("VendorId"); + + b.HasIndex("VendorId", "VendorInvoiceNo"); + + b.ToTable("purchase_invoices", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoiceLine", b => + { + b.Property("PurchaseInvoiceLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PurchaseInvoiceLineId")); + + b.Property("GrnId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PurchaseInvoiceId") + .HasColumnType("integer"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("VatTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("PurchaseInvoiceLineId"); + + b.HasIndex("GrnId") + .IsUnique(); + + b.HasIndex("PurchaseInvoiceId"); + + b.ToTable("purchase_invoice_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoicePayment", b => + { + b.Property("PurchaseInvoicePaymentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PurchaseInvoicePaymentId")); + + b.Property("Amount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BankAccountName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("GlBankAccountId") + .HasColumnType("bigint"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PaymentDate") + .HasColumnType("timestamp with time zone"); + + b.Property("PurchaseInvoiceId") + .HasColumnType("integer"); + + b.Property("Reference") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("PurchaseInvoicePaymentId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("PurchaseInvoiceId"); + + b.ToTable("purchase_invoice_payments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => + { + b.Property("PoId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PoId")); + + b.Property("ApprovalRequired") + .HasColumnType("boolean"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RequisitionId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.HasKey("PoId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("RequisitionId"); + + b.HasIndex("Status"); + + b.HasIndex("VendorId"); + + b.ToTable("purchase_orders", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturn", b => + { + b.Property("ReturnId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReasonCodeId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("ReturnId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("ReasonCodeId"); + + b.HasIndex("VendorId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("purchase_returns", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturnLine", b => + { + b.Property("ReturnLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnLineId")); + + b.Property("GrnLineId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReturnId") + .HasColumnType("integer"); + + b.HasKey("ReturnLineId"); + + b.HasIndex("GrnLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("ReturnId"); + + b.ToTable("purchase_return_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ReasonCode", b => + { + b.Property("ReasonCodeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReasonCodeId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Context") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.HasKey("ReasonCodeId"); + + b.HasIndex("Context", "Code") + .IsUnique(); + + b.ToTable("reason_codes", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => + { + b.Property("RequisitionId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RequisitionId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RequestedBy") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("RequisitionId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("RequestedBy"); + + b.HasIndex("Status"); + + b.ToTable("requisitions", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RequisitionLine", b => + { + b.Property("ReqLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReqLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RequiredBy") + .HasColumnType("date"); + + b.Property("RequisitionId") + .HasColumnType("integer"); + + b.HasKey("ReqLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RequisitionId"); + + b.ToTable("requisition_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => + { + b.Property("RfqId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RfqId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RequisitionId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("RfqId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("RequisitionId"); + + b.ToTable("rfqs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RfqLine", b => + { + b.Property("RfqLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RfqLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RfqId") + .HasColumnType("integer"); + + b.HasKey("RfqLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RfqId"); + + b.ToTable("rfq_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Role", b => + { + b.Property("RoleId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RoleId")); + + b.Property("AuthRoleId") + .HasColumnType("uuid") + .HasColumnName("auth_role_id"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsSystemRole") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("RoleId"); + + b.HasIndex("AuthRoleId") + .IsUnique(); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("roles", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RolePermission", b => + { + b.Property("RoleId") + .HasColumnType("integer"); + + b.Property("PermissionId") + .HasColumnType("integer"); + + b.HasKey("RoleId", "PermissionId"); + + b.HasIndex("PermissionId"); + + b.ToTable("role_permissions", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunEdge", b => + { + b.Property("RunEdgeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunEdgeId")); + + b.Property("ChildRunStageId") + .HasColumnType("integer"); + + b.Property("ParentRunStageId") + .HasColumnType("integer"); + + b.Property("RunId") + .HasColumnType("integer"); + + b.HasKey("RunEdgeId"); + + b.HasIndex("ChildRunStageId"); + + b.HasIndex("RunId"); + + b.HasIndex("ParentRunStageId", "ChildRunStageId") + .IsUnique(); + + b.ToTable("run_edges", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStage", b => + { + b.Property("RunStageId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunStageId")); + + b.Property("ActualEndAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ActualStartAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EstimatedMinutes") + .HasColumnType("integer"); + + b.Property("FieldDefs") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("FieldValues") + .HasColumnType("jsonb"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("PosX") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PosY") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RoleLabel") + .HasMaxLength(60) + .HasColumnType("character varying(60)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("RunId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("TemplateStageId") + .HasColumnType("integer"); + + b.HasKey("RunStageId"); + + b.HasIndex("TemplateStageId"); + + b.HasIndex("RunId", "Status"); + + b.ToTable("run_stages", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageEvent", b => + { + b.Property("EventId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EventId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Note") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Payload") + .HasColumnType("jsonb"); + + b.Property("RunId") + .HasColumnType("integer"); + + b.Property("RunStageId") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("EventId"); + + b.HasIndex("RunStageId"); + + b.HasIndex("UserId"); + + b.HasIndex("RunId", "EventId"); + + b.ToTable("run_stage_events", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageInput", b => + { + b.Property("RunInputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunInputId")); + + b.Property("ConsumedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ConsumedValue") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DeliveredQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("FromRunOutputId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("PlannedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyUnit") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ReturnedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReturnedValue") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RunStageId") + .HasColumnType("integer"); + + b.Property("Source") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("RunInputId"); + + b.HasIndex("FromRunOutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RunStageId"); + + b.ToTable("run_stage_inputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageOutput", b => + { + b.Property("RunOutputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunOutputId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("PlannedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ProducedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RunStageId") + .HasColumnType("integer"); + + b.Property("ScrapReasonCodeId") + .HasColumnType("integer"); + + b.Property("ScrappedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TransferredQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UomId") + .HasColumnType("integer"); + + b.HasKey("RunOutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RunStageId"); + + b.HasIndex("ScrapReasonCodeId"); + + b.HasIndex("UomId"); + + b.ToTable("run_stage_outputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalaryComponent", b => + { + b.Property("SalaryComponentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalaryComponentId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ComponentType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsEpfEtfApplicable") + .HasColumnType("boolean"); + + b.Property("IsTaxable") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("SalaryComponentId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_salary_components", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesDayEnd", b => + { + b.Property("SalesDayEndId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesDayEndId")); + + b.Property("BundleCount") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("BusinessDate") + .HasColumnType("date"); + + b.Property("CashierUserId") + .HasColumnType("integer"); + + b.Property("ClosedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ClosedBy") + .HasColumnType("integer"); + + b.Property("CostOfGoodsSold") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SlipCount") + .HasColumnType("integer"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("SalesDayEndId"); + + b.HasIndex("ClosedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("CashierUserId", "BusinessDate") + .IsUnique(); + + b.ToTable("sales_day_ends", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoice", b => + { + b.Property("SalesInvoiceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesInvoiceId")); + + b.Property("BalanceAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("CreatorUserId") + .HasColumnType("integer"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("CustomerSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CustomerSnapshotTaxNo") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("InvoiceDate") + .HasColumnType("timestamp with time zone"); + + b.Property("InvoiceNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("InvoiceType") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("B2C"); + + b.Property("NetPayable") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RoundOff") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesInvoiceId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatorUserId"); + + b.HasIndex("CustomerId"); + + b.HasIndex("InvoiceDate"); + + b.HasIndex("InvoiceNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_invoices", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoiceLine", b => + { + b.Property("SalesInvoiceLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesInvoiceLineId")); + + b.Property("BaseCost") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DiscountAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DiscountMode") + .HasColumnType("integer"); + + b.Property("DiscountPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("FreeQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("IsFreeIssue") + .HasColumnType("boolean"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("NetUnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ParentLineId") + .HasColumnType("integer"); + + b.Property("PriceSource") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SalesInvoiceId") + .HasColumnType("integer"); + + b.Property("TaxAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesInvoiceLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SalesInvoiceId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_invoice_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoicePayment", b => + { + b.Property("SalesInvoicePaymentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesInvoicePaymentId")); + + b.Property("Amount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BankAccountName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("GlBankAccountId") + .HasColumnType("bigint"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PaymentDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Reference") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("SalesInvoiceId") + .HasColumnType("integer"); + + b.HasKey("SalesInvoicePaymentId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("SalesInvoiceId"); + + b.ToTable("sales_invoice_payments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturn", b => + { + b.Property("ReturnId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReasonCodeId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("ReturnId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("CustomerId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("ReasonCodeId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_returns", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturnLine", b => + { + b.Property("ReturnLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReturnId") + .HasColumnType("integer"); + + b.Property("SalesInvoiceLineId") + .HasColumnType("integer"); + + b.HasKey("ReturnLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("ReturnId"); + + b.HasIndex("SalesInvoiceLineId"); + + b.ToTable("sales_return_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlip", b => + { + b.Property("SalesSlipId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesSlipId")); + + b.Property("BalanceAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CashierUserId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("CustomerSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DayEndId") + .HasColumnType("integer"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SlipDate") + .HasColumnType("timestamp with time zone"); + + b.Property("SlipNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesSlipId"); + + b.HasIndex("CashierUserId"); + + b.HasIndex("CustomerId"); + + b.HasIndex("DayEndId"); + + b.HasIndex("SlipDate"); + + b.HasIndex("SlipNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_slips", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlipLine", b => + { + b.Property("SalesSlipLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesSlipLineId")); + + b.Property("BaseCost") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DiscountAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DiscountMode") + .HasColumnType("integer"); + + b.Property("DiscountPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("FreeQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("IsFreeIssue") + .HasColumnType("boolean"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("NetUnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ParentLineId") + .HasColumnType("integer"); + + b.Property("PriceSource") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SalesSlipId") + .HasColumnType("integer"); + + b.Property("TaxAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesSlipLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SalesSlipId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_slip_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Serial", b => + { + b.Property("SerialId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SerialId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("SerialNo") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("SerialId"); + + b.HasIndex("ItemId", "SerialNo") + .IsUnique(); + + b.ToTable("serials", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageEdge", b => + { + b.Property("EdgeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EdgeId")); + + b.Property("ChildStageId") + .HasColumnType("integer"); + + b.Property("ParentStageId") + .HasColumnType("integer"); + + b.Property("TemplateId") + .HasColumnType("integer"); + + b.HasKey("EdgeId"); + + b.HasIndex("ChildStageId"); + + b.HasIndex("TemplateId"); + + b.HasIndex("ParentStageId", "ChildStageId") + .IsUnique(); + + b.ToTable("stage_edges", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageInput", b => + { + b.Property("InputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("InputId")); + + b.Property("FromOutputId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyPerBatch") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyUnit") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Source") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("StageId") + .HasColumnType("integer"); + + b.HasKey("InputId"); + + b.HasIndex("FromOutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("StageId"); + + b.ToTable("stage_inputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageOutput", b => + { + b.Property("OutputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("OutputId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("QtyPerBatch") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("StageId") + .HasColumnType("integer"); + + b.Property("UomId") + .HasColumnType("integer"); + + b.HasKey("OutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("StageId"); + + b.HasIndex("UomId"); + + b.ToTable("stage_outputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustment", b => + { + b.Property("AdjustmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AdjustmentId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReasonCodeId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("AdjustmentId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("ReasonCodeId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("stock_adjustments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustmentLine", b => + { + b.Property("AdjLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AdjLineId")); + + b.Property("AdjustmentId") + .HasColumnType("integer"); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyDelta") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.HasKey("AdjLineId"); + + b.HasIndex("AdjustmentId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SerialId"); + + b.ToTable("stock_adjustment_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCount", b => + { + b.Property("CountId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CountId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CountType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("CountId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("stock_counts", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCountLine", b => + { + b.Property("CountLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CountLineId")); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("CountId") + .HasColumnType("integer"); + + b.Property("CountedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("SystemQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Variance") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("CountLineId"); + + b.HasIndex("BinId"); + + b.HasIndex("CountId"); + + b.HasIndex("ItemId"); + + b.ToTable("stock_count_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLayer", b => + { + b.Property("LayerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LayerId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("GrnLineId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyReceived") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyRemaining") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReceiptDate") + .HasColumnType("timestamp with time zone"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("LayerId"); + + b.HasIndex("BatchId"); + + b.HasIndex("GrnLineId"); + + b.HasIndex("SerialId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("ItemId", "WarehouseId", "ReceiptDate", "LayerId"); + + b.ToTable("stock_layers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLedger", b => + { + b.Property("LedgerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LedgerId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Direction") + .IsRequired() + .HasMaxLength(5) + .HasColumnType("character varying(5)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyBase") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RunningBalance") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("SourceDocId") + .HasColumnType("integer"); + + b.Property("SourceDocType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.Property("Value") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("LedgerId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("SerialId"); + + b.HasIndex("UserId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("SourceDocType", "SourceDocId"); + + b.HasIndex("ItemId", "WarehouseId", "CreatedAt"); + + b.HasIndex("ItemId", "WarehouseId", "LedgerId"); + + b.ToTable("stock_ledger", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransfer", b => + { + b.Property("TransferId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TransferId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DestWarehouseId") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SrcWarehouseId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("TransferId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DestWarehouseId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("SrcWarehouseId"); + + b.HasIndex("Status"); + + b.ToTable("stock_transfers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransferLine", b => + { + b.Property("TransferLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TransferLineId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("DestBinId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyReceived") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("SrcBinId") + .HasColumnType("integer"); + + b.Property("TransferId") + .HasColumnType("integer"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.HasKey("TransferLineId"); + + b.HasIndex("BatchId"); + + b.HasIndex("DestBinId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SerialId"); + + b.HasIndex("SrcBinId"); + + b.HasIndex("TransferId"); + + b.ToTable("stock_transfer_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubCategory", b => + { + b.Property("SubCategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SubCategoryId")); + + b.Property("CategoryId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("SubCategoryId"); + + b.HasIndex("Status"); + + b.HasIndex("CategoryId", "Name") + .IsUnique(); + + b.ToTable("subcategories", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubNavItem", b => + { + b.Property("SubNavItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SubNavItemId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Href") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Icon") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("NavItemId") + .HasColumnType("integer"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.HasKey("SubNavItemId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("NavItemId"); + + b.ToTable("sub_nav_items", (string)null); + + b.HasData( + new + { + SubNavItemId = 1, + Code = "products.item", + Href = "/dashboard/products", + Label = "Item", + NavItemId = 2, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 2, + Code = "products.category", + Href = "/dashboard/products/categories", + Label = "Category", + NavItemId = 2, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 3, + Code = "products.brand", + Href = "/dashboard/products/brands", + Label = "Brand", + NavItemId = 2, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 4, + Code = "products.item-type", + Href = "/dashboard/products/item-types", + Label = "Item Type", + NavItemId = 2, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 5, + Code = "products.uom", + Href = "/dashboard/products/uoms", + Label = "UOM", + NavItemId = 2, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 6, + Code = "products.configuration", + Href = "/dashboard/products/settings", + Label = "Configuration", + NavItemId = 2, + SortOrder = 6, + Status = "Active" + }, + new + { + SubNavItemId = 29, + Code = "settings.branches", + Href = "/dashboard/settings/branches", + Label = "Branches", + NavItemId = 9, + SortOrder = 0, + Status = "Active" + }, + new + { + SubNavItemId = 7, + Code = "settings.roles", + Href = "/dashboard/settings/roles", + Label = "Roles", + NavItemId = 9, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 8, + Code = "settings.users", + Href = "/dashboard/settings/users", + Label = "Users", + NavItemId = 9, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 24, + Code = "settings.notification-config", + Href = "/dashboard/settings/notification-config", + Label = "Notification Config", + NavItemId = 9, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 40, + Code = "sales.invoices", + Href = "/dashboard/sales/invoices", + Label = "Sales", + NavItemId = 13, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 23, + Code = "sales.bundle-templates", + Href = "/dashboard/sales/bundles/templates", + Label = "Bundle Templates", + NavItemId = 13, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 41, + Code = "sales.free-issues", + Href = "/dashboard/sales/free-issues", + Label = "Free Issues", + NavItemId = 13, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 42, + Code = "sales.day-end", + Href = "/dashboard/sales/day-end", + Label = "Day End", + NavItemId = 13, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 30, + Code = "procurement.vendors", + Href = "/dashboard/vendors", + Label = "Vendors", + NavItemId = 4, + SortOrder = 0, + Status = "Active" + }, + new + { + SubNavItemId = 17, + Code = "procurement.requisitions", + Href = "/dashboard/procurement/requisitions", + Label = "Requisitions", + NavItemId = 4, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 18, + Code = "procurement.rfqs", + Href = "/dashboard/procurement/rfqs", + Label = "RFQs", + NavItemId = 4, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 19, + Code = "procurement.purchase-orders", + Href = "/dashboard/procurement/purchase-orders", + Label = "Purchase Orders", + NavItemId = 4, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 20, + Code = "procurement.purchase-returns", + Href = "/dashboard/procurement/purchase-returns", + Label = "Purchase Returns", + NavItemId = 4, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 28, + Code = "procurement.purchase-invoices", + Href = "/dashboard/procurement/purchase-invoices", + Label = "Purchase Invoices", + NavItemId = 4, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 9, + Code = "ledgers.trial-balance", + Href = "/dashboard/ledgers/trial-balance", + Label = "Trial Balance", + NavItemId = 11, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 10, + Code = "ledgers.balance-sheet", + Href = "/dashboard/ledgers/balance-sheet", + Label = "Balance Sheet", + NavItemId = 11, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 11, + Code = "ledgers.general-ledger", + Href = "/dashboard/ledgers/general-ledger", + Label = "General Ledger", + NavItemId = 11, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 12, + Code = "ledgers.profit-and-loss", + Href = "/dashboard/ledgers/profit-and-loss", + Label = "Profit & Loss", + NavItemId = 11, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 13, + Code = "ledgers.cash-flow", + Href = "/dashboard/ledgers/cash-flow", + Label = "Cash Flow", + NavItemId = 11, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 14, + Code = "ledgers.budget-vs-actual", + Href = "/dashboard/ledgers/budget-vs-actual", + Label = "Budget vs Actual", + NavItemId = 11, + SortOrder = 6, + Status = "Active" + }, + new + { + SubNavItemId = 16, + Code = "ledgers.tax-report", + Href = "/dashboard/ledgers/tax-report", + Label = "Tax Report", + NavItemId = 11, + SortOrder = 7, + Status = "Active" + }, + new + { + SubNavItemId = 15, + Code = "accounts.bank-accounts", + Href = "/dashboard/accounts/bank-accounts", + Label = "Cash / Bank Accounts", + NavItemId = 12, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 21, + Code = "accounts.cheque-books", + Href = "/dashboard/accounts/cheque-books", + Label = "Cheque Books", + NavItemId = 12, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 22, + Code = "accounts.received-cheques", + Href = "/dashboard/accounts/received-cheques", + Label = "Received Cheques", + NavItemId = 12, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 27, + Code = "production.templates", + Href = "/dashboard/production/templates", + Label = "Templates", + NavItemId = 14, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 25, + Code = "production.runs", + Href = "/dashboard/production/runs", + Label = "Runs", + NavItemId = 14, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 26, + Code = "production.produced", + Href = "/dashboard/production/produced", + Label = "Produced", + NavItemId = 14, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 31, + Code = "stock.ledger", + Href = "/dashboard/stock/ledger", + Label = "Stock Ledger", + NavItemId = 6, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 32, + Code = "stock.enquiry", + Href = "/dashboard/stock/enquiry", + Label = "Stock Enquiry", + NavItemId = 6, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 33, + Code = "stock.valuation", + Href = "/dashboard/stock/valuation", + Label = "Valuation", + NavItemId = 6, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 34, + Code = "stock.transfers", + Href = "/dashboard/stock/transfers", + Label = "Transfers", + NavItemId = 6, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 35, + Code = "stock.adjustments", + Href = "/dashboard/stock/adjustments", + Label = "Adjustments", + NavItemId = 6, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 36, + Code = "stock.counts", + Href = "/dashboard/stock/counts", + Label = "Counts", + NavItemId = 6, + SortOrder = 6, + Status = "Active" + }, + new + { + SubNavItemId = 37, + Code = "stock.reorder-alerts", + Href = "/dashboard/stock/reorder-alerts", + Label = "Reorder Alerts", + NavItemId = 6, + SortOrder = 7, + Status = "Active" + }, + new + { + SubNavItemId = 38, + Code = "stock.wastage", + Href = "/dashboard/stock/wastage", + Label = "Wastage", + NavItemId = 6, + SortOrder = 8, + Status = "Active" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicket", b => + { + b.Property("TicketId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TicketId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedByUserId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Subject") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("TicketId"); + + b.HasIndex("CreatedByUserId"); + + b.HasIndex("Status"); + + b.ToTable("support_tickets", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicketMessage", b => + { + b.Property("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("MessageId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsFromAdmin") + .HasColumnType("boolean"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("SenderUserId") + .HasColumnType("integer"); + + b.Property("TicketId") + .HasColumnType("integer"); + + b.HasKey("MessageId"); + + b.HasIndex("TicketId", "CreatedAt"); + + b.ToTable("support_ticket_messages", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TaxSlab", b => + { + b.Property("TaxSlabId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TaxSlabId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveTo") + .HasColumnType("timestamp with time zone"); + + b.Property("LowerBound") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("Rate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("UpperBound") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.HasKey("TaxSlabId"); + + b.HasIndex("EffectiveFrom"); + + b.ToTable("hr_tax_slabs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => + { + b.Property("StageId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("StageId")); + + b.Property("EstimatedMinutes") + .HasColumnType("integer"); + + b.Property("FieldDefs") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("PosX") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PosY") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RoleLabel") + .HasMaxLength(60) + .HasColumnType("character varying(60)"); + + b.Property("TemplateId") + .HasColumnType("integer"); + + b.HasKey("StageId"); + + b.HasIndex("TemplateId"); + + b.ToTable("template_stages", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Uom", b => + { + b.Property("UomId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("UomId")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("UomId"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("uoms", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.User", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("UserId")); + + b.Property("AuthUserId") + .HasColumnType("uuid") + .HasColumnName("auth_user_id"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Email") + .HasMaxLength(320) + .HasColumnType("character varying(320)"); + + b.Property("RoleId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("UserId"); + + b.HasIndex("AuthUserId") + .IsUnique(); + + b.HasIndex("Email") + .IsUnique(); + + b.HasIndex("RoleId"); + + b.HasIndex("Username") + .IsUnique(); + + b.ToTable("users", (string)null); + + b.HasData( + new + { + UserId = 1, + DisplayName = "System", + Status = "Active", + Username = "system" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Vendor", b => + { + b.Property("VendorId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("VendorId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Currency") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(3) + .HasColumnType("character varying(3)") + .HasDefaultValue("LKR"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TaxReg") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Terms") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("VendorId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("vendors", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => + { + b.Property("QuotationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("QuotationId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("RfqId") + .HasColumnType("integer"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.HasKey("QuotationId"); + + b.HasIndex("VendorId"); + + b.HasIndex("RfqId", "VendorId") + .IsUnique(); + + b.ToTable("vendor_quotations", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotationLine", b => + { + b.Property("QuotationLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("QuotationLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LeadDays") + .HasColumnType("integer"); + + b.Property("QuotationId") + .HasColumnType("integer"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("QuotationLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("QuotationId"); + + b.ToTable("vendor_quotation_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Warehouse", b => + { + b.Property("WarehouseId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("WarehouseId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.HasKey("WarehouseId"); + + b.HasIndex("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("warehouses", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.WorkShift", b => + { + b.Property("WorkShiftId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("WorkShiftId")); + + b.Property("BreakMinutes") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EndTime") + .HasColumnType("interval"); + + b.Property("GraceMinutes") + .HasColumnType("integer"); + + b.Property("IsOvernight") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("OtMultiplier") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("StandardWorkingMinutes") + .HasColumnType("integer"); + + b.Property("StartTime") + .HasColumnType("interval"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WorkingDaysMask") + .HasColumnType("integer"); + + b.HasKey("WorkShiftId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_work_shifts", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceRecord", b => + { + b.HasOne("ERPCore.Domain.Entities.AttendanceUploadBatch", "AttendanceUploadBatch") + .WithMany() + .HasForeignKey("AttendanceUploadBatchId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.WorkShift", "WorkShift") + .WithMany() + .HasForeignKey("WorkShiftId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("AttendanceUploadBatch"); + + b.Navigation("Employee"); + + b.Navigation("WorkShift"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AuditLog", b => + { + b.HasOne("ERPCore.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Batch", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Bin", b => + { + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany("Bins") + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BranchConfig", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSale", b => + { + b.HasOne("ERPCore.Domain.Entities.BundleSaleTemplate", "BundleSaleTemplate") + .WithMany() + .HasForeignKey("BundleSaleTemplateId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "CashierUser") + .WithMany() + .HasForeignKey("CashierUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesDayEnd", "DayEnd") + .WithMany("BundleSales") + .HasForeignKey("DayEndId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BundleSaleTemplate"); + + b.Navigation("CashierUser"); + + b.Navigation("Customer"); + + b.Navigation("DayEnd"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleLine", b => + { + b.HasOne("ERPCore.Domain.Entities.BundleSale", "BundleSale") + .WithMany("Lines") + .HasForeignKey("BundleSaleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BundleSale"); + + b.Navigation("Item"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplateLine", b => + { + b.HasOne("ERPCore.Domain.Entities.BundleSaleTemplate", "BundleSaleTemplate") + .WithMany("Lines") + .HasForeignKey("BundleSaleTemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BundleSaleTemplate"); + + b.Navigation("Item"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Customer", b => + { + b.HasOne("ERPCore.Domain.Entities.Warehouse", "DefaultWarehouse") + .WithMany() + .HasForeignKey("DefaultWarehouseId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("DefaultWarehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Department", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Employee", "HeadEmployee") + .WithMany() + .HasForeignKey("HeadEmployeeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Department", "ParentDepartment") + .WithMany() + .HasForeignKey("ParentDepartmentId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Branch"); + + b.Navigation("HeadEmployee"); + + b.Navigation("ParentDepartment"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Employee", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Department", "Department") + .WithMany() + .HasForeignKey("DepartmentId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Designation", "Designation") + .WithMany() + .HasForeignKey("DesignationId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.EmploymentType", "EmploymentType") + .WithMany() + .HasForeignKey("EmploymentTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Employee", "ReportingManager") + .WithMany() + .HasForeignKey("ReportingManagerId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithOne() + .HasForeignKey("ERPCore.Domain.Entities.Employee", "UserId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.WorkShift", "WorkShift") + .WithMany() + .HasForeignKey("WorkShiftId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Department"); + + b.Navigation("Designation"); + + b.Navigation("EmploymentType"); + + b.Navigation("ReportingManager"); + + b.Navigation("User"); + + b.Navigation("WorkShift"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeBankDetail", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeDocument", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.HrDocumentType", "HrDocumentType") + .WithMany() + .HasForeignKey("HrDocumentTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("HrDocumentType"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeLoan", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructure", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructureLine", b => + { + b.HasOne("ERPCore.Domain.Entities.EmployeeSalaryStructure", "EmployeeSalaryStructure") + .WithMany("Lines") + .HasForeignKey("EmployeeSalaryStructureId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalaryComponent", "SalaryComponent") + .WithMany() + .HasForeignKey("SalaryComponentId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("EmployeeSalaryStructure"); + + b.Navigation("SalaryComponent"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Grn", 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.HasOne("ERPCore.Domain.Entities.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("PoId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.PurchaseInvoice", "PurchaseInvoice") + .WithMany() + .HasForeignKey("PurchaseInvoiceId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("PurchaseInvoice"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Vendor"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", "Batch") + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", "Bin") + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Grn", "Grn") + .WithMany("Lines") + .HasForeignKey("GrnId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PoLine", "PoLine") + .WithMany() + .HasForeignKey("PoLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Batch"); + + b.Navigation("Bin"); + + b.Navigation("Grn"); + + b.Navigation("Item"); + + b.Navigation("PoLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLineWarrantyNumber", b => + { + b.HasOne("ERPCore.Domain.Entities.GrnLine", "GrnLine") + .WithMany("WarrantyNumbers") + .HasForeignKey("GrnLineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GrnLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Item", b => + { + b.HasOne("ERPCore.Domain.Entities.Uom", "BaseUom") + .WithMany() + .HasForeignKey("BaseUomId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Brand", "Brand") + .WithMany() + .HasForeignKey("BrandId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Category", "Category") + .WithMany() + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "DefaultVendor") + .WithMany() + .HasForeignKey("DefaultVendorId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.SubCategory", "SubCategory") + .WithMany() + .HasForeignKey("SubCategoryId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("BaseUom"); + + b.Navigation("Brand"); + + b.Navigation("Category"); + + b.Navigation("DefaultVendor"); + + b.Navigation("SubCategory"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ItemReorder", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany("ReorderSettings") + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveBalance", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.LeaveType", "LeaveType") + .WithMany() + .HasForeignKey("LeaveTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("LeaveType"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveRequest", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.LeaveType", "LeaveType") + .WithMany() + .HasForeignKey("LeaveTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("LeaveType"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoanInstallment", b => + { + b.HasOne("ERPCore.Domain.Entities.EmployeeLoan", "EmployeeLoan") + .WithMany("Installments") + .HasForeignKey("EmployeeLoanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PayrollRun", "PayrollRun") + .WithMany() + .HasForeignKey("PayrollRunId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("EmployeeLoan"); + + b.Navigation("PayrollRun"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoginActivity", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfigModule", b => + { + b.HasOne("ERPCore.Domain.Entities.NotificationConfig", "NotificationConfig") + .WithMany("Modules") + .HasForeignKey("NotificationConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("NotificationConfig"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationRecipient", b => + { + b.HasOne("ERPCore.Domain.Entities.Notification", "Notification") + .WithMany("Recipients") + .HasForeignKey("NotificationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Notification"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PayrollRun", "PayrollRun") + .WithMany("Lines") + .HasForeignKey("PayrollRunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("PayrollRun"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLineComponent", b => + { + b.HasOne("ERPCore.Domain.Entities.PayrollLine", "PayrollLine") + .WithMany("Components") + .HasForeignKey("PayrollLineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalaryComponent", "SalaryComponent") + .WithMany() + .HasForeignKey("SalaryComponentId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("PayrollLine"); + + b.Navigation("SalaryComponent"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollRun", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Branch"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Payslip", b => + { + b.HasOne("ERPCore.Domain.Entities.PayrollLine", "PayrollLine") + .WithOne() + .HasForeignKey("ERPCore.Domain.Entities.Payslip", "PayrollLineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PayrollLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Permission", b => + { + b.HasOne("ERPCore.Domain.Entities.NavItem", "NavItem") + .WithMany() + .HasForeignKey("NavItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ERPCore.Domain.Entities.SubNavItem", "SubNavItem") + .WithMany() + .HasForeignKey("SubNavItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("NavItem"); + + b.Navigation("SubNavItem"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PoLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseOrder", "PurchaseOrder") + .WithMany("Lines") + .HasForeignKey("PoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductConfig", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b => + { + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "CancelReason") + .WithMany() + .HasForeignKey("CancelReasonCodeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Bin", "OutputBin") + .WithMany() + .HasForeignKey("OutputBinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") + .WithMany("Runs") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CancelReason"); + + b.Navigation("Creator"); + + b.Navigation("OutputBin"); + + b.Navigation("Template"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionTemplate", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoiceLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Grn", "Grn") + .WithMany() + .HasForeignKey("GrnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseInvoice", "PurchaseInvoice") + .WithMany("Lines") + .HasForeignKey("PurchaseInvoiceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Grn"); + + b.Navigation("PurchaseInvoice"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoicePayment", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseInvoice", "PurchaseInvoice") + .WithMany("Payments") + .HasForeignKey("PurchaseInvoiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("PurchaseInvoice"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") + .WithMany() + .HasForeignKey("RequisitionId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("Requisition"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturn", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ReasonCode") + .WithMany() + .HasForeignKey("ReasonCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("ReasonCode"); + + b.Navigation("Vendor"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturnLine", b => + { + b.HasOne("ERPCore.Domain.Entities.GrnLine", "GrnLine") + .WithMany() + .HasForeignKey("GrnLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseReturn", "Return") + .WithMany("Lines") + .HasForeignKey("ReturnId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GrnLine"); + + b.Navigation("Item"); + + b.Navigation("Return"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Requester") + .WithMany() + .HasForeignKey("RequestedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Requester"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RequisitionLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") + .WithMany("Lines") + .HasForeignKey("RequisitionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Requisition"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => + { + b.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") + .WithMany() + .HasForeignKey("RequisitionId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Requisition"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RfqLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Rfq", "Rfq") + .WithMany("Lines") + .HasForeignKey("RfqId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Rfq"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RolePermission", b => + { + b.HasOne("ERPCore.Domain.Entities.Permission", "Permission") + .WithMany() + .HasForeignKey("PermissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Role", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Permission"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunEdge", b => + { + b.HasOne("ERPCore.Domain.Entities.RunStage", "ChildRunStage") + .WithMany() + .HasForeignKey("ChildRunStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "ParentRunStage") + .WithMany() + .HasForeignKey("ParentRunStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ProductionRun", "Run") + .WithMany("Edges") + .HasForeignKey("RunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildRunStage"); + + b.Navigation("ParentRunStage"); + + b.Navigation("Run"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStage", b => + { + b.HasOne("ERPCore.Domain.Entities.ProductionRun", "Run") + .WithMany("Stages") + .HasForeignKey("RunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "TemplateStage") + .WithMany() + .HasForeignKey("TemplateStageId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Run"); + + b.Navigation("TemplateStage"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageEvent", b => + { + b.HasOne("ERPCore.Domain.Entities.ProductionRun", "Run") + .WithMany("Events") + .HasForeignKey("RunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "RunStage") + .WithMany("Events") + .HasForeignKey("RunStageId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Run"); + + b.Navigation("RunStage"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageInput", b => + { + b.HasOne("ERPCore.Domain.Entities.RunStageOutput", "FromRunOutput") + .WithMany() + .HasForeignKey("FromRunOutputId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "RunStage") + .WithMany("Inputs") + .HasForeignKey("RunStageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromRunOutput"); + + b.Navigation("Item"); + + b.Navigation("RunStage"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageOutput", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "RunStage") + .WithMany("Outputs") + .HasForeignKey("RunStageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ScrapReason") + .WithMany() + .HasForeignKey("ScrapReasonCodeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Uom", "Uom") + .WithMany() + .HasForeignKey("UomId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Item"); + + b.Navigation("RunStage"); + + b.Navigation("ScrapReason"); + + b.Navigation("Uom"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesDayEnd", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "CashierUser") + .WithMany() + .HasForeignKey("CashierUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "ClosedByUser") + .WithMany() + .HasForeignKey("ClosedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CashierUser"); + + b.Navigation("ClosedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoice", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatorUserId"); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("Customer"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoiceLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesInvoice", "SalesInvoice") + .WithMany("Lines") + .HasForeignKey("SalesInvoiceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SalesInvoice"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoicePayment", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesInvoice", "SalesInvoice") + .WithMany("Payments") + .HasForeignKey("SalesInvoiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("SalesInvoice"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturn", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ReasonCode") + .WithMany() + .HasForeignKey("ReasonCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("Customer"); + + b.Navigation("ReasonCode"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturnLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesReturn", "Return") + .WithMany("Lines") + .HasForeignKey("ReturnId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesInvoiceLine", "SalesInvoiceLine") + .WithMany() + .HasForeignKey("SalesInvoiceLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Item"); + + b.Navigation("Return"); + + b.Navigation("SalesInvoiceLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlip", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "CashierUser") + .WithMany() + .HasForeignKey("CashierUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesDayEnd", "DayEnd") + .WithMany("Slips") + .HasForeignKey("DayEndId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CashierUser"); + + b.Navigation("Customer"); + + b.Navigation("DayEnd"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlipLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesSlip", "SalesSlip") + .WithMany("Lines") + .HasForeignKey("SalesSlipId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SalesSlip"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Serial", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageEdge", b => + { + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "ChildStage") + .WithMany() + .HasForeignKey("ChildStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "ParentStage") + .WithMany() + .HasForeignKey("ParentStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") + .WithMany("Edges") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildStage"); + + b.Navigation("ParentStage"); + + b.Navigation("Template"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageInput", b => + { + b.HasOne("ERPCore.Domain.Entities.StageOutput", "FromOutput") + .WithMany() + .HasForeignKey("FromOutputId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "Stage") + .WithMany("Inputs") + .HasForeignKey("StageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromOutput"); + + b.Navigation("Item"); + + b.Navigation("Stage"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageOutput", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "Stage") + .WithMany("Outputs") + .HasForeignKey("StageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Uom", "Uom") + .WithMany() + .HasForeignKey("UomId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Item"); + + b.Navigation("Stage"); + + b.Navigation("Uom"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustment", 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.HasOne("ERPCore.Domain.Entities.ReasonCode", "ReasonCode") + .WithMany() + .HasForeignKey("ReasonCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("ReasonCode"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustmentLine", b => + { + b.HasOne("ERPCore.Domain.Entities.StockAdjustment", "Adjustment") + .WithMany("Lines") + .HasForeignKey("AdjustmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Batch", null) + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", null) + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Adjustment"); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCount", 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.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCountLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.StockCount", "Count") + .WithMany("Lines") + .HasForeignKey("CountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Count"); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLayer", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", "Batch") + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.GrnLine", "GrnLine") + .WithMany() + .HasForeignKey("GrnLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", "Serial") + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Batch"); + + b.Navigation("GrnLine"); + + b.Navigation("Item"); + + b.Navigation("Serial"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLedger", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", null) + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", null) + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", null) + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", null) + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransfer", 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.HasOne("ERPCore.Domain.Entities.Warehouse", "DestWarehouse") + .WithMany() + .HasForeignKey("DestWarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "SrcWarehouse") + .WithMany() + .HasForeignKey("SrcWarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("DestWarehouse"); + + b.Navigation("SrcWarehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransferLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", null) + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("DestBinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", null) + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("SrcBinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.StockTransfer", "Transfer") + .WithMany("Lines") + .HasForeignKey("TransferId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Transfer"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubCategory", b => + { + b.HasOne("ERPCore.Domain.Entities.Category", "Category") + .WithMany("SubCategories") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubNavItem", b => + { + b.HasOne("ERPCore.Domain.Entities.NavItem", "NavItem") + .WithMany("Children") + .HasForeignKey("NavItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("NavItem"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicketMessage", b => + { + b.HasOne("ERPCore.Domain.Entities.SupportTicket", "Ticket") + .WithMany("Messages") + .HasForeignKey("TicketId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ticket"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => + { + b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") + .WithMany("Stages") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Template"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.User", b => + { + b.HasOne("ERPCore.Domain.Entities.Role", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => + { + b.HasOne("ERPCore.Domain.Entities.Rfq", "Rfq") + .WithMany("Quotations") + .HasForeignKey("RfqId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Rfq"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotationLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.VendorQuotation", "Quotation") + .WithMany("Lines") + .HasForeignKey("QuotationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Quotation"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Warehouse", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSale", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplate", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Category", b => + { + b.Navigation("SubCategories"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeLoan", b => + { + b.Navigation("Installments"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructure", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Grn", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLine", b => + { + b.Navigation("WarrantyNumbers"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Item", b => + { + b.Navigation("ReorderSettings"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NavItem", b => + { + b.Navigation("Children"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Notification", b => + { + b.Navigation("Recipients"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => + { + b.Navigation("Modules"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => + { + b.Navigation("Components"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollRun", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b => + { + b.Navigation("Edges"); + + b.Navigation("Events"); + + b.Navigation("Stages"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionTemplate", b => + { + b.Navigation("Edges"); + + b.Navigation("Runs"); + + b.Navigation("Stages"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", b => + { + b.Navigation("Lines"); + + b.Navigation("Payments"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturn", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => + { + b.Navigation("Lines"); + + b.Navigation("Quotations"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStage", b => + { + b.Navigation("Events"); + + b.Navigation("Inputs"); + + b.Navigation("Outputs"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesDayEnd", b => + { + b.Navigation("BundleSales"); + + b.Navigation("Slips"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoice", b => + { + b.Navigation("Lines"); + + b.Navigation("Payments"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturn", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlip", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustment", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCount", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransfer", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicket", b => + { + b.Navigation("Messages"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => + { + b.Navigation("Inputs"); + + b.Navigation("Outputs"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Warehouse", b => + { + b.Navigation("Bins"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Backend/ERPCore/Migrations/20260915044627_AddSupportTickets.cs b/Backend/ERPCore/Migrations/20260915044627_AddSupportTickets.cs new file mode 100644 index 0000000..bd472e6 --- /dev/null +++ b/Backend/ERPCore/Migrations/20260915044627_AddSupportTickets.cs @@ -0,0 +1,81 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace ERPCore.Migrations +{ + /// + public partial class AddSupportTickets : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "support_tickets", + columns: table => new + { + TicketId = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + Subject = table.Column(type: "character varying(200)", maxLength: 200, nullable: false), + Status = table.Column(type: "character varying(20)", maxLength: 20, nullable: false), + CreatedByUserId = table.Column(type: "integer", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + UpdatedAt = table.Column(type: "timestamp with time zone", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_support_tickets", x => x.TicketId); + }); + + migrationBuilder.CreateTable( + name: "support_ticket_messages", + columns: table => new + { + MessageId = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + TicketId = table.Column(type: "integer", nullable: false), + SenderUserId = table.Column(type: "integer", nullable: false), + IsFromAdmin = table.Column(type: "boolean", nullable: false), + Message = table.Column(type: "character varying(2000)", maxLength: 2000, nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_support_ticket_messages", x => x.MessageId); + table.ForeignKey( + name: "FK_support_ticket_messages_support_tickets_TicketId", + column: x => x.TicketId, + principalTable: "support_tickets", + principalColumn: "TicketId", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_support_ticket_messages_TicketId_CreatedAt", + table: "support_ticket_messages", + columns: new[] { "TicketId", "CreatedAt" }); + + migrationBuilder.CreateIndex( + name: "IX_support_tickets_CreatedByUserId", + table: "support_tickets", + column: "CreatedByUserId"); + + migrationBuilder.CreateIndex( + name: "IX_support_tickets_Status", + table: "support_tickets", + column: "Status"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "support_ticket_messages"); + + migrationBuilder.DropTable( + name: "support_tickets"); + } + } +} diff --git a/Backend/ERPCore/Migrations/20260915065226_RestyleSupportTicketLikeEmployee.Designer.cs b/Backend/ERPCore/Migrations/20260915065226_RestyleSupportTicketLikeEmployee.Designer.cs new file mode 100644 index 0000000..0b68bf4 --- /dev/null +++ b/Backend/ERPCore/Migrations/20260915065226_RestyleSupportTicketLikeEmployee.Designer.cs @@ -0,0 +1,8417 @@ +// +using System; +using ERPCore.Infra.Persistence; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace ERPCore.Migrations +{ + [DbContext(typeof(ErpDbContext))] + [Migration("20260915065226_RestyleSupportTicketLikeEmployee")] + partial class RestyleSupportTicketLikeEmployee + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.9") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceRecord", b => + { + b.Property("AttendanceRecordId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AttendanceRecordId")); + + b.Property("AttendanceDate") + .HasColumnType("timestamp with time zone"); + + b.Property("AttendanceStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("AttendanceUploadBatchId") + .HasColumnType("integer"); + + b.Property("CheckIn") + .HasColumnType("interval"); + + b.Property("CheckOut") + .HasColumnType("interval"); + + b.Property("DuplicateOfAttendanceRecordId") + .HasColumnType("integer"); + + b.Property("EarlyLeaveMinutes") + .HasColumnType("integer"); + + b.Property("EditedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EditedBy") + .HasColumnType("integer"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("IsManualOverride") + .HasColumnType("boolean"); + + b.Property("LateMinutes") + .HasColumnType("integer"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("OvertimeMinutes") + .HasColumnType("integer"); + + b.Property("RowValidationStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("WorkShiftId") + .HasColumnType("integer"); + + b.Property("WorkingMinutes") + .HasColumnType("integer"); + + b.HasKey("AttendanceRecordId"); + + b.HasIndex("AttendanceUploadBatchId"); + + b.HasIndex("WorkShiftId"); + + b.HasIndex("EmployeeId", "AttendanceDate"); + + b.ToTable("hr_attendance_records", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceUploadBatch", b => + { + b.Property("AttendanceUploadBatchId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AttendanceUploadBatchId")); + + b.Property("ConfirmedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ConfirmedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("OriginalFileName") + .HasMaxLength(260) + .HasColumnType("character varying(260)"); + + b.Property("PeriodEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("PeriodStart") + .HasColumnType("timestamp with time zone"); + + b.Property("RowCountDuplicate") + .HasColumnType("integer"); + + b.Property("RowCountError") + .HasColumnType("integer"); + + b.Property("RowCountTotal") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SourceType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UploadedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UploadedBy") + .HasColumnType("integer"); + + b.HasKey("AttendanceUploadBatchId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("PeriodStart", "PeriodEnd"); + + b.ToTable("hr_attendance_upload_batches", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AuditLog", b => + { + b.Property("AuditId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AuditId")); + + b.Property("Action") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("ChangeSet") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EntityId") + .HasColumnType("integer"); + + b.Property("EntityType") + .IsRequired() + .HasMaxLength(80) + .HasColumnType("character varying(80)"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("AuditId"); + + b.HasIndex("CreatedAt"); + + b.HasIndex("UserId"); + + b.HasIndex("EntityType", "EntityId"); + + b.ToTable("audit_logs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Batch", b => + { + b.Property("BatchId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BatchId")); + + b.Property("BatchNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ExpiryDate") + .HasColumnType("date"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.HasKey("BatchId"); + + b.HasIndex("ItemId", "BatchNo") + .IsUnique(); + + b.ToTable("batches", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Bin", b => + { + b.Property("BinId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BinId")); + + b.Property("BinType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BinId"); + + b.HasIndex("WarehouseId", "Code") + .IsUnique(); + + b.ToTable("bins", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Branch", b => + { + b.Property("BranchId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BranchId")); + + b.Property("Address") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("PhoneNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_branches", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BranchConfig", b => + { + b.Property("ConfigId") + .HasColumnType("integer"); + + b.Property("BranchingEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.HasKey("ConfigId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("branch_config", null, t => + { + t.HasCheckConstraint("ck_branch_config_singleton", "\"ConfigId\" = 1"); + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Brand", b => + { + b.Property("BrandId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BrandId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("BrandId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("brands", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSale", b => + { + b.Property("BundleSaleId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleId")); + + b.Property("BundleCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BundleDate") + .HasColumnType("timestamp with time zone"); + + b.Property("BundleName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("BundleNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BundlePrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BundleSaleTemplateId") + .HasColumnType("integer"); + + b.Property("CashierUserId") + .HasColumnType("integer"); + + b.Property("ComponentSubtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("CustomerSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DayEndId") + .HasColumnType("integer"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("MarginAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BundleSaleId"); + + b.HasIndex("BundleNo") + .IsUnique(); + + b.HasIndex("BundleSaleTemplateId"); + + b.HasIndex("CashierUserId"); + + b.HasIndex("CustomerId"); + + b.HasIndex("DayEndId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("bundle_sales", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleLine", b => + { + b.Property("BundleSaleLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleLineId")); + + b.Property("BundleSaleId") + .HasColumnType("integer"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("IncludeInBundle") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("IsComponent") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ParentLineId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BundleSaleLineId"); + + b.HasIndex("BundleSaleId"); + + b.HasIndex("ItemId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("bundle_sale_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplate", b => + { + b.Property("BundleSaleTemplateId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleTemplateId")); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TemplateCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("TemplateName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("BundleSaleTemplateId"); + + b.HasIndex("TemplateCode") + .IsUnique(); + + b.ToTable("bundle_sale_templates", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplateLine", b => + { + b.Property("BundleSaleTemplateLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleTemplateLineId")); + + b.Property("BundleSaleTemplateId") + .HasColumnType("integer"); + + b.Property("IncludeInBundle") + .HasColumnType("boolean"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SortOrder") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BundleSaleTemplateLineId"); + + b.HasIndex("BundleSaleTemplateId"); + + b.HasIndex("ItemId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("bundle_sale_template_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Category", b => + { + b.Property("CategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CategoryId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("CategoryId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("categories", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Customer", b => + { + b.Property("CustomerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CustomerId")); + + b.Property("AddressLine1") + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("AddressLine2") + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("City") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Country") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreditDays") + .HasColumnType("integer"); + + b.Property("CreditLimit") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CustomerCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CustomerType") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("B2C"); + + b.Property("DefaultWarehouseId") + .HasColumnType("integer"); + + b.Property("DisplayName") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Email") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Phone") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TaxRegistrationNo") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("CustomerId"); + + b.HasIndex("CustomerCode") + .IsUnique(); + + b.HasIndex("CustomerType"); + + b.HasIndex("DefaultWarehouseId"); + + b.HasIndex("Status"); + + b.ToTable("customers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Department", b => + { + b.Property("DepartmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("DepartmentId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("HeadEmployeeId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("ParentDepartmentId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("DepartmentId"); + + b.HasIndex("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("HeadEmployeeId"); + + b.HasIndex("ParentDepartmentId"); + + b.HasIndex("Status"); + + b.ToTable("hr_departments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Designation", b => + { + b.Property("DesignationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("DesignationId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("DesignationId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_designations", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Employee", b => + { + b.Property("EmployeeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeId")); + + b.Property("AddressLine1") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("AddressLine2") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("City") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ConfirmationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Country") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DateOfBirth") + .HasColumnType("timestamp with time zone"); + + b.Property("DepartmentId") + .HasColumnType("integer"); + + b.Property("DesignationId") + .HasColumnType("integer"); + + b.Property("Email") + .HasMaxLength(320) + .HasColumnType("character varying(320)"); + + b.Property("EmergencyContactName") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("EmergencyContactPhone") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmergencyContactRelationship") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("EmployeeCode") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmploymentTypeId") + .HasColumnType("integer"); + + b.Property("EpfNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EtfNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Gender") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("HireDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LastWorkingDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Nationality") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Nic") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PersonalMobile") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PostalCode") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ProfilePhotoPath") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("ReportingManagerId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TaxIdentificationNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.Property("WorkShiftId") + .HasColumnType("integer"); + + b.HasKey("EmployeeId"); + + b.HasIndex("BranchId"); + + b.HasIndex("DepartmentId"); + + b.HasIndex("DesignationId"); + + b.HasIndex("Email"); + + b.HasIndex("EmployeeCode") + .IsUnique(); + + b.HasIndex("EmploymentTypeId"); + + b.HasIndex("ReportingManagerId"); + + b.HasIndex("Status"); + + b.HasIndex("UserId") + .IsUnique(); + + b.HasIndex("WorkShiftId"); + + b.ToTable("hr_employees", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeBankDetail", b => + { + b.Property("EmployeeBankDetailId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeBankDetailId")); + + b.Property("AccountHolderName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("AccountNumber") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BankName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("BranchName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("IsPrimary") + .HasColumnType("boolean"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("SwiftCode") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("EmployeeBankDetailId"); + + b.HasIndex("EmployeeId"); + + b.ToTable("hr_employee_bank_details", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeDocument", b => + { + b.Property("EmployeeDocumentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeDocumentId")); + + b.Property("ContentType") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("ExpiryDate") + .HasColumnType("timestamp with time zone"); + + b.Property("HrDocumentTypeId") + .HasColumnType("integer"); + + b.Property("IssueDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("OriginalFileName") + .IsRequired() + .HasMaxLength(260) + .HasColumnType("character varying(260)"); + + b.Property("RelativePath") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SizeBytes") + .HasColumnType("bigint"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("StoredFileName") + .IsRequired() + .HasMaxLength(260) + .HasColumnType("character varying(260)"); + + b.Property("UploadedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UploadedBy") + .HasColumnType("integer"); + + b.Property("VerifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VerifiedBy") + .HasColumnType("integer"); + + b.HasKey("EmployeeDocumentId"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("ExpiryDate"); + + b.HasIndex("HrDocumentTypeId"); + + b.ToTable("hr_employee_documents", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeLoan", b => + { + b.Property("EmployeeLoanId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeLoanId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("InstallmentAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("InterestRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("LoanKind") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("NumberOfInstallments") + .HasColumnType("integer"); + + b.Property("OutstandingBalance") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("PrincipalAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("StartMonth") + .HasColumnType("integer"); + + b.Property("StartYear") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("EmployeeLoanId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("EmployeeId"); + + b.HasIndex("Status"); + + b.ToTable("hr_employee_loans", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructure", b => + { + b.Property("EmployeeSalaryStructureId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeSalaryStructureId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("BasicSalary") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("Currency") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("character varying(3)"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveTo") + .HasColumnType("timestamp with time zone"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("EmployeeSalaryStructureId"); + + b.HasIndex("EmployeeId", "EffectiveTo"); + + b.ToTable("hr_employee_salary_structures", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructureLine", b => + { + b.Property("EmployeeSalaryStructureLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeSalaryStructureLineId")); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("EmployeeSalaryStructureId") + .HasColumnType("integer"); + + b.Property("SalaryComponentId") + .HasColumnType("integer"); + + b.HasKey("EmployeeSalaryStructureLineId"); + + b.HasIndex("EmployeeSalaryStructureId"); + + b.HasIndex("SalaryComponentId"); + + b.ToTable("hr_employee_salary_structure_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmploymentType", b => + { + b.Property("EmploymentTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmploymentTypeId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("EmploymentTypeId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_employment_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Grn", b => + { + b.Property("GrnId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("GrnId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PoId") + .HasColumnType("integer"); + + b.Property("PostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PurchaseInvoiceId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("GrnId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("PoId"); + + b.HasIndex("PurchaseInvoiceId"); + + b.HasIndex("Status"); + + b.HasIndex("VendorId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("grns", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLine", b => + { + b.Property("GrnLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("GrnLineId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("DiscountPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("GrnId") + .HasColumnType("integer"); + + b.Property("HoldStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("NetUnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("PoLineId") + .HasColumnType("integer"); + + b.Property("PoUnitPrice") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReceivedValue") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("VatAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("VatPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.HasKey("GrnLineId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("GrnId"); + + b.HasIndex("ItemId"); + + b.HasIndex("PoLineId"); + + b.ToTable("grn_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLineWarrantyNumber", b => + { + b.Property("GrnLineWarrantyNumberId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("GrnLineWarrantyNumberId")); + + b.Property("GrnLineId") + .HasColumnType("integer"); + + b.Property("WarrantyNo") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("WarrantyPeriodMonths") + .HasColumnType("integer"); + + b.HasKey("GrnLineWarrantyNumberId"); + + b.HasIndex("GrnLineId", "WarrantyNo") + .IsUnique(); + + b.ToTable("grn_line_warranty_numbers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.HrDocumentType", b => + { + b.Property("HrDocumentTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("HrDocumentTypeId")); + + b.Property("Category") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpiryTracked") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RequiredAtOnboarding") + .HasColumnType("boolean"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("HrDocumentTypeId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_document_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Item", b => + { + b.Property("ItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ItemId")); + + b.Property("BaseUomId") + .HasColumnType("integer"); + + b.Property("BrandId") + .HasColumnType("integer"); + + b.Property("CategoryId") + .HasColumnType("integer"); + + b.Property("ContentBaseQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ContentBaseUnit") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ContentQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ContentUnit") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DefaultVendorId") + .HasColumnType("integer"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SellingFlatPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SellingMaxPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SellingMinPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Sku") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("StockNature") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("SubCategoryId") + .HasColumnType("integer"); + + b.Property("TaxClass") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("TrackingMode") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Warranty") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("NonWarranty"); + + b.Property("WarrantyPeriodMonths") + .HasColumnType("integer"); + + b.HasKey("ItemId"); + + b.HasIndex("BaseUomId"); + + b.HasIndex("BrandId"); + + b.HasIndex("CategoryId"); + + b.HasIndex("DefaultVendorId"); + + b.HasIndex("Sku") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("SubCategoryId"); + + b.ToTable("items", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ItemReorder", b => + { + b.Property("ReorderId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReorderId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("ReorderPoint") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReorderQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("ReorderId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("ItemId", "WarehouseId") + .IsUnique(); + + b.ToTable("item_reorders", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ItemType", b => + { + b.Property("ItemTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ItemTypeId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsMeasurable") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("ItemTypeId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("item_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.JournalEntryStub", b => + { + b.Property("JournalId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("JournalId")); + + b.Property("Amount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CreditAccount") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("DebitAccount") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("SourceDocId") + .HasColumnType("integer"); + + b.Property("SourceDocType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.HasKey("JournalId"); + + b.HasIndex("SourceDocType", "SourceDocId"); + + b.ToTable("journal_entry_stubs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveBalance", b => + { + b.Property("LeaveBalanceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LeaveBalanceId")); + + b.Property("AdjustmentDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("CarriedForwardDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("EntitledDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("LeaveTypeId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("TakenDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Year") + .HasColumnType("integer"); + + b.HasKey("LeaveBalanceId"); + + b.HasIndex("LeaveTypeId"); + + b.HasIndex("EmployeeId", "LeaveTypeId", "Year") + .IsUnique(); + + b.ToTable("hr_leave_balances", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveRequest", b => + { + b.Property("LeaveRequestId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LeaveRequestId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DaysCount") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("EndDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LeaveTypeId") + .HasColumnType("integer"); + + b.Property("Reason") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("RejectionReason") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("StartDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("LeaveRequestId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("EmployeeId"); + + b.HasIndex("LeaveTypeId"); + + b.HasIndex("Status"); + + b.HasIndex("StartDate", "EndDate"); + + b.ToTable("hr_leave_requests", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveType", b => + { + b.Property("LeaveTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LeaveTypeId")); + + b.Property("AccrualPerYear") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("CarryForwardAllowed") + .HasColumnType("boolean"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CountsAsNoPay") + .HasColumnType("boolean"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsPaid") + .HasColumnType("boolean"); + + b.Property("MaxCarryForwardDays") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RequiresApproval") + .HasColumnType("boolean"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("LeaveTypeId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_leave_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoanInstallment", b => + { + b.Property("LoanInstallmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LoanInstallmentId")); + + b.Property("DueMonth") + .HasColumnType("integer"); + + b.Property("DueYear") + .HasColumnType("integer"); + + b.Property("EmployeeLoanId") + .HasColumnType("integer"); + + b.Property("InstallmentNumber") + .HasColumnType("integer"); + + b.Property("PaidAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("PayrollRunId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("ScheduledAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("LoanInstallmentId"); + + b.HasIndex("EmployeeLoanId"); + + b.HasIndex("PayrollRunId"); + + b.HasIndex("DueYear", "DueMonth"); + + b.ToTable("hr_loan_installments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoginActivity", b => + { + b.Property("LoginActivityId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LoginActivityId")); + + b.Property("DeviceLabel") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("IpAddress") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("LoginAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserAgent") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("LoginActivityId"); + + b.HasIndex("UserId", "LoginAt"); + + b.ToTable("login_activities", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NavItem", b => + { + b.Property("NavItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NavItemId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Href") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Icon") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.HasKey("NavItemId"); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("nav_items", (string)null); + + b.HasData( + new + { + NavItemId = 1, + Code = "dashboard", + Href = "/dashboard", + Label = "Dashboard", + SortOrder = 1, + Status = "Active" + }, + new + { + NavItemId = 2, + Code = "products", + Href = "/dashboard/products", + Label = "Products", + SortOrder = 2, + Status = "Active" + }, + new + { + NavItemId = 4, + Code = "procurement", + Href = "/dashboard/procurement", + Label = "Procurement", + SortOrder = 4, + Status = "Active" + }, + new + { + NavItemId = 5, + Code = "receiving", + Href = "/dashboard/receiving/grn", + Label = "Receiving", + SortOrder = 5, + Status = "Active" + }, + new + { + NavItemId = 6, + Code = "stock", + Href = "/dashboard/stock", + Label = "Stock", + SortOrder = 6, + Status = "Active" + }, + new + { + NavItemId = 7, + Code = "warehouses", + Href = "/dashboard/warehouse", + Label = "Warehouses", + SortOrder = 7, + Status = "Active" + }, + new + { + NavItemId = 8, + Code = "orders", + Href = "/dashboard/orders", + Label = "Orders", + SortOrder = 8, + Status = "Active" + }, + new + { + NavItemId = 9, + Code = "settings", + Href = "/dashboard/settings", + Label = "Settings", + SortOrder = 9, + Status = "Active" + }, + new + { + NavItemId = 10, + Code = "help", + Href = "/dashboard/help", + Label = "Help", + SortOrder = 10, + Status = "Active" + }, + new + { + NavItemId = 11, + Code = "ledgers", + Href = "/dashboard/ledgers", + Label = "Ledgers", + SortOrder = 11, + Status = "Active" + }, + new + { + NavItemId = 12, + Code = "accounts", + Href = "/dashboard/accounts", + Label = "Accounts", + SortOrder = 12, + Status = "Active" + }, + new + { + NavItemId = 13, + Code = "sales", + Href = "/dashboard/sales", + Label = "Sales", + SortOrder = 13, + Status = "Active" + }, + new + { + NavItemId = 14, + Code = "production", + Href = "/dashboard/production", + Label = "Production", + SortOrder = 14, + Status = "Active" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Notification", b => + { + b.Property("NotificationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NotificationId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("ModuleKey") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("RelatedEntityId") + .HasColumnType("integer"); + + b.Property("RelatedEntityType") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.HasKey("NotificationId"); + + b.HasIndex("CreatedAt"); + + b.ToTable("notifications", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => + { + b.Property("NotificationConfigId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.HasKey("NotificationConfigId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("notification_config", null, t => + { + t.HasCheckConstraint("ck_notification_config_singleton", "\"NotificationConfigId\" = 1"); + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfigModule", b => + { + b.Property("NotificationConfigModuleId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NotificationConfigModuleId")); + + b.Property("EmailEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("InAppEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("ModuleKey") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("NotificationConfigId") + .HasColumnType("integer"); + + b.Property("SmsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.HasKey("NotificationConfigModuleId"); + + b.HasIndex("ModuleKey") + .IsUnique(); + + b.HasIndex("NotificationConfigId"); + + b.ToTable("notification_config_modules", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationRecipient", b => + { + b.Property("NotificationRecipientId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NotificationRecipientId")); + + b.Property("IsRead") + .HasColumnType("boolean"); + + b.Property("NotificationId") + .HasColumnType("integer"); + + b.Property("ReadAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("NotificationRecipientId"); + + b.HasIndex("NotificationId"); + + b.HasIndex("UserId", "IsRead", "NotificationId"); + + b.ToTable("notification_recipients", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NumberSequence", b => + { + b.Property("SequenceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SequenceId")); + + b.Property("DocType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("doc_type"); + + b.Property("LastNumber") + .HasColumnType("integer") + .HasColumnName("last_number"); + + b.Property("Year") + .HasColumnType("integer") + .HasColumnName("year"); + + b.HasKey("SequenceId"); + + b.HasIndex("DocType", "Year") + .IsUnique(); + + b.ToTable("number_sequences", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => + { + b.Property("PayrollLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollLineId")); + + b.Property("AbsentDays") + .HasColumnType("integer"); + + b.Property("BasicSalary") + .HasColumnType("numeric(18,2)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("EpfEmployeeAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("EpfEmployerAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("EtfEmployerAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("GrossSalary") + .HasColumnType("numeric(18,2)"); + + b.Property("LateDeductionAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("LateMinutesTotal") + .HasColumnType("integer"); + + b.Property("LeaveDays") + .HasColumnType("integer"); + + b.Property("LoanDeductionAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("NetSalary") + .HasColumnType("numeric(18,2)"); + + b.Property("NoPayAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("OtMinutesTotal") + .HasColumnType("integer"); + + b.Property("OtherDeductionsAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("OvertimeAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("PayrollRunId") + .HasColumnType("integer"); + + b.Property("PresentDays") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("TaxAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("TotalAllowances") + .HasColumnType("numeric(18,2)"); + + b.Property("WorkingDays") + .HasColumnType("integer"); + + b.HasKey("PayrollLineId"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("PayrollRunId", "EmployeeId") + .IsUnique(); + + b.ToTable("hr_payroll_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLineComponent", b => + { + b.Property("PayrollLineComponentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollLineComponentId")); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("ComponentCategory") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("PayrollLineId") + .HasColumnType("integer"); + + b.Property("SalaryComponentId") + .HasColumnType("integer"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.HasKey("PayrollLineComponentId"); + + b.HasIndex("PayrollLineId"); + + b.HasIndex("SalaryComponentId"); + + b.ToTable("hr_payroll_line_components", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollRun", b => + { + b.Property("PayrollRunId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollRunId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GeneratedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GeneratedBy") + .HasColumnType("integer"); + + b.Property("LockedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("LockedBy") + .HasColumnType("integer"); + + b.Property("PeriodMonth") + .HasColumnType("integer"); + + b.Property("PeriodYear") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UnlockReason") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("UnlockedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UnlockedBy") + .HasColumnType("integer"); + + b.HasKey("PayrollRunId"); + + b.HasIndex("BranchId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("PeriodYear", "PeriodMonth", "BranchId"); + + b.ToTable("hr_payroll_runs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollStatutorySetting", b => + { + b.Property("PayrollStatutorySettingId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollStatutorySettingId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveTo") + .HasColumnType("timestamp with time zone"); + + b.Property("EpfEmployeeRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("EpfEmployerRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("EtfEmployerRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("OtMultiplierDefault") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.HasKey("PayrollStatutorySettingId"); + + b.HasIndex("EffectiveFrom"); + + b.ToTable("hr_payroll_statutory_settings", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Payslip", b => + { + b.Property("PayslipId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayslipId")); + + b.Property("GeneratedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PayrollLineId") + .HasColumnType("integer"); + + b.Property("ReleasedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReleasedBy") + .HasColumnType("integer"); + + b.HasKey("PayslipId"); + + b.HasIndex("PayrollLineId") + .IsUnique(); + + b.ToTable("hr_payslips", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Permission", b => + { + b.Property("PermissionId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PermissionId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(80) + .HasColumnType("character varying(80)"); + + b.Property("NavItemId") + .HasColumnType("integer"); + + b.Property("SubNavItemId") + .HasColumnType("integer"); + + b.HasKey("PermissionId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("NavItemId"); + + b.HasIndex("SubNavItemId"); + + b.ToTable("permissions", (string)null); + + b.HasData( + new + { + PermissionId = 1, + Code = "NAV:dashboard", + NavItemId = 1 + }, + new + { + PermissionId = 2, + Code = "NAV:products", + NavItemId = 2 + }, + new + { + PermissionId = 3, + Code = "NAV:procurement.vendors", + SubNavItemId = 30 + }, + new + { + PermissionId = 4, + Code = "NAV:procurement", + NavItemId = 4 + }, + new + { + PermissionId = 5, + Code = "NAV:receiving", + NavItemId = 5 + }, + new + { + PermissionId = 6, + Code = "NAV:stock", + NavItemId = 6 + }, + new + { + PermissionId = 7, + Code = "NAV:warehouses", + NavItemId = 7 + }, + new + { + PermissionId = 8, + Code = "NAV:orders", + NavItemId = 8 + }, + new + { + PermissionId = 9, + Code = "NAV:settings", + NavItemId = 9 + }, + new + { + PermissionId = 10, + Code = "NAV:help", + NavItemId = 10 + }, + new + { + PermissionId = 11, + Code = "NAV:products.item", + SubNavItemId = 1 + }, + new + { + PermissionId = 12, + Code = "NAV:products.category", + SubNavItemId = 2 + }, + new + { + PermissionId = 13, + Code = "NAV:products.brand", + SubNavItemId = 3 + }, + new + { + PermissionId = 14, + Code = "NAV:products.item-type", + SubNavItemId = 4 + }, + new + { + PermissionId = 15, + Code = "NAV:products.uom", + SubNavItemId = 5 + }, + new + { + PermissionId = 16, + Code = "NAV:products.configuration", + SubNavItemId = 6 + }, + new + { + PermissionId = 17, + Code = "NAV:settings.roles", + SubNavItemId = 7 + }, + new + { + PermissionId = 18, + Code = "NAV:settings.users", + SubNavItemId = 8 + }, + new + { + PermissionId = 28, + Code = "NAV:procurement.requisitions", + SubNavItemId = 17 + }, + new + { + PermissionId = 29, + Code = "NAV:procurement.rfqs", + SubNavItemId = 18 + }, + new + { + PermissionId = 30, + Code = "NAV:procurement.purchase-orders", + SubNavItemId = 19 + }, + new + { + PermissionId = 31, + Code = "NAV:procurement.purchase-returns", + SubNavItemId = 20 + }, + new + { + PermissionId = 19, + Code = "NAV:ledgers", + NavItemId = 11 + }, + new + { + PermissionId = 20, + Code = "NAV:ledgers.trial-balance", + SubNavItemId = 9 + }, + new + { + PermissionId = 21, + Code = "NAV:ledgers.balance-sheet", + SubNavItemId = 10 + }, + new + { + PermissionId = 22, + Code = "NAV:ledgers.general-ledger", + SubNavItemId = 11 + }, + new + { + PermissionId = 23, + Code = "NAV:ledgers.profit-and-loss", + SubNavItemId = 12 + }, + new + { + PermissionId = 24, + Code = "NAV:ledgers.cash-flow", + SubNavItemId = 13 + }, + new + { + PermissionId = 25, + Code = "NAV:ledgers.budget-vs-actual", + SubNavItemId = 14 + }, + new + { + PermissionId = 27, + Code = "NAV:ledgers.tax-report", + SubNavItemId = 16 + }, + new + { + PermissionId = 26, + Code = "NAV:accounts.bank-accounts", + SubNavItemId = 15 + }, + new + { + PermissionId = 32, + Code = "NAV:accounts", + NavItemId = 12 + }, + new + { + PermissionId = 33, + Code = "NAV:accounts.cheque-books", + SubNavItemId = 21 + }, + new + { + PermissionId = 34, + Code = "NAV:accounts.received-cheques", + SubNavItemId = 22 + }, + new + { + PermissionId = 35, + Code = "NAV:production", + NavItemId = 14 + }, + new + { + PermissionId = 36, + Code = "NAV:production.templates", + SubNavItemId = 27 + }, + new + { + PermissionId = 37, + Code = "NAV:production.runs", + SubNavItemId = 25 + }, + new + { + PermissionId = 38, + Code = "NAV:production.produced", + SubNavItemId = 26 + }, + new + { + PermissionId = 39, + Code = "NAV:procurement.purchase-invoices", + SubNavItemId = 28 + }, + new + { + PermissionId = 40, + Code = "NAV:settings.branches", + SubNavItemId = 29 + }, + new + { + PermissionId = 41, + Code = "NAV:stock.ledger", + SubNavItemId = 31 + }, + new + { + PermissionId = 42, + Code = "NAV:stock.enquiry", + SubNavItemId = 32 + }, + new + { + PermissionId = 43, + Code = "NAV:stock.valuation", + SubNavItemId = 33 + }, + new + { + PermissionId = 44, + Code = "NAV:stock.transfers", + SubNavItemId = 34 + }, + new + { + PermissionId = 45, + Code = "NAV:stock.adjustments", + SubNavItemId = 35 + }, + new + { + PermissionId = 46, + Code = "NAV:stock.counts", + SubNavItemId = 36 + }, + new + { + PermissionId = 47, + Code = "NAV:stock.reorder-alerts", + SubNavItemId = 37 + }, + new + { + PermissionId = 48, + Code = "NAV:stock.wastage", + SubNavItemId = 38 + }, + new + { + PermissionId = 49, + Code = "NAV:sales.bundle-templates", + SubNavItemId = 23 + }, + new + { + PermissionId = 50, + Code = "NAV:sales.invoices", + SubNavItemId = 40 + }, + new + { + PermissionId = 51, + Code = "NAV:sales.free-issues", + SubNavItemId = 41 + }, + new + { + PermissionId = 52, + Code = "NAV:sales.day-end", + SubNavItemId = 42 + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PoLine", b => + { + b.Property("PoLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PoLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("PoId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyReceived") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Tax") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("PoLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("PoId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("po_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductConfig", b => + { + b.Property("ConfigId") + .HasColumnType("integer"); + + b.Property("BatchListsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("BrandsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("ItemTypesEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SellingPricesEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("SerialNumbersEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("SubcategoriesEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.Property("WarrantyPeriodsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.HasKey("ConfigId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("product_config", null, t => + { + t.HasCheckConstraint("ck_product_config_singleton", "\"ConfigId\" = 1"); + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b => + { + b.Property("RunId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunId")); + + b.Property("CancelReasonCodeId") + .HasColumnType("integer"); + + b.Property("CompletedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("OutputBinId") + .HasColumnType("integer"); + + b.Property("ReworkCount") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("ScaleFactor") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("TargetQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TemplateId") + .HasColumnType("integer"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("RunId"); + + b.HasIndex("CancelReasonCodeId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("OutputBinId"); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("TemplateId", "Status"); + + b.ToTable("production_runs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionTemplate", b => + { + b.Property("TemplateId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TemplateId")); + + b.Property("Annotations") + .HasColumnType("jsonb"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("TemplateId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("CreatedBy"); + + b.HasIndex("Status"); + + b.ToTable("production_templates", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", b => + { + b.Property("PurchaseInvoiceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PurchaseInvoiceId")); + + b.Property("BalanceAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VatTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.Property("VendorInvoiceDate") + .HasColumnType("timestamp with time zone"); + + b.Property("VendorInvoiceNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("VendorSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("VendorSnapshotTaxNo") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("PurchaseInvoiceId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("VendorId"); + + b.HasIndex("VendorId", "VendorInvoiceNo"); + + b.ToTable("purchase_invoices", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoiceLine", b => + { + b.Property("PurchaseInvoiceLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PurchaseInvoiceLineId")); + + b.Property("GrnId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PurchaseInvoiceId") + .HasColumnType("integer"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("VatTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("PurchaseInvoiceLineId"); + + b.HasIndex("GrnId") + .IsUnique(); + + b.HasIndex("PurchaseInvoiceId"); + + b.ToTable("purchase_invoice_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoicePayment", b => + { + b.Property("PurchaseInvoicePaymentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PurchaseInvoicePaymentId")); + + b.Property("Amount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BankAccountName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("GlBankAccountId") + .HasColumnType("bigint"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PaymentDate") + .HasColumnType("timestamp with time zone"); + + b.Property("PurchaseInvoiceId") + .HasColumnType("integer"); + + b.Property("Reference") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("PurchaseInvoicePaymentId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("PurchaseInvoiceId"); + + b.ToTable("purchase_invoice_payments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => + { + b.Property("PoId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PoId")); + + b.Property("ApprovalRequired") + .HasColumnType("boolean"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RequisitionId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.HasKey("PoId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("RequisitionId"); + + b.HasIndex("Status"); + + b.HasIndex("VendorId"); + + b.ToTable("purchase_orders", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturn", b => + { + b.Property("ReturnId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReasonCodeId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("ReturnId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("ReasonCodeId"); + + b.HasIndex("VendorId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("purchase_returns", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturnLine", b => + { + b.Property("ReturnLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnLineId")); + + b.Property("GrnLineId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReturnId") + .HasColumnType("integer"); + + b.HasKey("ReturnLineId"); + + b.HasIndex("GrnLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("ReturnId"); + + b.ToTable("purchase_return_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ReasonCode", b => + { + b.Property("ReasonCodeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReasonCodeId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Context") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.HasKey("ReasonCodeId"); + + b.HasIndex("Context", "Code") + .IsUnique(); + + b.ToTable("reason_codes", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => + { + b.Property("RequisitionId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RequisitionId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RequestedBy") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("RequisitionId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("RequestedBy"); + + b.HasIndex("Status"); + + b.ToTable("requisitions", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RequisitionLine", b => + { + b.Property("ReqLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReqLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RequiredBy") + .HasColumnType("date"); + + b.Property("RequisitionId") + .HasColumnType("integer"); + + b.HasKey("ReqLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RequisitionId"); + + b.ToTable("requisition_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => + { + b.Property("RfqId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RfqId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RequisitionId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("RfqId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("RequisitionId"); + + b.ToTable("rfqs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RfqLine", b => + { + b.Property("RfqLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RfqLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RfqId") + .HasColumnType("integer"); + + b.HasKey("RfqLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RfqId"); + + b.ToTable("rfq_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Role", b => + { + b.Property("RoleId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RoleId")); + + b.Property("AuthRoleId") + .HasColumnType("uuid") + .HasColumnName("auth_role_id"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsSystemRole") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("RoleId"); + + b.HasIndex("AuthRoleId") + .IsUnique(); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("roles", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RolePermission", b => + { + b.Property("RoleId") + .HasColumnType("integer"); + + b.Property("PermissionId") + .HasColumnType("integer"); + + b.HasKey("RoleId", "PermissionId"); + + b.HasIndex("PermissionId"); + + b.ToTable("role_permissions", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunEdge", b => + { + b.Property("RunEdgeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunEdgeId")); + + b.Property("ChildRunStageId") + .HasColumnType("integer"); + + b.Property("ParentRunStageId") + .HasColumnType("integer"); + + b.Property("RunId") + .HasColumnType("integer"); + + b.HasKey("RunEdgeId"); + + b.HasIndex("ChildRunStageId"); + + b.HasIndex("RunId"); + + b.HasIndex("ParentRunStageId", "ChildRunStageId") + .IsUnique(); + + b.ToTable("run_edges", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStage", b => + { + b.Property("RunStageId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunStageId")); + + b.Property("ActualEndAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ActualStartAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EstimatedMinutes") + .HasColumnType("integer"); + + b.Property("FieldDefs") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("FieldValues") + .HasColumnType("jsonb"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("PosX") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PosY") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RoleLabel") + .HasMaxLength(60) + .HasColumnType("character varying(60)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("RunId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("TemplateStageId") + .HasColumnType("integer"); + + b.HasKey("RunStageId"); + + b.HasIndex("TemplateStageId"); + + b.HasIndex("RunId", "Status"); + + b.ToTable("run_stages", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageEvent", b => + { + b.Property("EventId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EventId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Note") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Payload") + .HasColumnType("jsonb"); + + b.Property("RunId") + .HasColumnType("integer"); + + b.Property("RunStageId") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("EventId"); + + b.HasIndex("RunStageId"); + + b.HasIndex("UserId"); + + b.HasIndex("RunId", "EventId"); + + b.ToTable("run_stage_events", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageInput", b => + { + b.Property("RunInputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunInputId")); + + b.Property("ConsumedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ConsumedValue") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DeliveredQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("FromRunOutputId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("PlannedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyUnit") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ReturnedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReturnedValue") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RunStageId") + .HasColumnType("integer"); + + b.Property("Source") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("RunInputId"); + + b.HasIndex("FromRunOutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RunStageId"); + + b.ToTable("run_stage_inputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageOutput", b => + { + b.Property("RunOutputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunOutputId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("PlannedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ProducedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RunStageId") + .HasColumnType("integer"); + + b.Property("ScrapReasonCodeId") + .HasColumnType("integer"); + + b.Property("ScrappedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TransferredQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UomId") + .HasColumnType("integer"); + + b.HasKey("RunOutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RunStageId"); + + b.HasIndex("ScrapReasonCodeId"); + + b.HasIndex("UomId"); + + b.ToTable("run_stage_outputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalaryComponent", b => + { + b.Property("SalaryComponentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalaryComponentId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ComponentType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsEpfEtfApplicable") + .HasColumnType("boolean"); + + b.Property("IsTaxable") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("SalaryComponentId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_salary_components", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesDayEnd", b => + { + b.Property("SalesDayEndId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesDayEndId")); + + b.Property("BundleCount") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("BusinessDate") + .HasColumnType("date"); + + b.Property("CashierUserId") + .HasColumnType("integer"); + + b.Property("ClosedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ClosedBy") + .HasColumnType("integer"); + + b.Property("CostOfGoodsSold") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SlipCount") + .HasColumnType("integer"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("SalesDayEndId"); + + b.HasIndex("ClosedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("CashierUserId", "BusinessDate") + .IsUnique(); + + b.ToTable("sales_day_ends", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoice", b => + { + b.Property("SalesInvoiceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesInvoiceId")); + + b.Property("BalanceAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("CreatorUserId") + .HasColumnType("integer"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("CustomerSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CustomerSnapshotTaxNo") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("InvoiceDate") + .HasColumnType("timestamp with time zone"); + + b.Property("InvoiceNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("InvoiceType") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("B2C"); + + b.Property("NetPayable") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RoundOff") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesInvoiceId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatorUserId"); + + b.HasIndex("CustomerId"); + + b.HasIndex("InvoiceDate"); + + b.HasIndex("InvoiceNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_invoices", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoiceLine", b => + { + b.Property("SalesInvoiceLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesInvoiceLineId")); + + b.Property("BaseCost") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DiscountAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DiscountMode") + .HasColumnType("integer"); + + b.Property("DiscountPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("FreeQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("IsFreeIssue") + .HasColumnType("boolean"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("NetUnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ParentLineId") + .HasColumnType("integer"); + + b.Property("PriceSource") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SalesInvoiceId") + .HasColumnType("integer"); + + b.Property("TaxAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesInvoiceLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SalesInvoiceId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_invoice_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoicePayment", b => + { + b.Property("SalesInvoicePaymentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesInvoicePaymentId")); + + b.Property("Amount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BankAccountName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("GlBankAccountId") + .HasColumnType("bigint"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PaymentDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Reference") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("SalesInvoiceId") + .HasColumnType("integer"); + + b.HasKey("SalesInvoicePaymentId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("SalesInvoiceId"); + + b.ToTable("sales_invoice_payments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturn", b => + { + b.Property("ReturnId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReasonCodeId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("ReturnId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("CustomerId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("ReasonCodeId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_returns", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturnLine", b => + { + b.Property("ReturnLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReturnId") + .HasColumnType("integer"); + + b.Property("SalesInvoiceLineId") + .HasColumnType("integer"); + + b.HasKey("ReturnLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("ReturnId"); + + b.HasIndex("SalesInvoiceLineId"); + + b.ToTable("sales_return_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlip", b => + { + b.Property("SalesSlipId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesSlipId")); + + b.Property("BalanceAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CashierUserId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("CustomerSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DayEndId") + .HasColumnType("integer"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SlipDate") + .HasColumnType("timestamp with time zone"); + + b.Property("SlipNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesSlipId"); + + b.HasIndex("CashierUserId"); + + b.HasIndex("CustomerId"); + + b.HasIndex("DayEndId"); + + b.HasIndex("SlipDate"); + + b.HasIndex("SlipNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_slips", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlipLine", b => + { + b.Property("SalesSlipLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesSlipLineId")); + + b.Property("BaseCost") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DiscountAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DiscountMode") + .HasColumnType("integer"); + + b.Property("DiscountPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("FreeQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("IsFreeIssue") + .HasColumnType("boolean"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("NetUnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ParentLineId") + .HasColumnType("integer"); + + b.Property("PriceSource") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SalesSlipId") + .HasColumnType("integer"); + + b.Property("TaxAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesSlipLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SalesSlipId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_slip_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Serial", b => + { + b.Property("SerialId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SerialId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("SerialNo") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("SerialId"); + + b.HasIndex("ItemId", "SerialNo") + .IsUnique(); + + b.ToTable("serials", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageEdge", b => + { + b.Property("EdgeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EdgeId")); + + b.Property("ChildStageId") + .HasColumnType("integer"); + + b.Property("ParentStageId") + .HasColumnType("integer"); + + b.Property("TemplateId") + .HasColumnType("integer"); + + b.HasKey("EdgeId"); + + b.HasIndex("ChildStageId"); + + b.HasIndex("TemplateId"); + + b.HasIndex("ParentStageId", "ChildStageId") + .IsUnique(); + + b.ToTable("stage_edges", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageInput", b => + { + b.Property("InputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("InputId")); + + b.Property("FromOutputId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyPerBatch") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyUnit") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Source") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("StageId") + .HasColumnType("integer"); + + b.HasKey("InputId"); + + b.HasIndex("FromOutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("StageId"); + + b.ToTable("stage_inputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageOutput", b => + { + b.Property("OutputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("OutputId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("QtyPerBatch") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("StageId") + .HasColumnType("integer"); + + b.Property("UomId") + .HasColumnType("integer"); + + b.HasKey("OutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("StageId"); + + b.HasIndex("UomId"); + + b.ToTable("stage_outputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustment", b => + { + b.Property("AdjustmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AdjustmentId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReasonCodeId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("AdjustmentId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("ReasonCodeId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("stock_adjustments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustmentLine", b => + { + b.Property("AdjLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AdjLineId")); + + b.Property("AdjustmentId") + .HasColumnType("integer"); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyDelta") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.HasKey("AdjLineId"); + + b.HasIndex("AdjustmentId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SerialId"); + + b.ToTable("stock_adjustment_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCount", b => + { + b.Property("CountId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CountId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CountType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("CountId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("stock_counts", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCountLine", b => + { + b.Property("CountLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CountLineId")); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("CountId") + .HasColumnType("integer"); + + b.Property("CountedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("SystemQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Variance") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("CountLineId"); + + b.HasIndex("BinId"); + + b.HasIndex("CountId"); + + b.HasIndex("ItemId"); + + b.ToTable("stock_count_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLayer", b => + { + b.Property("LayerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LayerId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("GrnLineId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyReceived") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyRemaining") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReceiptDate") + .HasColumnType("timestamp with time zone"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("LayerId"); + + b.HasIndex("BatchId"); + + b.HasIndex("GrnLineId"); + + b.HasIndex("SerialId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("ItemId", "WarehouseId", "ReceiptDate", "LayerId"); + + b.ToTable("stock_layers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLedger", b => + { + b.Property("LedgerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LedgerId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Direction") + .IsRequired() + .HasMaxLength(5) + .HasColumnType("character varying(5)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyBase") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RunningBalance") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("SourceDocId") + .HasColumnType("integer"); + + b.Property("SourceDocType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.Property("Value") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("LedgerId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("SerialId"); + + b.HasIndex("UserId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("SourceDocType", "SourceDocId"); + + b.HasIndex("ItemId", "WarehouseId", "CreatedAt"); + + b.HasIndex("ItemId", "WarehouseId", "LedgerId"); + + b.ToTable("stock_ledger", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransfer", b => + { + b.Property("TransferId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TransferId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DestWarehouseId") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SrcWarehouseId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("TransferId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DestWarehouseId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("SrcWarehouseId"); + + b.HasIndex("Status"); + + b.ToTable("stock_transfers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransferLine", b => + { + b.Property("TransferLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TransferLineId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("DestBinId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyReceived") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("SrcBinId") + .HasColumnType("integer"); + + b.Property("TransferId") + .HasColumnType("integer"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.HasKey("TransferLineId"); + + b.HasIndex("BatchId"); + + b.HasIndex("DestBinId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SerialId"); + + b.HasIndex("SrcBinId"); + + b.HasIndex("TransferId"); + + b.ToTable("stock_transfer_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubCategory", b => + { + b.Property("SubCategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SubCategoryId")); + + b.Property("CategoryId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("SubCategoryId"); + + b.HasIndex("Status"); + + b.HasIndex("CategoryId", "Name") + .IsUnique(); + + b.ToTable("subcategories", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubNavItem", b => + { + b.Property("SubNavItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SubNavItemId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Href") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Icon") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("NavItemId") + .HasColumnType("integer"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.HasKey("SubNavItemId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("NavItemId"); + + b.ToTable("sub_nav_items", (string)null); + + b.HasData( + new + { + SubNavItemId = 1, + Code = "products.item", + Href = "/dashboard/products", + Label = "Item", + NavItemId = 2, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 2, + Code = "products.category", + Href = "/dashboard/products/categories", + Label = "Category", + NavItemId = 2, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 3, + Code = "products.brand", + Href = "/dashboard/products/brands", + Label = "Brand", + NavItemId = 2, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 4, + Code = "products.item-type", + Href = "/dashboard/products/item-types", + Label = "Item Type", + NavItemId = 2, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 5, + Code = "products.uom", + Href = "/dashboard/products/uoms", + Label = "UOM", + NavItemId = 2, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 6, + Code = "products.configuration", + Href = "/dashboard/products/settings", + Label = "Configuration", + NavItemId = 2, + SortOrder = 6, + Status = "Active" + }, + new + { + SubNavItemId = 29, + Code = "settings.branches", + Href = "/dashboard/settings/branches", + Label = "Branches", + NavItemId = 9, + SortOrder = 0, + Status = "Active" + }, + new + { + SubNavItemId = 7, + Code = "settings.roles", + Href = "/dashboard/settings/roles", + Label = "Roles", + NavItemId = 9, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 8, + Code = "settings.users", + Href = "/dashboard/settings/users", + Label = "Users", + NavItemId = 9, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 24, + Code = "settings.notification-config", + Href = "/dashboard/settings/notification-config", + Label = "Notification Config", + NavItemId = 9, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 40, + Code = "sales.invoices", + Href = "/dashboard/sales/invoices", + Label = "Sales", + NavItemId = 13, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 23, + Code = "sales.bundle-templates", + Href = "/dashboard/sales/bundles/templates", + Label = "Bundle Templates", + NavItemId = 13, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 41, + Code = "sales.free-issues", + Href = "/dashboard/sales/free-issues", + Label = "Free Issues", + NavItemId = 13, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 42, + Code = "sales.day-end", + Href = "/dashboard/sales/day-end", + Label = "Day End", + NavItemId = 13, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 30, + Code = "procurement.vendors", + Href = "/dashboard/vendors", + Label = "Vendors", + NavItemId = 4, + SortOrder = 0, + Status = "Active" + }, + new + { + SubNavItemId = 17, + Code = "procurement.requisitions", + Href = "/dashboard/procurement/requisitions", + Label = "Requisitions", + NavItemId = 4, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 18, + Code = "procurement.rfqs", + Href = "/dashboard/procurement/rfqs", + Label = "RFQs", + NavItemId = 4, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 19, + Code = "procurement.purchase-orders", + Href = "/dashboard/procurement/purchase-orders", + Label = "Purchase Orders", + NavItemId = 4, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 20, + Code = "procurement.purchase-returns", + Href = "/dashboard/procurement/purchase-returns", + Label = "Purchase Returns", + NavItemId = 4, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 28, + Code = "procurement.purchase-invoices", + Href = "/dashboard/procurement/purchase-invoices", + Label = "Purchase Invoices", + NavItemId = 4, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 9, + Code = "ledgers.trial-balance", + Href = "/dashboard/ledgers/trial-balance", + Label = "Trial Balance", + NavItemId = 11, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 10, + Code = "ledgers.balance-sheet", + Href = "/dashboard/ledgers/balance-sheet", + Label = "Balance Sheet", + NavItemId = 11, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 11, + Code = "ledgers.general-ledger", + Href = "/dashboard/ledgers/general-ledger", + Label = "General Ledger", + NavItemId = 11, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 12, + Code = "ledgers.profit-and-loss", + Href = "/dashboard/ledgers/profit-and-loss", + Label = "Profit & Loss", + NavItemId = 11, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 13, + Code = "ledgers.cash-flow", + Href = "/dashboard/ledgers/cash-flow", + Label = "Cash Flow", + NavItemId = 11, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 14, + Code = "ledgers.budget-vs-actual", + Href = "/dashboard/ledgers/budget-vs-actual", + Label = "Budget vs Actual", + NavItemId = 11, + SortOrder = 6, + Status = "Active" + }, + new + { + SubNavItemId = 16, + Code = "ledgers.tax-report", + Href = "/dashboard/ledgers/tax-report", + Label = "Tax Report", + NavItemId = 11, + SortOrder = 7, + Status = "Active" + }, + new + { + SubNavItemId = 15, + Code = "accounts.bank-accounts", + Href = "/dashboard/accounts/bank-accounts", + Label = "Cash / Bank Accounts", + NavItemId = 12, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 21, + Code = "accounts.cheque-books", + Href = "/dashboard/accounts/cheque-books", + Label = "Cheque Books", + NavItemId = 12, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 22, + Code = "accounts.received-cheques", + Href = "/dashboard/accounts/received-cheques", + Label = "Received Cheques", + NavItemId = 12, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 27, + Code = "production.templates", + Href = "/dashboard/production/templates", + Label = "Templates", + NavItemId = 14, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 25, + Code = "production.runs", + Href = "/dashboard/production/runs", + Label = "Runs", + NavItemId = 14, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 26, + Code = "production.produced", + Href = "/dashboard/production/produced", + Label = "Produced", + NavItemId = 14, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 31, + Code = "stock.ledger", + Href = "/dashboard/stock/ledger", + Label = "Stock Ledger", + NavItemId = 6, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 32, + Code = "stock.enquiry", + Href = "/dashboard/stock/enquiry", + Label = "Stock Enquiry", + NavItemId = 6, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 33, + Code = "stock.valuation", + Href = "/dashboard/stock/valuation", + Label = "Valuation", + NavItemId = 6, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 34, + Code = "stock.transfers", + Href = "/dashboard/stock/transfers", + Label = "Transfers", + NavItemId = 6, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 35, + Code = "stock.adjustments", + Href = "/dashboard/stock/adjustments", + Label = "Adjustments", + NavItemId = 6, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 36, + Code = "stock.counts", + Href = "/dashboard/stock/counts", + Label = "Counts", + NavItemId = 6, + SortOrder = 6, + Status = "Active" + }, + new + { + SubNavItemId = 37, + Code = "stock.reorder-alerts", + Href = "/dashboard/stock/reorder-alerts", + Label = "Reorder Alerts", + NavItemId = 6, + SortOrder = 7, + Status = "Active" + }, + new + { + SubNavItemId = 38, + Code = "stock.wastage", + Href = "/dashboard/stock/wastage", + Label = "Wastage", + NavItemId = 6, + SortOrder = 8, + Status = "Active" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicket", b => + { + b.Property("TicketId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TicketId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Subject") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.HasKey("TicketId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("Status"); + + b.ToTable("support_tickets", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicketMessage", b => + { + b.Property("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("MessageId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsFromAdmin") + .HasColumnType("boolean"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("SenderUserId") + .HasColumnType("integer"); + + b.Property("TicketId") + .HasColumnType("integer"); + + b.HasKey("MessageId"); + + b.HasIndex("TicketId", "CreatedAt"); + + b.ToTable("support_ticket_messages", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TaxSlab", b => + { + b.Property("TaxSlabId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TaxSlabId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveTo") + .HasColumnType("timestamp with time zone"); + + b.Property("LowerBound") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("Rate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("UpperBound") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.HasKey("TaxSlabId"); + + b.HasIndex("EffectiveFrom"); + + b.ToTable("hr_tax_slabs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => + { + b.Property("StageId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("StageId")); + + b.Property("EstimatedMinutes") + .HasColumnType("integer"); + + b.Property("FieldDefs") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("PosX") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PosY") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RoleLabel") + .HasMaxLength(60) + .HasColumnType("character varying(60)"); + + b.Property("TemplateId") + .HasColumnType("integer"); + + b.HasKey("StageId"); + + b.HasIndex("TemplateId"); + + b.ToTable("template_stages", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Uom", b => + { + b.Property("UomId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("UomId")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("UomId"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("uoms", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.User", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("UserId")); + + b.Property("AuthUserId") + .HasColumnType("uuid") + .HasColumnName("auth_user_id"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Email") + .HasMaxLength(320) + .HasColumnType("character varying(320)"); + + b.Property("RoleId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("UserId"); + + b.HasIndex("AuthUserId") + .IsUnique(); + + b.HasIndex("Email") + .IsUnique(); + + b.HasIndex("RoleId"); + + b.HasIndex("Username") + .IsUnique(); + + b.ToTable("users", (string)null); + + b.HasData( + new + { + UserId = 1, + DisplayName = "System", + Status = "Active", + Username = "system" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Vendor", b => + { + b.Property("VendorId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("VendorId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Currency") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(3) + .HasColumnType("character varying(3)") + .HasDefaultValue("LKR"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TaxReg") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Terms") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("VendorId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("vendors", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => + { + b.Property("QuotationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("QuotationId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("RfqId") + .HasColumnType("integer"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.HasKey("QuotationId"); + + b.HasIndex("VendorId"); + + b.HasIndex("RfqId", "VendorId") + .IsUnique(); + + b.ToTable("vendor_quotations", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotationLine", b => + { + b.Property("QuotationLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("QuotationLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LeadDays") + .HasColumnType("integer"); + + b.Property("QuotationId") + .HasColumnType("integer"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("QuotationLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("QuotationId"); + + b.ToTable("vendor_quotation_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Warehouse", b => + { + b.Property("WarehouseId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("WarehouseId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.HasKey("WarehouseId"); + + b.HasIndex("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("warehouses", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.WorkShift", b => + { + b.Property("WorkShiftId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("WorkShiftId")); + + b.Property("BreakMinutes") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EndTime") + .HasColumnType("interval"); + + b.Property("GraceMinutes") + .HasColumnType("integer"); + + b.Property("IsOvernight") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("OtMultiplier") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("StandardWorkingMinutes") + .HasColumnType("integer"); + + b.Property("StartTime") + .HasColumnType("interval"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WorkingDaysMask") + .HasColumnType("integer"); + + b.HasKey("WorkShiftId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_work_shifts", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceRecord", b => + { + b.HasOne("ERPCore.Domain.Entities.AttendanceUploadBatch", "AttendanceUploadBatch") + .WithMany() + .HasForeignKey("AttendanceUploadBatchId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.WorkShift", "WorkShift") + .WithMany() + .HasForeignKey("WorkShiftId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("AttendanceUploadBatch"); + + b.Navigation("Employee"); + + b.Navigation("WorkShift"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AuditLog", b => + { + b.HasOne("ERPCore.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Batch", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Bin", b => + { + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany("Bins") + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BranchConfig", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSale", b => + { + b.HasOne("ERPCore.Domain.Entities.BundleSaleTemplate", "BundleSaleTemplate") + .WithMany() + .HasForeignKey("BundleSaleTemplateId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "CashierUser") + .WithMany() + .HasForeignKey("CashierUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesDayEnd", "DayEnd") + .WithMany("BundleSales") + .HasForeignKey("DayEndId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BundleSaleTemplate"); + + b.Navigation("CashierUser"); + + b.Navigation("Customer"); + + b.Navigation("DayEnd"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleLine", b => + { + b.HasOne("ERPCore.Domain.Entities.BundleSale", "BundleSale") + .WithMany("Lines") + .HasForeignKey("BundleSaleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BundleSale"); + + b.Navigation("Item"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplateLine", b => + { + b.HasOne("ERPCore.Domain.Entities.BundleSaleTemplate", "BundleSaleTemplate") + .WithMany("Lines") + .HasForeignKey("BundleSaleTemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BundleSaleTemplate"); + + b.Navigation("Item"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Customer", b => + { + b.HasOne("ERPCore.Domain.Entities.Warehouse", "DefaultWarehouse") + .WithMany() + .HasForeignKey("DefaultWarehouseId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("DefaultWarehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Department", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Employee", "HeadEmployee") + .WithMany() + .HasForeignKey("HeadEmployeeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Department", "ParentDepartment") + .WithMany() + .HasForeignKey("ParentDepartmentId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Branch"); + + b.Navigation("HeadEmployee"); + + b.Navigation("ParentDepartment"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Employee", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Department", "Department") + .WithMany() + .HasForeignKey("DepartmentId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Designation", "Designation") + .WithMany() + .HasForeignKey("DesignationId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.EmploymentType", "EmploymentType") + .WithMany() + .HasForeignKey("EmploymentTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Employee", "ReportingManager") + .WithMany() + .HasForeignKey("ReportingManagerId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithOne() + .HasForeignKey("ERPCore.Domain.Entities.Employee", "UserId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.WorkShift", "WorkShift") + .WithMany() + .HasForeignKey("WorkShiftId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Department"); + + b.Navigation("Designation"); + + b.Navigation("EmploymentType"); + + b.Navigation("ReportingManager"); + + b.Navigation("User"); + + b.Navigation("WorkShift"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeBankDetail", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeDocument", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.HrDocumentType", "HrDocumentType") + .WithMany() + .HasForeignKey("HrDocumentTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("HrDocumentType"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeLoan", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructure", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructureLine", b => + { + b.HasOne("ERPCore.Domain.Entities.EmployeeSalaryStructure", "EmployeeSalaryStructure") + .WithMany("Lines") + .HasForeignKey("EmployeeSalaryStructureId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalaryComponent", "SalaryComponent") + .WithMany() + .HasForeignKey("SalaryComponentId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("EmployeeSalaryStructure"); + + b.Navigation("SalaryComponent"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Grn", 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.HasOne("ERPCore.Domain.Entities.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("PoId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.PurchaseInvoice", "PurchaseInvoice") + .WithMany() + .HasForeignKey("PurchaseInvoiceId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("PurchaseInvoice"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Vendor"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", "Batch") + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", "Bin") + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Grn", "Grn") + .WithMany("Lines") + .HasForeignKey("GrnId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PoLine", "PoLine") + .WithMany() + .HasForeignKey("PoLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Batch"); + + b.Navigation("Bin"); + + b.Navigation("Grn"); + + b.Navigation("Item"); + + b.Navigation("PoLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLineWarrantyNumber", b => + { + b.HasOne("ERPCore.Domain.Entities.GrnLine", "GrnLine") + .WithMany("WarrantyNumbers") + .HasForeignKey("GrnLineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GrnLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Item", b => + { + b.HasOne("ERPCore.Domain.Entities.Uom", "BaseUom") + .WithMany() + .HasForeignKey("BaseUomId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Brand", "Brand") + .WithMany() + .HasForeignKey("BrandId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Category", "Category") + .WithMany() + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "DefaultVendor") + .WithMany() + .HasForeignKey("DefaultVendorId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.SubCategory", "SubCategory") + .WithMany() + .HasForeignKey("SubCategoryId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("BaseUom"); + + b.Navigation("Brand"); + + b.Navigation("Category"); + + b.Navigation("DefaultVendor"); + + b.Navigation("SubCategory"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ItemReorder", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany("ReorderSettings") + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveBalance", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.LeaveType", "LeaveType") + .WithMany() + .HasForeignKey("LeaveTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("LeaveType"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveRequest", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.LeaveType", "LeaveType") + .WithMany() + .HasForeignKey("LeaveTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("LeaveType"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoanInstallment", b => + { + b.HasOne("ERPCore.Domain.Entities.EmployeeLoan", "EmployeeLoan") + .WithMany("Installments") + .HasForeignKey("EmployeeLoanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PayrollRun", "PayrollRun") + .WithMany() + .HasForeignKey("PayrollRunId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("EmployeeLoan"); + + b.Navigation("PayrollRun"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoginActivity", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfigModule", b => + { + b.HasOne("ERPCore.Domain.Entities.NotificationConfig", "NotificationConfig") + .WithMany("Modules") + .HasForeignKey("NotificationConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("NotificationConfig"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationRecipient", b => + { + b.HasOne("ERPCore.Domain.Entities.Notification", "Notification") + .WithMany("Recipients") + .HasForeignKey("NotificationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Notification"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PayrollRun", "PayrollRun") + .WithMany("Lines") + .HasForeignKey("PayrollRunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("PayrollRun"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLineComponent", b => + { + b.HasOne("ERPCore.Domain.Entities.PayrollLine", "PayrollLine") + .WithMany("Components") + .HasForeignKey("PayrollLineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalaryComponent", "SalaryComponent") + .WithMany() + .HasForeignKey("SalaryComponentId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("PayrollLine"); + + b.Navigation("SalaryComponent"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollRun", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Branch"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Payslip", b => + { + b.HasOne("ERPCore.Domain.Entities.PayrollLine", "PayrollLine") + .WithOne() + .HasForeignKey("ERPCore.Domain.Entities.Payslip", "PayrollLineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PayrollLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Permission", b => + { + b.HasOne("ERPCore.Domain.Entities.NavItem", "NavItem") + .WithMany() + .HasForeignKey("NavItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ERPCore.Domain.Entities.SubNavItem", "SubNavItem") + .WithMany() + .HasForeignKey("SubNavItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("NavItem"); + + b.Navigation("SubNavItem"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PoLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseOrder", "PurchaseOrder") + .WithMany("Lines") + .HasForeignKey("PoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductConfig", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b => + { + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "CancelReason") + .WithMany() + .HasForeignKey("CancelReasonCodeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Bin", "OutputBin") + .WithMany() + .HasForeignKey("OutputBinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") + .WithMany("Runs") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CancelReason"); + + b.Navigation("Creator"); + + b.Navigation("OutputBin"); + + b.Navigation("Template"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionTemplate", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoiceLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Grn", "Grn") + .WithMany() + .HasForeignKey("GrnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseInvoice", "PurchaseInvoice") + .WithMany("Lines") + .HasForeignKey("PurchaseInvoiceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Grn"); + + b.Navigation("PurchaseInvoice"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoicePayment", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseInvoice", "PurchaseInvoice") + .WithMany("Payments") + .HasForeignKey("PurchaseInvoiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("PurchaseInvoice"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") + .WithMany() + .HasForeignKey("RequisitionId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("Requisition"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturn", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ReasonCode") + .WithMany() + .HasForeignKey("ReasonCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("ReasonCode"); + + b.Navigation("Vendor"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturnLine", b => + { + b.HasOne("ERPCore.Domain.Entities.GrnLine", "GrnLine") + .WithMany() + .HasForeignKey("GrnLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseReturn", "Return") + .WithMany("Lines") + .HasForeignKey("ReturnId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GrnLine"); + + b.Navigation("Item"); + + b.Navigation("Return"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Requester") + .WithMany() + .HasForeignKey("RequestedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Requester"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RequisitionLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") + .WithMany("Lines") + .HasForeignKey("RequisitionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Requisition"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => + { + b.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") + .WithMany() + .HasForeignKey("RequisitionId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Requisition"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RfqLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Rfq", "Rfq") + .WithMany("Lines") + .HasForeignKey("RfqId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Rfq"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RolePermission", b => + { + b.HasOne("ERPCore.Domain.Entities.Permission", "Permission") + .WithMany() + .HasForeignKey("PermissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Role", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Permission"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunEdge", b => + { + b.HasOne("ERPCore.Domain.Entities.RunStage", "ChildRunStage") + .WithMany() + .HasForeignKey("ChildRunStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "ParentRunStage") + .WithMany() + .HasForeignKey("ParentRunStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ProductionRun", "Run") + .WithMany("Edges") + .HasForeignKey("RunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildRunStage"); + + b.Navigation("ParentRunStage"); + + b.Navigation("Run"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStage", b => + { + b.HasOne("ERPCore.Domain.Entities.ProductionRun", "Run") + .WithMany("Stages") + .HasForeignKey("RunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "TemplateStage") + .WithMany() + .HasForeignKey("TemplateStageId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Run"); + + b.Navigation("TemplateStage"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageEvent", b => + { + b.HasOne("ERPCore.Domain.Entities.ProductionRun", "Run") + .WithMany("Events") + .HasForeignKey("RunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "RunStage") + .WithMany("Events") + .HasForeignKey("RunStageId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Run"); + + b.Navigation("RunStage"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageInput", b => + { + b.HasOne("ERPCore.Domain.Entities.RunStageOutput", "FromRunOutput") + .WithMany() + .HasForeignKey("FromRunOutputId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "RunStage") + .WithMany("Inputs") + .HasForeignKey("RunStageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromRunOutput"); + + b.Navigation("Item"); + + b.Navigation("RunStage"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageOutput", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "RunStage") + .WithMany("Outputs") + .HasForeignKey("RunStageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ScrapReason") + .WithMany() + .HasForeignKey("ScrapReasonCodeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Uom", "Uom") + .WithMany() + .HasForeignKey("UomId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Item"); + + b.Navigation("RunStage"); + + b.Navigation("ScrapReason"); + + b.Navigation("Uom"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesDayEnd", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "CashierUser") + .WithMany() + .HasForeignKey("CashierUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "ClosedByUser") + .WithMany() + .HasForeignKey("ClosedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CashierUser"); + + b.Navigation("ClosedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoice", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatorUserId"); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("Customer"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoiceLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesInvoice", "SalesInvoice") + .WithMany("Lines") + .HasForeignKey("SalesInvoiceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SalesInvoice"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoicePayment", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesInvoice", "SalesInvoice") + .WithMany("Payments") + .HasForeignKey("SalesInvoiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("SalesInvoice"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturn", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ReasonCode") + .WithMany() + .HasForeignKey("ReasonCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("Customer"); + + b.Navigation("ReasonCode"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturnLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesReturn", "Return") + .WithMany("Lines") + .HasForeignKey("ReturnId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesInvoiceLine", "SalesInvoiceLine") + .WithMany() + .HasForeignKey("SalesInvoiceLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Item"); + + b.Navigation("Return"); + + b.Navigation("SalesInvoiceLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlip", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "CashierUser") + .WithMany() + .HasForeignKey("CashierUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesDayEnd", "DayEnd") + .WithMany("Slips") + .HasForeignKey("DayEndId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CashierUser"); + + b.Navigation("Customer"); + + b.Navigation("DayEnd"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlipLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesSlip", "SalesSlip") + .WithMany("Lines") + .HasForeignKey("SalesSlipId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SalesSlip"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Serial", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageEdge", b => + { + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "ChildStage") + .WithMany() + .HasForeignKey("ChildStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "ParentStage") + .WithMany() + .HasForeignKey("ParentStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") + .WithMany("Edges") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildStage"); + + b.Navigation("ParentStage"); + + b.Navigation("Template"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageInput", b => + { + b.HasOne("ERPCore.Domain.Entities.StageOutput", "FromOutput") + .WithMany() + .HasForeignKey("FromOutputId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "Stage") + .WithMany("Inputs") + .HasForeignKey("StageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromOutput"); + + b.Navigation("Item"); + + b.Navigation("Stage"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageOutput", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "Stage") + .WithMany("Outputs") + .HasForeignKey("StageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Uom", "Uom") + .WithMany() + .HasForeignKey("UomId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Item"); + + b.Navigation("Stage"); + + b.Navigation("Uom"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustment", 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.HasOne("ERPCore.Domain.Entities.ReasonCode", "ReasonCode") + .WithMany() + .HasForeignKey("ReasonCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("ReasonCode"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustmentLine", b => + { + b.HasOne("ERPCore.Domain.Entities.StockAdjustment", "Adjustment") + .WithMany("Lines") + .HasForeignKey("AdjustmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Batch", null) + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", null) + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Adjustment"); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCount", 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.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCountLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.StockCount", "Count") + .WithMany("Lines") + .HasForeignKey("CountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Count"); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLayer", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", "Batch") + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.GrnLine", "GrnLine") + .WithMany() + .HasForeignKey("GrnLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", "Serial") + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Batch"); + + b.Navigation("GrnLine"); + + b.Navigation("Item"); + + b.Navigation("Serial"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLedger", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", null) + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", null) + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", null) + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", null) + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransfer", 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.HasOne("ERPCore.Domain.Entities.Warehouse", "DestWarehouse") + .WithMany() + .HasForeignKey("DestWarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "SrcWarehouse") + .WithMany() + .HasForeignKey("SrcWarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("DestWarehouse"); + + b.Navigation("SrcWarehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransferLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", null) + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("DestBinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", null) + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("SrcBinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.StockTransfer", "Transfer") + .WithMany("Lines") + .HasForeignKey("TransferId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Transfer"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubCategory", b => + { + b.HasOne("ERPCore.Domain.Entities.Category", "Category") + .WithMany("SubCategories") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubNavItem", b => + { + b.HasOne("ERPCore.Domain.Entities.NavItem", "NavItem") + .WithMany("Children") + .HasForeignKey("NavItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("NavItem"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicketMessage", b => + { + b.HasOne("ERPCore.Domain.Entities.SupportTicket", "Ticket") + .WithMany("Messages") + .HasForeignKey("TicketId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ticket"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => + { + b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") + .WithMany("Stages") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Template"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.User", b => + { + b.HasOne("ERPCore.Domain.Entities.Role", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => + { + b.HasOne("ERPCore.Domain.Entities.Rfq", "Rfq") + .WithMany("Quotations") + .HasForeignKey("RfqId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Rfq"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotationLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.VendorQuotation", "Quotation") + .WithMany("Lines") + .HasForeignKey("QuotationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Quotation"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Warehouse", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSale", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplate", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Category", b => + { + b.Navigation("SubCategories"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeLoan", b => + { + b.Navigation("Installments"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructure", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Grn", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLine", b => + { + b.Navigation("WarrantyNumbers"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Item", b => + { + b.Navigation("ReorderSettings"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NavItem", b => + { + b.Navigation("Children"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Notification", b => + { + b.Navigation("Recipients"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => + { + b.Navigation("Modules"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => + { + b.Navigation("Components"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollRun", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b => + { + b.Navigation("Edges"); + + b.Navigation("Events"); + + b.Navigation("Stages"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionTemplate", b => + { + b.Navigation("Edges"); + + b.Navigation("Runs"); + + b.Navigation("Stages"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", b => + { + b.Navigation("Lines"); + + b.Navigation("Payments"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturn", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => + { + b.Navigation("Lines"); + + b.Navigation("Quotations"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStage", b => + { + b.Navigation("Events"); + + b.Navigation("Inputs"); + + b.Navigation("Outputs"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesDayEnd", b => + { + b.Navigation("BundleSales"); + + b.Navigation("Slips"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoice", b => + { + b.Navigation("Lines"); + + b.Navigation("Payments"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturn", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlip", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustment", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCount", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransfer", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicket", b => + { + b.Navigation("Messages"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => + { + b.Navigation("Inputs"); + + b.Navigation("Outputs"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Warehouse", b => + { + b.Navigation("Bins"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Backend/ERPCore/Migrations/20260915065226_RestyleSupportTicketLikeEmployee.cs b/Backend/ERPCore/Migrations/20260915065226_RestyleSupportTicketLikeEmployee.cs new file mode 100644 index 0000000..9e7cb83 --- /dev/null +++ b/Backend/ERPCore/Migrations/20260915065226_RestyleSupportTicketLikeEmployee.cs @@ -0,0 +1,79 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace ERPCore.Migrations +{ + /// + public partial class RestyleSupportTicketLikeEmployee : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "CreatedByUserId", + table: "support_tickets", + newName: "CreatedBy"); + + migrationBuilder.RenameIndex( + name: "IX_support_tickets_CreatedByUserId", + table: "support_tickets", + newName: "IX_support_tickets_CreatedBy"); + + migrationBuilder.AlterColumn( + name: "UpdatedAt", + table: "support_tickets", + type: "timestamp with time zone", + nullable: true, + oldClrType: typeof(DateTime), + oldType: "timestamp with time zone"); + + migrationBuilder.AddColumn( + name: "UpdatedBy", + table: "support_tickets", + type: "integer", + nullable: true); + + migrationBuilder.AddColumn( + name: "xmin", + table: "support_tickets", + type: "xid", + rowVersion: true, + nullable: false, + defaultValue: 0u); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "UpdatedBy", + table: "support_tickets"); + + migrationBuilder.DropColumn( + name: "xmin", + table: "support_tickets"); + + migrationBuilder.RenameColumn( + name: "CreatedBy", + table: "support_tickets", + newName: "CreatedByUserId"); + + migrationBuilder.RenameIndex( + name: "IX_support_tickets_CreatedBy", + table: "support_tickets", + newName: "IX_support_tickets_CreatedByUserId"); + + migrationBuilder.AlterColumn( + name: "UpdatedAt", + table: "support_tickets", + type: "timestamp with time zone", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + oldClrType: typeof(DateTime), + oldType: "timestamp with time zone", + oldNullable: true); + } + } +} diff --git a/Backend/ERPCore/Migrations/20260915100820_AddWarehouseAddressPhone.Designer.cs b/Backend/ERPCore/Migrations/20260915100820_AddWarehouseAddressPhone.Designer.cs new file mode 100644 index 0000000..cb9ec89 --- /dev/null +++ b/Backend/ERPCore/Migrations/20260915100820_AddWarehouseAddressPhone.Designer.cs @@ -0,0 +1,8423 @@ +// +using System; +using ERPCore.Infra.Persistence; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace ERPCore.Migrations +{ + [DbContext(typeof(ErpDbContext))] + [Migration("20260915100820_AddWarehouseAddressPhone")] + partial class AddWarehouseAddressPhone + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.9") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceRecord", b => + { + b.Property("AttendanceRecordId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AttendanceRecordId")); + + b.Property("AttendanceDate") + .HasColumnType("timestamp with time zone"); + + b.Property("AttendanceStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("AttendanceUploadBatchId") + .HasColumnType("integer"); + + b.Property("CheckIn") + .HasColumnType("interval"); + + b.Property("CheckOut") + .HasColumnType("interval"); + + b.Property("DuplicateOfAttendanceRecordId") + .HasColumnType("integer"); + + b.Property("EarlyLeaveMinutes") + .HasColumnType("integer"); + + b.Property("EditedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EditedBy") + .HasColumnType("integer"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("IsManualOverride") + .HasColumnType("boolean"); + + b.Property("LateMinutes") + .HasColumnType("integer"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("OvertimeMinutes") + .HasColumnType("integer"); + + b.Property("RowValidationStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("WorkShiftId") + .HasColumnType("integer"); + + b.Property("WorkingMinutes") + .HasColumnType("integer"); + + b.HasKey("AttendanceRecordId"); + + b.HasIndex("AttendanceUploadBatchId"); + + b.HasIndex("WorkShiftId"); + + b.HasIndex("EmployeeId", "AttendanceDate"); + + b.ToTable("hr_attendance_records", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceUploadBatch", b => + { + b.Property("AttendanceUploadBatchId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AttendanceUploadBatchId")); + + b.Property("ConfirmedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ConfirmedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("OriginalFileName") + .HasMaxLength(260) + .HasColumnType("character varying(260)"); + + b.Property("PeriodEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("PeriodStart") + .HasColumnType("timestamp with time zone"); + + b.Property("RowCountDuplicate") + .HasColumnType("integer"); + + b.Property("RowCountError") + .HasColumnType("integer"); + + b.Property("RowCountTotal") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SourceType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UploadedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UploadedBy") + .HasColumnType("integer"); + + b.HasKey("AttendanceUploadBatchId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("PeriodStart", "PeriodEnd"); + + b.ToTable("hr_attendance_upload_batches", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AuditLog", b => + { + b.Property("AuditId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AuditId")); + + b.Property("Action") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("ChangeSet") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EntityId") + .HasColumnType("integer"); + + b.Property("EntityType") + .IsRequired() + .HasMaxLength(80) + .HasColumnType("character varying(80)"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("AuditId"); + + b.HasIndex("CreatedAt"); + + b.HasIndex("UserId"); + + b.HasIndex("EntityType", "EntityId"); + + b.ToTable("audit_logs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Batch", b => + { + b.Property("BatchId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BatchId")); + + b.Property("BatchNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ExpiryDate") + .HasColumnType("date"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.HasKey("BatchId"); + + b.HasIndex("ItemId", "BatchNo") + .IsUnique(); + + b.ToTable("batches", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Bin", b => + { + b.Property("BinId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BinId")); + + b.Property("BinType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BinId"); + + b.HasIndex("WarehouseId", "Code") + .IsUnique(); + + b.ToTable("bins", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Branch", b => + { + b.Property("BranchId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BranchId")); + + b.Property("Address") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("PhoneNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_branches", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BranchConfig", b => + { + b.Property("ConfigId") + .HasColumnType("integer"); + + b.Property("BranchingEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.HasKey("ConfigId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("branch_config", null, t => + { + t.HasCheckConstraint("ck_branch_config_singleton", "\"ConfigId\" = 1"); + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Brand", b => + { + b.Property("BrandId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BrandId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("BrandId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("brands", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSale", b => + { + b.Property("BundleSaleId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleId")); + + b.Property("BundleCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BundleDate") + .HasColumnType("timestamp with time zone"); + + b.Property("BundleName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("BundleNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BundlePrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BundleSaleTemplateId") + .HasColumnType("integer"); + + b.Property("CashierUserId") + .HasColumnType("integer"); + + b.Property("ComponentSubtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("CustomerSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DayEndId") + .HasColumnType("integer"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("MarginAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BundleSaleId"); + + b.HasIndex("BundleNo") + .IsUnique(); + + b.HasIndex("BundleSaleTemplateId"); + + b.HasIndex("CashierUserId"); + + b.HasIndex("CustomerId"); + + b.HasIndex("DayEndId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("bundle_sales", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleLine", b => + { + b.Property("BundleSaleLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleLineId")); + + b.Property("BundleSaleId") + .HasColumnType("integer"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("IncludeInBundle") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("IsComponent") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ParentLineId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BundleSaleLineId"); + + b.HasIndex("BundleSaleId"); + + b.HasIndex("ItemId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("bundle_sale_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplate", b => + { + b.Property("BundleSaleTemplateId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleTemplateId")); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TemplateCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("TemplateName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("BundleSaleTemplateId"); + + b.HasIndex("TemplateCode") + .IsUnique(); + + b.ToTable("bundle_sale_templates", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplateLine", b => + { + b.Property("BundleSaleTemplateLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleTemplateLineId")); + + b.Property("BundleSaleTemplateId") + .HasColumnType("integer"); + + b.Property("IncludeInBundle") + .HasColumnType("boolean"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SortOrder") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BundleSaleTemplateLineId"); + + b.HasIndex("BundleSaleTemplateId"); + + b.HasIndex("ItemId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("bundle_sale_template_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Category", b => + { + b.Property("CategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CategoryId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("CategoryId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("categories", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Customer", b => + { + b.Property("CustomerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CustomerId")); + + b.Property("AddressLine1") + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("AddressLine2") + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("City") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Country") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreditDays") + .HasColumnType("integer"); + + b.Property("CreditLimit") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CustomerCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CustomerType") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("B2C"); + + b.Property("DefaultWarehouseId") + .HasColumnType("integer"); + + b.Property("DisplayName") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Email") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Phone") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TaxRegistrationNo") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("CustomerId"); + + b.HasIndex("CustomerCode") + .IsUnique(); + + b.HasIndex("CustomerType"); + + b.HasIndex("DefaultWarehouseId"); + + b.HasIndex("Status"); + + b.ToTable("customers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Department", b => + { + b.Property("DepartmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("DepartmentId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("HeadEmployeeId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("ParentDepartmentId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("DepartmentId"); + + b.HasIndex("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("HeadEmployeeId"); + + b.HasIndex("ParentDepartmentId"); + + b.HasIndex("Status"); + + b.ToTable("hr_departments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Designation", b => + { + b.Property("DesignationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("DesignationId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("DesignationId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_designations", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Employee", b => + { + b.Property("EmployeeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeId")); + + b.Property("AddressLine1") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("AddressLine2") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("City") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ConfirmationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Country") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DateOfBirth") + .HasColumnType("timestamp with time zone"); + + b.Property("DepartmentId") + .HasColumnType("integer"); + + b.Property("DesignationId") + .HasColumnType("integer"); + + b.Property("Email") + .HasMaxLength(320) + .HasColumnType("character varying(320)"); + + b.Property("EmergencyContactName") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("EmergencyContactPhone") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmergencyContactRelationship") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("EmployeeCode") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmploymentTypeId") + .HasColumnType("integer"); + + b.Property("EpfNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EtfNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Gender") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("HireDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LastWorkingDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Nationality") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Nic") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PersonalMobile") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PostalCode") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ProfilePhotoPath") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("ReportingManagerId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TaxIdentificationNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.Property("WorkShiftId") + .HasColumnType("integer"); + + b.HasKey("EmployeeId"); + + b.HasIndex("BranchId"); + + b.HasIndex("DepartmentId"); + + b.HasIndex("DesignationId"); + + b.HasIndex("Email"); + + b.HasIndex("EmployeeCode") + .IsUnique(); + + b.HasIndex("EmploymentTypeId"); + + b.HasIndex("ReportingManagerId"); + + b.HasIndex("Status"); + + b.HasIndex("UserId") + .IsUnique(); + + b.HasIndex("WorkShiftId"); + + b.ToTable("hr_employees", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeBankDetail", b => + { + b.Property("EmployeeBankDetailId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeBankDetailId")); + + b.Property("AccountHolderName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("AccountNumber") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BankName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("BranchName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("IsPrimary") + .HasColumnType("boolean"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("SwiftCode") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("EmployeeBankDetailId"); + + b.HasIndex("EmployeeId"); + + b.ToTable("hr_employee_bank_details", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeDocument", b => + { + b.Property("EmployeeDocumentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeDocumentId")); + + b.Property("ContentType") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("ExpiryDate") + .HasColumnType("timestamp with time zone"); + + b.Property("HrDocumentTypeId") + .HasColumnType("integer"); + + b.Property("IssueDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("OriginalFileName") + .IsRequired() + .HasMaxLength(260) + .HasColumnType("character varying(260)"); + + b.Property("RelativePath") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SizeBytes") + .HasColumnType("bigint"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("StoredFileName") + .IsRequired() + .HasMaxLength(260) + .HasColumnType("character varying(260)"); + + b.Property("UploadedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UploadedBy") + .HasColumnType("integer"); + + b.Property("VerifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VerifiedBy") + .HasColumnType("integer"); + + b.HasKey("EmployeeDocumentId"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("ExpiryDate"); + + b.HasIndex("HrDocumentTypeId"); + + b.ToTable("hr_employee_documents", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeLoan", b => + { + b.Property("EmployeeLoanId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeLoanId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("InstallmentAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("InterestRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("LoanKind") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("NumberOfInstallments") + .HasColumnType("integer"); + + b.Property("OutstandingBalance") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("PrincipalAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("StartMonth") + .HasColumnType("integer"); + + b.Property("StartYear") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("EmployeeLoanId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("EmployeeId"); + + b.HasIndex("Status"); + + b.ToTable("hr_employee_loans", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructure", b => + { + b.Property("EmployeeSalaryStructureId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeSalaryStructureId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("BasicSalary") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("Currency") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("character varying(3)"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveTo") + .HasColumnType("timestamp with time zone"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("EmployeeSalaryStructureId"); + + b.HasIndex("EmployeeId", "EffectiveTo"); + + b.ToTable("hr_employee_salary_structures", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructureLine", b => + { + b.Property("EmployeeSalaryStructureLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeSalaryStructureLineId")); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("EmployeeSalaryStructureId") + .HasColumnType("integer"); + + b.Property("SalaryComponentId") + .HasColumnType("integer"); + + b.HasKey("EmployeeSalaryStructureLineId"); + + b.HasIndex("EmployeeSalaryStructureId"); + + b.HasIndex("SalaryComponentId"); + + b.ToTable("hr_employee_salary_structure_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmploymentType", b => + { + b.Property("EmploymentTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmploymentTypeId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("EmploymentTypeId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_employment_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Grn", b => + { + b.Property("GrnId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("GrnId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PoId") + .HasColumnType("integer"); + + b.Property("PostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PurchaseInvoiceId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("GrnId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("PoId"); + + b.HasIndex("PurchaseInvoiceId"); + + b.HasIndex("Status"); + + b.HasIndex("VendorId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("grns", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLine", b => + { + b.Property("GrnLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("GrnLineId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("DiscountPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("GrnId") + .HasColumnType("integer"); + + b.Property("HoldStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("NetUnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("PoLineId") + .HasColumnType("integer"); + + b.Property("PoUnitPrice") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReceivedValue") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("VatAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("VatPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.HasKey("GrnLineId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("GrnId"); + + b.HasIndex("ItemId"); + + b.HasIndex("PoLineId"); + + b.ToTable("grn_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLineWarrantyNumber", b => + { + b.Property("GrnLineWarrantyNumberId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("GrnLineWarrantyNumberId")); + + b.Property("GrnLineId") + .HasColumnType("integer"); + + b.Property("WarrantyNo") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("WarrantyPeriodMonths") + .HasColumnType("integer"); + + b.HasKey("GrnLineWarrantyNumberId"); + + b.HasIndex("GrnLineId", "WarrantyNo") + .IsUnique(); + + b.ToTable("grn_line_warranty_numbers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.HrDocumentType", b => + { + b.Property("HrDocumentTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("HrDocumentTypeId")); + + b.Property("Category") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpiryTracked") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RequiredAtOnboarding") + .HasColumnType("boolean"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("HrDocumentTypeId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_document_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Item", b => + { + b.Property("ItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ItemId")); + + b.Property("BaseUomId") + .HasColumnType("integer"); + + b.Property("BrandId") + .HasColumnType("integer"); + + b.Property("CategoryId") + .HasColumnType("integer"); + + b.Property("ContentBaseQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ContentBaseUnit") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ContentQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ContentUnit") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DefaultVendorId") + .HasColumnType("integer"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SellingFlatPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SellingMaxPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SellingMinPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Sku") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("StockNature") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("SubCategoryId") + .HasColumnType("integer"); + + b.Property("TaxClass") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("TrackingMode") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Warranty") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("NonWarranty"); + + b.Property("WarrantyPeriodMonths") + .HasColumnType("integer"); + + b.HasKey("ItemId"); + + b.HasIndex("BaseUomId"); + + b.HasIndex("BrandId"); + + b.HasIndex("CategoryId"); + + b.HasIndex("DefaultVendorId"); + + b.HasIndex("Sku") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("SubCategoryId"); + + b.ToTable("items", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ItemReorder", b => + { + b.Property("ReorderId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReorderId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("ReorderPoint") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReorderQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("ReorderId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("ItemId", "WarehouseId") + .IsUnique(); + + b.ToTable("item_reorders", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ItemType", b => + { + b.Property("ItemTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ItemTypeId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsMeasurable") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("ItemTypeId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("item_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.JournalEntryStub", b => + { + b.Property("JournalId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("JournalId")); + + b.Property("Amount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CreditAccount") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("DebitAccount") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("SourceDocId") + .HasColumnType("integer"); + + b.Property("SourceDocType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.HasKey("JournalId"); + + b.HasIndex("SourceDocType", "SourceDocId"); + + b.ToTable("journal_entry_stubs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveBalance", b => + { + b.Property("LeaveBalanceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LeaveBalanceId")); + + b.Property("AdjustmentDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("CarriedForwardDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("EntitledDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("LeaveTypeId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("TakenDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Year") + .HasColumnType("integer"); + + b.HasKey("LeaveBalanceId"); + + b.HasIndex("LeaveTypeId"); + + b.HasIndex("EmployeeId", "LeaveTypeId", "Year") + .IsUnique(); + + b.ToTable("hr_leave_balances", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveRequest", b => + { + b.Property("LeaveRequestId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LeaveRequestId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DaysCount") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("EndDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LeaveTypeId") + .HasColumnType("integer"); + + b.Property("Reason") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("RejectionReason") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("StartDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("LeaveRequestId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("EmployeeId"); + + b.HasIndex("LeaveTypeId"); + + b.HasIndex("Status"); + + b.HasIndex("StartDate", "EndDate"); + + b.ToTable("hr_leave_requests", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveType", b => + { + b.Property("LeaveTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LeaveTypeId")); + + b.Property("AccrualPerYear") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("CarryForwardAllowed") + .HasColumnType("boolean"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CountsAsNoPay") + .HasColumnType("boolean"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsPaid") + .HasColumnType("boolean"); + + b.Property("MaxCarryForwardDays") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RequiresApproval") + .HasColumnType("boolean"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("LeaveTypeId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_leave_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoanInstallment", b => + { + b.Property("LoanInstallmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LoanInstallmentId")); + + b.Property("DueMonth") + .HasColumnType("integer"); + + b.Property("DueYear") + .HasColumnType("integer"); + + b.Property("EmployeeLoanId") + .HasColumnType("integer"); + + b.Property("InstallmentNumber") + .HasColumnType("integer"); + + b.Property("PaidAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("PayrollRunId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("ScheduledAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("LoanInstallmentId"); + + b.HasIndex("EmployeeLoanId"); + + b.HasIndex("PayrollRunId"); + + b.HasIndex("DueYear", "DueMonth"); + + b.ToTable("hr_loan_installments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoginActivity", b => + { + b.Property("LoginActivityId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LoginActivityId")); + + b.Property("DeviceLabel") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("IpAddress") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("LoginAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserAgent") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("LoginActivityId"); + + b.HasIndex("UserId", "LoginAt"); + + b.ToTable("login_activities", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NavItem", b => + { + b.Property("NavItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NavItemId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Href") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Icon") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.HasKey("NavItemId"); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("nav_items", (string)null); + + b.HasData( + new + { + NavItemId = 1, + Code = "dashboard", + Href = "/dashboard", + Label = "Dashboard", + SortOrder = 1, + Status = "Active" + }, + new + { + NavItemId = 2, + Code = "products", + Href = "/dashboard/products", + Label = "Products", + SortOrder = 2, + Status = "Active" + }, + new + { + NavItemId = 4, + Code = "procurement", + Href = "/dashboard/procurement", + Label = "Procurement", + SortOrder = 4, + Status = "Active" + }, + new + { + NavItemId = 5, + Code = "receiving", + Href = "/dashboard/receiving/grn", + Label = "Receiving", + SortOrder = 5, + Status = "Active" + }, + new + { + NavItemId = 6, + Code = "stock", + Href = "/dashboard/stock", + Label = "Stock", + SortOrder = 6, + Status = "Active" + }, + new + { + NavItemId = 7, + Code = "warehouses", + Href = "/dashboard/warehouse", + Label = "Warehouses", + SortOrder = 7, + Status = "Active" + }, + new + { + NavItemId = 8, + Code = "orders", + Href = "/dashboard/orders", + Label = "Orders", + SortOrder = 8, + Status = "Active" + }, + new + { + NavItemId = 9, + Code = "settings", + Href = "/dashboard/settings", + Label = "Settings", + SortOrder = 9, + Status = "Active" + }, + new + { + NavItemId = 10, + Code = "help", + Href = "/dashboard/help", + Label = "Help", + SortOrder = 10, + Status = "Active" + }, + new + { + NavItemId = 11, + Code = "ledgers", + Href = "/dashboard/ledgers", + Label = "Ledgers", + SortOrder = 11, + Status = "Active" + }, + new + { + NavItemId = 12, + Code = "accounts", + Href = "/dashboard/accounts", + Label = "Accounts", + SortOrder = 12, + Status = "Active" + }, + new + { + NavItemId = 13, + Code = "sales", + Href = "/dashboard/sales", + Label = "Sales", + SortOrder = 13, + Status = "Active" + }, + new + { + NavItemId = 14, + Code = "production", + Href = "/dashboard/production", + Label = "Production", + SortOrder = 14, + Status = "Active" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Notification", b => + { + b.Property("NotificationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NotificationId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("ModuleKey") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("RelatedEntityId") + .HasColumnType("integer"); + + b.Property("RelatedEntityType") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.HasKey("NotificationId"); + + b.HasIndex("CreatedAt"); + + b.ToTable("notifications", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => + { + b.Property("NotificationConfigId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.HasKey("NotificationConfigId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("notification_config", null, t => + { + t.HasCheckConstraint("ck_notification_config_singleton", "\"NotificationConfigId\" = 1"); + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfigModule", b => + { + b.Property("NotificationConfigModuleId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NotificationConfigModuleId")); + + b.Property("EmailEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("InAppEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("ModuleKey") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("NotificationConfigId") + .HasColumnType("integer"); + + b.Property("SmsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.HasKey("NotificationConfigModuleId"); + + b.HasIndex("ModuleKey") + .IsUnique(); + + b.HasIndex("NotificationConfigId"); + + b.ToTable("notification_config_modules", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationRecipient", b => + { + b.Property("NotificationRecipientId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NotificationRecipientId")); + + b.Property("IsRead") + .HasColumnType("boolean"); + + b.Property("NotificationId") + .HasColumnType("integer"); + + b.Property("ReadAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("NotificationRecipientId"); + + b.HasIndex("NotificationId"); + + b.HasIndex("UserId", "IsRead", "NotificationId"); + + b.ToTable("notification_recipients", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NumberSequence", b => + { + b.Property("SequenceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SequenceId")); + + b.Property("DocType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("doc_type"); + + b.Property("LastNumber") + .HasColumnType("integer") + .HasColumnName("last_number"); + + b.Property("Year") + .HasColumnType("integer") + .HasColumnName("year"); + + b.HasKey("SequenceId"); + + b.HasIndex("DocType", "Year") + .IsUnique(); + + b.ToTable("number_sequences", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => + { + b.Property("PayrollLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollLineId")); + + b.Property("AbsentDays") + .HasColumnType("integer"); + + b.Property("BasicSalary") + .HasColumnType("numeric(18,2)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("EpfEmployeeAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("EpfEmployerAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("EtfEmployerAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("GrossSalary") + .HasColumnType("numeric(18,2)"); + + b.Property("LateDeductionAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("LateMinutesTotal") + .HasColumnType("integer"); + + b.Property("LeaveDays") + .HasColumnType("integer"); + + b.Property("LoanDeductionAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("NetSalary") + .HasColumnType("numeric(18,2)"); + + b.Property("NoPayAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("OtMinutesTotal") + .HasColumnType("integer"); + + b.Property("OtherDeductionsAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("OvertimeAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("PayrollRunId") + .HasColumnType("integer"); + + b.Property("PresentDays") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("TaxAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("TotalAllowances") + .HasColumnType("numeric(18,2)"); + + b.Property("WorkingDays") + .HasColumnType("integer"); + + b.HasKey("PayrollLineId"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("PayrollRunId", "EmployeeId") + .IsUnique(); + + b.ToTable("hr_payroll_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLineComponent", b => + { + b.Property("PayrollLineComponentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollLineComponentId")); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("ComponentCategory") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("PayrollLineId") + .HasColumnType("integer"); + + b.Property("SalaryComponentId") + .HasColumnType("integer"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.HasKey("PayrollLineComponentId"); + + b.HasIndex("PayrollLineId"); + + b.HasIndex("SalaryComponentId"); + + b.ToTable("hr_payroll_line_components", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollRun", b => + { + b.Property("PayrollRunId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollRunId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GeneratedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GeneratedBy") + .HasColumnType("integer"); + + b.Property("LockedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("LockedBy") + .HasColumnType("integer"); + + b.Property("PeriodMonth") + .HasColumnType("integer"); + + b.Property("PeriodYear") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UnlockReason") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("UnlockedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UnlockedBy") + .HasColumnType("integer"); + + b.HasKey("PayrollRunId"); + + b.HasIndex("BranchId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("PeriodYear", "PeriodMonth", "BranchId"); + + b.ToTable("hr_payroll_runs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollStatutorySetting", b => + { + b.Property("PayrollStatutorySettingId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollStatutorySettingId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveTo") + .HasColumnType("timestamp with time zone"); + + b.Property("EpfEmployeeRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("EpfEmployerRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("EtfEmployerRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("OtMultiplierDefault") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.HasKey("PayrollStatutorySettingId"); + + b.HasIndex("EffectiveFrom"); + + b.ToTable("hr_payroll_statutory_settings", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Payslip", b => + { + b.Property("PayslipId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayslipId")); + + b.Property("GeneratedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PayrollLineId") + .HasColumnType("integer"); + + b.Property("ReleasedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReleasedBy") + .HasColumnType("integer"); + + b.HasKey("PayslipId"); + + b.HasIndex("PayrollLineId") + .IsUnique(); + + b.ToTable("hr_payslips", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Permission", b => + { + b.Property("PermissionId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PermissionId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(80) + .HasColumnType("character varying(80)"); + + b.Property("NavItemId") + .HasColumnType("integer"); + + b.Property("SubNavItemId") + .HasColumnType("integer"); + + b.HasKey("PermissionId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("NavItemId"); + + b.HasIndex("SubNavItemId"); + + b.ToTable("permissions", (string)null); + + b.HasData( + new + { + PermissionId = 1, + Code = "NAV:dashboard", + NavItemId = 1 + }, + new + { + PermissionId = 2, + Code = "NAV:products", + NavItemId = 2 + }, + new + { + PermissionId = 3, + Code = "NAV:procurement.vendors", + SubNavItemId = 30 + }, + new + { + PermissionId = 4, + Code = "NAV:procurement", + NavItemId = 4 + }, + new + { + PermissionId = 5, + Code = "NAV:receiving", + NavItemId = 5 + }, + new + { + PermissionId = 6, + Code = "NAV:stock", + NavItemId = 6 + }, + new + { + PermissionId = 7, + Code = "NAV:warehouses", + NavItemId = 7 + }, + new + { + PermissionId = 8, + Code = "NAV:orders", + NavItemId = 8 + }, + new + { + PermissionId = 9, + Code = "NAV:settings", + NavItemId = 9 + }, + new + { + PermissionId = 10, + Code = "NAV:help", + NavItemId = 10 + }, + new + { + PermissionId = 11, + Code = "NAV:products.item", + SubNavItemId = 1 + }, + new + { + PermissionId = 12, + Code = "NAV:products.category", + SubNavItemId = 2 + }, + new + { + PermissionId = 13, + Code = "NAV:products.brand", + SubNavItemId = 3 + }, + new + { + PermissionId = 14, + Code = "NAV:products.item-type", + SubNavItemId = 4 + }, + new + { + PermissionId = 15, + Code = "NAV:products.uom", + SubNavItemId = 5 + }, + new + { + PermissionId = 16, + Code = "NAV:products.configuration", + SubNavItemId = 6 + }, + new + { + PermissionId = 17, + Code = "NAV:settings.roles", + SubNavItemId = 7 + }, + new + { + PermissionId = 18, + Code = "NAV:settings.users", + SubNavItemId = 8 + }, + new + { + PermissionId = 28, + Code = "NAV:procurement.requisitions", + SubNavItemId = 17 + }, + new + { + PermissionId = 29, + Code = "NAV:procurement.rfqs", + SubNavItemId = 18 + }, + new + { + PermissionId = 30, + Code = "NAV:procurement.purchase-orders", + SubNavItemId = 19 + }, + new + { + PermissionId = 31, + Code = "NAV:procurement.purchase-returns", + SubNavItemId = 20 + }, + new + { + PermissionId = 19, + Code = "NAV:ledgers", + NavItemId = 11 + }, + new + { + PermissionId = 20, + Code = "NAV:ledgers.trial-balance", + SubNavItemId = 9 + }, + new + { + PermissionId = 21, + Code = "NAV:ledgers.balance-sheet", + SubNavItemId = 10 + }, + new + { + PermissionId = 22, + Code = "NAV:ledgers.general-ledger", + SubNavItemId = 11 + }, + new + { + PermissionId = 23, + Code = "NAV:ledgers.profit-and-loss", + SubNavItemId = 12 + }, + new + { + PermissionId = 24, + Code = "NAV:ledgers.cash-flow", + SubNavItemId = 13 + }, + new + { + PermissionId = 25, + Code = "NAV:ledgers.budget-vs-actual", + SubNavItemId = 14 + }, + new + { + PermissionId = 27, + Code = "NAV:ledgers.tax-report", + SubNavItemId = 16 + }, + new + { + PermissionId = 26, + Code = "NAV:accounts.bank-accounts", + SubNavItemId = 15 + }, + new + { + PermissionId = 32, + Code = "NAV:accounts", + NavItemId = 12 + }, + new + { + PermissionId = 33, + Code = "NAV:accounts.cheque-books", + SubNavItemId = 21 + }, + new + { + PermissionId = 34, + Code = "NAV:accounts.received-cheques", + SubNavItemId = 22 + }, + new + { + PermissionId = 35, + Code = "NAV:production", + NavItemId = 14 + }, + new + { + PermissionId = 36, + Code = "NAV:production.templates", + SubNavItemId = 27 + }, + new + { + PermissionId = 37, + Code = "NAV:production.runs", + SubNavItemId = 25 + }, + new + { + PermissionId = 38, + Code = "NAV:production.produced", + SubNavItemId = 26 + }, + new + { + PermissionId = 39, + Code = "NAV:procurement.purchase-invoices", + SubNavItemId = 28 + }, + new + { + PermissionId = 40, + Code = "NAV:settings.branches", + SubNavItemId = 29 + }, + new + { + PermissionId = 41, + Code = "NAV:stock.ledger", + SubNavItemId = 31 + }, + new + { + PermissionId = 42, + Code = "NAV:stock.enquiry", + SubNavItemId = 32 + }, + new + { + PermissionId = 43, + Code = "NAV:stock.valuation", + SubNavItemId = 33 + }, + new + { + PermissionId = 44, + Code = "NAV:stock.transfers", + SubNavItemId = 34 + }, + new + { + PermissionId = 45, + Code = "NAV:stock.adjustments", + SubNavItemId = 35 + }, + new + { + PermissionId = 46, + Code = "NAV:stock.counts", + SubNavItemId = 36 + }, + new + { + PermissionId = 47, + Code = "NAV:stock.reorder-alerts", + SubNavItemId = 37 + }, + new + { + PermissionId = 48, + Code = "NAV:stock.wastage", + SubNavItemId = 38 + }, + new + { + PermissionId = 49, + Code = "NAV:sales.bundle-templates", + SubNavItemId = 23 + }, + new + { + PermissionId = 50, + Code = "NAV:sales.invoices", + SubNavItemId = 40 + }, + new + { + PermissionId = 51, + Code = "NAV:sales.free-issues", + SubNavItemId = 41 + }, + new + { + PermissionId = 52, + Code = "NAV:sales.day-end", + SubNavItemId = 42 + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PoLine", b => + { + b.Property("PoLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PoLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("PoId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyReceived") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Tax") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("PoLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("PoId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("po_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductConfig", b => + { + b.Property("ConfigId") + .HasColumnType("integer"); + + b.Property("BatchListsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("BrandsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("ItemTypesEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SellingPricesEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("SerialNumbersEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("SubcategoriesEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.Property("WarrantyPeriodsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.HasKey("ConfigId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("product_config", null, t => + { + t.HasCheckConstraint("ck_product_config_singleton", "\"ConfigId\" = 1"); + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b => + { + b.Property("RunId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunId")); + + b.Property("CancelReasonCodeId") + .HasColumnType("integer"); + + b.Property("CompletedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("OutputBinId") + .HasColumnType("integer"); + + b.Property("ReworkCount") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("ScaleFactor") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("TargetQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TemplateId") + .HasColumnType("integer"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("RunId"); + + b.HasIndex("CancelReasonCodeId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("OutputBinId"); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("TemplateId", "Status"); + + b.ToTable("production_runs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionTemplate", b => + { + b.Property("TemplateId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TemplateId")); + + b.Property("Annotations") + .HasColumnType("jsonb"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("TemplateId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("CreatedBy"); + + b.HasIndex("Status"); + + b.ToTable("production_templates", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", b => + { + b.Property("PurchaseInvoiceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PurchaseInvoiceId")); + + b.Property("BalanceAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VatTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.Property("VendorInvoiceDate") + .HasColumnType("timestamp with time zone"); + + b.Property("VendorInvoiceNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("VendorSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("VendorSnapshotTaxNo") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("PurchaseInvoiceId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("VendorId"); + + b.HasIndex("VendorId", "VendorInvoiceNo"); + + b.ToTable("purchase_invoices", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoiceLine", b => + { + b.Property("PurchaseInvoiceLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PurchaseInvoiceLineId")); + + b.Property("GrnId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PurchaseInvoiceId") + .HasColumnType("integer"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("VatTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("PurchaseInvoiceLineId"); + + b.HasIndex("GrnId") + .IsUnique(); + + b.HasIndex("PurchaseInvoiceId"); + + b.ToTable("purchase_invoice_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoicePayment", b => + { + b.Property("PurchaseInvoicePaymentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PurchaseInvoicePaymentId")); + + b.Property("Amount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BankAccountName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("GlBankAccountId") + .HasColumnType("bigint"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PaymentDate") + .HasColumnType("timestamp with time zone"); + + b.Property("PurchaseInvoiceId") + .HasColumnType("integer"); + + b.Property("Reference") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("PurchaseInvoicePaymentId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("PurchaseInvoiceId"); + + b.ToTable("purchase_invoice_payments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => + { + b.Property("PoId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PoId")); + + b.Property("ApprovalRequired") + .HasColumnType("boolean"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RequisitionId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.HasKey("PoId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("RequisitionId"); + + b.HasIndex("Status"); + + b.HasIndex("VendorId"); + + b.ToTable("purchase_orders", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturn", b => + { + b.Property("ReturnId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReasonCodeId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("ReturnId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("ReasonCodeId"); + + b.HasIndex("VendorId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("purchase_returns", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturnLine", b => + { + b.Property("ReturnLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnLineId")); + + b.Property("GrnLineId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReturnId") + .HasColumnType("integer"); + + b.HasKey("ReturnLineId"); + + b.HasIndex("GrnLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("ReturnId"); + + b.ToTable("purchase_return_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ReasonCode", b => + { + b.Property("ReasonCodeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReasonCodeId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Context") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.HasKey("ReasonCodeId"); + + b.HasIndex("Context", "Code") + .IsUnique(); + + b.ToTable("reason_codes", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => + { + b.Property("RequisitionId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RequisitionId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RequestedBy") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("RequisitionId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("RequestedBy"); + + b.HasIndex("Status"); + + b.ToTable("requisitions", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RequisitionLine", b => + { + b.Property("ReqLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReqLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RequiredBy") + .HasColumnType("date"); + + b.Property("RequisitionId") + .HasColumnType("integer"); + + b.HasKey("ReqLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RequisitionId"); + + b.ToTable("requisition_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => + { + b.Property("RfqId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RfqId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RequisitionId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("RfqId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("RequisitionId"); + + b.ToTable("rfqs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RfqLine", b => + { + b.Property("RfqLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RfqLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RfqId") + .HasColumnType("integer"); + + b.HasKey("RfqLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RfqId"); + + b.ToTable("rfq_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Role", b => + { + b.Property("RoleId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RoleId")); + + b.Property("AuthRoleId") + .HasColumnType("uuid") + .HasColumnName("auth_role_id"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsSystemRole") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("RoleId"); + + b.HasIndex("AuthRoleId") + .IsUnique(); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("roles", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RolePermission", b => + { + b.Property("RoleId") + .HasColumnType("integer"); + + b.Property("PermissionId") + .HasColumnType("integer"); + + b.HasKey("RoleId", "PermissionId"); + + b.HasIndex("PermissionId"); + + b.ToTable("role_permissions", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunEdge", b => + { + b.Property("RunEdgeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunEdgeId")); + + b.Property("ChildRunStageId") + .HasColumnType("integer"); + + b.Property("ParentRunStageId") + .HasColumnType("integer"); + + b.Property("RunId") + .HasColumnType("integer"); + + b.HasKey("RunEdgeId"); + + b.HasIndex("ChildRunStageId"); + + b.HasIndex("RunId"); + + b.HasIndex("ParentRunStageId", "ChildRunStageId") + .IsUnique(); + + b.ToTable("run_edges", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStage", b => + { + b.Property("RunStageId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunStageId")); + + b.Property("ActualEndAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ActualStartAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EstimatedMinutes") + .HasColumnType("integer"); + + b.Property("FieldDefs") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("FieldValues") + .HasColumnType("jsonb"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("PosX") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PosY") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RoleLabel") + .HasMaxLength(60) + .HasColumnType("character varying(60)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("RunId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("TemplateStageId") + .HasColumnType("integer"); + + b.HasKey("RunStageId"); + + b.HasIndex("TemplateStageId"); + + b.HasIndex("RunId", "Status"); + + b.ToTable("run_stages", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageEvent", b => + { + b.Property("EventId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EventId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Note") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Payload") + .HasColumnType("jsonb"); + + b.Property("RunId") + .HasColumnType("integer"); + + b.Property("RunStageId") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("EventId"); + + b.HasIndex("RunStageId"); + + b.HasIndex("UserId"); + + b.HasIndex("RunId", "EventId"); + + b.ToTable("run_stage_events", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageInput", b => + { + b.Property("RunInputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunInputId")); + + b.Property("ConsumedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ConsumedValue") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DeliveredQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("FromRunOutputId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("PlannedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyUnit") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ReturnedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReturnedValue") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RunStageId") + .HasColumnType("integer"); + + b.Property("Source") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("RunInputId"); + + b.HasIndex("FromRunOutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RunStageId"); + + b.ToTable("run_stage_inputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageOutput", b => + { + b.Property("RunOutputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunOutputId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("PlannedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ProducedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RunStageId") + .HasColumnType("integer"); + + b.Property("ScrapReasonCodeId") + .HasColumnType("integer"); + + b.Property("ScrappedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TransferredQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UomId") + .HasColumnType("integer"); + + b.HasKey("RunOutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RunStageId"); + + b.HasIndex("ScrapReasonCodeId"); + + b.HasIndex("UomId"); + + b.ToTable("run_stage_outputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalaryComponent", b => + { + b.Property("SalaryComponentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalaryComponentId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ComponentType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsEpfEtfApplicable") + .HasColumnType("boolean"); + + b.Property("IsTaxable") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("SalaryComponentId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_salary_components", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesDayEnd", b => + { + b.Property("SalesDayEndId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesDayEndId")); + + b.Property("BundleCount") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("BusinessDate") + .HasColumnType("date"); + + b.Property("CashierUserId") + .HasColumnType("integer"); + + b.Property("ClosedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ClosedBy") + .HasColumnType("integer"); + + b.Property("CostOfGoodsSold") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SlipCount") + .HasColumnType("integer"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("SalesDayEndId"); + + b.HasIndex("ClosedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("CashierUserId", "BusinessDate") + .IsUnique(); + + b.ToTable("sales_day_ends", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoice", b => + { + b.Property("SalesInvoiceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesInvoiceId")); + + b.Property("BalanceAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("CreatorUserId") + .HasColumnType("integer"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("CustomerSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CustomerSnapshotTaxNo") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("InvoiceDate") + .HasColumnType("timestamp with time zone"); + + b.Property("InvoiceNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("InvoiceType") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("B2C"); + + b.Property("NetPayable") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RoundOff") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesInvoiceId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatorUserId"); + + b.HasIndex("CustomerId"); + + b.HasIndex("InvoiceDate"); + + b.HasIndex("InvoiceNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_invoices", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoiceLine", b => + { + b.Property("SalesInvoiceLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesInvoiceLineId")); + + b.Property("BaseCost") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DiscountAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DiscountMode") + .HasColumnType("integer"); + + b.Property("DiscountPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("FreeQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("IsFreeIssue") + .HasColumnType("boolean"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("NetUnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ParentLineId") + .HasColumnType("integer"); + + b.Property("PriceSource") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SalesInvoiceId") + .HasColumnType("integer"); + + b.Property("TaxAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesInvoiceLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SalesInvoiceId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_invoice_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoicePayment", b => + { + b.Property("SalesInvoicePaymentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesInvoicePaymentId")); + + b.Property("Amount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BankAccountName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("GlBankAccountId") + .HasColumnType("bigint"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PaymentDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Reference") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("SalesInvoiceId") + .HasColumnType("integer"); + + b.HasKey("SalesInvoicePaymentId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("SalesInvoiceId"); + + b.ToTable("sales_invoice_payments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturn", b => + { + b.Property("ReturnId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReasonCodeId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("ReturnId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("CustomerId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("ReasonCodeId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_returns", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturnLine", b => + { + b.Property("ReturnLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReturnId") + .HasColumnType("integer"); + + b.Property("SalesInvoiceLineId") + .HasColumnType("integer"); + + b.HasKey("ReturnLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("ReturnId"); + + b.HasIndex("SalesInvoiceLineId"); + + b.ToTable("sales_return_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlip", b => + { + b.Property("SalesSlipId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesSlipId")); + + b.Property("BalanceAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CashierUserId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("CustomerSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DayEndId") + .HasColumnType("integer"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SlipDate") + .HasColumnType("timestamp with time zone"); + + b.Property("SlipNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesSlipId"); + + b.HasIndex("CashierUserId"); + + b.HasIndex("CustomerId"); + + b.HasIndex("DayEndId"); + + b.HasIndex("SlipDate"); + + b.HasIndex("SlipNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_slips", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlipLine", b => + { + b.Property("SalesSlipLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesSlipLineId")); + + b.Property("BaseCost") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DiscountAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DiscountMode") + .HasColumnType("integer"); + + b.Property("DiscountPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("FreeQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("IsFreeIssue") + .HasColumnType("boolean"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("NetUnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ParentLineId") + .HasColumnType("integer"); + + b.Property("PriceSource") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SalesSlipId") + .HasColumnType("integer"); + + b.Property("TaxAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesSlipLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SalesSlipId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_slip_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Serial", b => + { + b.Property("SerialId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SerialId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("SerialNo") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("SerialId"); + + b.HasIndex("ItemId", "SerialNo") + .IsUnique(); + + b.ToTable("serials", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageEdge", b => + { + b.Property("EdgeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EdgeId")); + + b.Property("ChildStageId") + .HasColumnType("integer"); + + b.Property("ParentStageId") + .HasColumnType("integer"); + + b.Property("TemplateId") + .HasColumnType("integer"); + + b.HasKey("EdgeId"); + + b.HasIndex("ChildStageId"); + + b.HasIndex("TemplateId"); + + b.HasIndex("ParentStageId", "ChildStageId") + .IsUnique(); + + b.ToTable("stage_edges", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageInput", b => + { + b.Property("InputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("InputId")); + + b.Property("FromOutputId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyPerBatch") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyUnit") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Source") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("StageId") + .HasColumnType("integer"); + + b.HasKey("InputId"); + + b.HasIndex("FromOutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("StageId"); + + b.ToTable("stage_inputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageOutput", b => + { + b.Property("OutputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("OutputId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("QtyPerBatch") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("StageId") + .HasColumnType("integer"); + + b.Property("UomId") + .HasColumnType("integer"); + + b.HasKey("OutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("StageId"); + + b.HasIndex("UomId"); + + b.ToTable("stage_outputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustment", b => + { + b.Property("AdjustmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AdjustmentId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReasonCodeId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("AdjustmentId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("ReasonCodeId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("stock_adjustments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustmentLine", b => + { + b.Property("AdjLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AdjLineId")); + + b.Property("AdjustmentId") + .HasColumnType("integer"); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyDelta") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.HasKey("AdjLineId"); + + b.HasIndex("AdjustmentId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SerialId"); + + b.ToTable("stock_adjustment_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCount", b => + { + b.Property("CountId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CountId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CountType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("CountId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("stock_counts", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCountLine", b => + { + b.Property("CountLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CountLineId")); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("CountId") + .HasColumnType("integer"); + + b.Property("CountedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("SystemQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Variance") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("CountLineId"); + + b.HasIndex("BinId"); + + b.HasIndex("CountId"); + + b.HasIndex("ItemId"); + + b.ToTable("stock_count_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLayer", b => + { + b.Property("LayerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LayerId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("GrnLineId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyReceived") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyRemaining") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReceiptDate") + .HasColumnType("timestamp with time zone"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("LayerId"); + + b.HasIndex("BatchId"); + + b.HasIndex("GrnLineId"); + + b.HasIndex("SerialId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("ItemId", "WarehouseId", "ReceiptDate", "LayerId"); + + b.ToTable("stock_layers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLedger", b => + { + b.Property("LedgerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LedgerId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Direction") + .IsRequired() + .HasMaxLength(5) + .HasColumnType("character varying(5)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyBase") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RunningBalance") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("SourceDocId") + .HasColumnType("integer"); + + b.Property("SourceDocType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.Property("Value") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("LedgerId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("SerialId"); + + b.HasIndex("UserId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("SourceDocType", "SourceDocId"); + + b.HasIndex("ItemId", "WarehouseId", "CreatedAt"); + + b.HasIndex("ItemId", "WarehouseId", "LedgerId"); + + b.ToTable("stock_ledger", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransfer", b => + { + b.Property("TransferId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TransferId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DestWarehouseId") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SrcWarehouseId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("TransferId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DestWarehouseId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("SrcWarehouseId"); + + b.HasIndex("Status"); + + b.ToTable("stock_transfers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransferLine", b => + { + b.Property("TransferLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TransferLineId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("DestBinId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyReceived") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("SrcBinId") + .HasColumnType("integer"); + + b.Property("TransferId") + .HasColumnType("integer"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.HasKey("TransferLineId"); + + b.HasIndex("BatchId"); + + b.HasIndex("DestBinId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SerialId"); + + b.HasIndex("SrcBinId"); + + b.HasIndex("TransferId"); + + b.ToTable("stock_transfer_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubCategory", b => + { + b.Property("SubCategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SubCategoryId")); + + b.Property("CategoryId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("SubCategoryId"); + + b.HasIndex("Status"); + + b.HasIndex("CategoryId", "Name") + .IsUnique(); + + b.ToTable("subcategories", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubNavItem", b => + { + b.Property("SubNavItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SubNavItemId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Href") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Icon") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("NavItemId") + .HasColumnType("integer"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.HasKey("SubNavItemId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("NavItemId"); + + b.ToTable("sub_nav_items", (string)null); + + b.HasData( + new + { + SubNavItemId = 1, + Code = "products.item", + Href = "/dashboard/products", + Label = "Item", + NavItemId = 2, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 2, + Code = "products.category", + Href = "/dashboard/products/categories", + Label = "Category", + NavItemId = 2, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 3, + Code = "products.brand", + Href = "/dashboard/products/brands", + Label = "Brand", + NavItemId = 2, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 4, + Code = "products.item-type", + Href = "/dashboard/products/item-types", + Label = "Item Type", + NavItemId = 2, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 5, + Code = "products.uom", + Href = "/dashboard/products/uoms", + Label = "UOM", + NavItemId = 2, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 6, + Code = "products.configuration", + Href = "/dashboard/products/settings", + Label = "Configuration", + NavItemId = 2, + SortOrder = 6, + Status = "Active" + }, + new + { + SubNavItemId = 29, + Code = "settings.branches", + Href = "/dashboard/settings/branches", + Label = "Branches", + NavItemId = 9, + SortOrder = 0, + Status = "Active" + }, + new + { + SubNavItemId = 7, + Code = "settings.roles", + Href = "/dashboard/settings/roles", + Label = "Roles", + NavItemId = 9, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 8, + Code = "settings.users", + Href = "/dashboard/settings/users", + Label = "Users", + NavItemId = 9, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 24, + Code = "settings.notification-config", + Href = "/dashboard/settings/notification-config", + Label = "Notification Config", + NavItemId = 9, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 40, + Code = "sales.invoices", + Href = "/dashboard/sales/invoices", + Label = "Sales", + NavItemId = 13, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 23, + Code = "sales.bundle-templates", + Href = "/dashboard/sales/bundles/templates", + Label = "Bundle Templates", + NavItemId = 13, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 41, + Code = "sales.free-issues", + Href = "/dashboard/sales/free-issues", + Label = "Free Issues", + NavItemId = 13, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 42, + Code = "sales.day-end", + Href = "/dashboard/sales/day-end", + Label = "Day End", + NavItemId = 13, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 30, + Code = "procurement.vendors", + Href = "/dashboard/vendors", + Label = "Vendors", + NavItemId = 4, + SortOrder = 0, + Status = "Active" + }, + new + { + SubNavItemId = 17, + Code = "procurement.requisitions", + Href = "/dashboard/procurement/requisitions", + Label = "Requisitions", + NavItemId = 4, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 18, + Code = "procurement.rfqs", + Href = "/dashboard/procurement/rfqs", + Label = "RFQs", + NavItemId = 4, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 19, + Code = "procurement.purchase-orders", + Href = "/dashboard/procurement/purchase-orders", + Label = "Purchase Orders", + NavItemId = 4, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 20, + Code = "procurement.purchase-returns", + Href = "/dashboard/procurement/purchase-returns", + Label = "Purchase Returns", + NavItemId = 4, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 28, + Code = "procurement.purchase-invoices", + Href = "/dashboard/procurement/purchase-invoices", + Label = "Purchase Invoices", + NavItemId = 4, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 9, + Code = "ledgers.trial-balance", + Href = "/dashboard/ledgers/trial-balance", + Label = "Trial Balance", + NavItemId = 11, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 10, + Code = "ledgers.balance-sheet", + Href = "/dashboard/ledgers/balance-sheet", + Label = "Balance Sheet", + NavItemId = 11, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 11, + Code = "ledgers.general-ledger", + Href = "/dashboard/ledgers/general-ledger", + Label = "General Ledger", + NavItemId = 11, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 12, + Code = "ledgers.profit-and-loss", + Href = "/dashboard/ledgers/profit-and-loss", + Label = "Profit & Loss", + NavItemId = 11, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 13, + Code = "ledgers.cash-flow", + Href = "/dashboard/ledgers/cash-flow", + Label = "Cash Flow", + NavItemId = 11, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 14, + Code = "ledgers.budget-vs-actual", + Href = "/dashboard/ledgers/budget-vs-actual", + Label = "Budget vs Actual", + NavItemId = 11, + SortOrder = 6, + Status = "Active" + }, + new + { + SubNavItemId = 16, + Code = "ledgers.tax-report", + Href = "/dashboard/ledgers/tax-report", + Label = "Tax Report", + NavItemId = 11, + SortOrder = 7, + Status = "Active" + }, + new + { + SubNavItemId = 15, + Code = "accounts.bank-accounts", + Href = "/dashboard/accounts/bank-accounts", + Label = "Cash / Bank Accounts", + NavItemId = 12, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 21, + Code = "accounts.cheque-books", + Href = "/dashboard/accounts/cheque-books", + Label = "Cheque Books", + NavItemId = 12, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 22, + Code = "accounts.received-cheques", + Href = "/dashboard/accounts/received-cheques", + Label = "Received Cheques", + NavItemId = 12, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 27, + Code = "production.templates", + Href = "/dashboard/production/templates", + Label = "Templates", + NavItemId = 14, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 25, + Code = "production.runs", + Href = "/dashboard/production/runs", + Label = "Runs", + NavItemId = 14, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 26, + Code = "production.produced", + Href = "/dashboard/production/produced", + Label = "Produced", + NavItemId = 14, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 31, + Code = "stock.ledger", + Href = "/dashboard/stock/ledger", + Label = "Stock Ledger", + NavItemId = 6, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 32, + Code = "stock.enquiry", + Href = "/dashboard/stock/enquiry", + Label = "Stock Enquiry", + NavItemId = 6, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 33, + Code = "stock.valuation", + Href = "/dashboard/stock/valuation", + Label = "Valuation", + NavItemId = 6, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 34, + Code = "stock.transfers", + Href = "/dashboard/stock/transfers", + Label = "Transfers", + NavItemId = 6, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 35, + Code = "stock.adjustments", + Href = "/dashboard/stock/adjustments", + Label = "Adjustments", + NavItemId = 6, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 36, + Code = "stock.counts", + Href = "/dashboard/stock/counts", + Label = "Counts", + NavItemId = 6, + SortOrder = 6, + Status = "Active" + }, + new + { + SubNavItemId = 37, + Code = "stock.reorder-alerts", + Href = "/dashboard/stock/reorder-alerts", + Label = "Reorder Alerts", + NavItemId = 6, + SortOrder = 7, + Status = "Active" + }, + new + { + SubNavItemId = 38, + Code = "stock.wastage", + Href = "/dashboard/stock/wastage", + Label = "Wastage", + NavItemId = 6, + SortOrder = 8, + Status = "Active" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicket", b => + { + b.Property("TicketId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TicketId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Subject") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.HasKey("TicketId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("Status"); + + b.ToTable("support_tickets", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicketMessage", b => + { + b.Property("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("MessageId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsFromAdmin") + .HasColumnType("boolean"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("SenderUserId") + .HasColumnType("integer"); + + b.Property("TicketId") + .HasColumnType("integer"); + + b.HasKey("MessageId"); + + b.HasIndex("TicketId", "CreatedAt"); + + b.ToTable("support_ticket_messages", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TaxSlab", b => + { + b.Property("TaxSlabId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TaxSlabId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveTo") + .HasColumnType("timestamp with time zone"); + + b.Property("LowerBound") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("Rate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("UpperBound") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.HasKey("TaxSlabId"); + + b.HasIndex("EffectiveFrom"); + + b.ToTable("hr_tax_slabs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => + { + b.Property("StageId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("StageId")); + + b.Property("EstimatedMinutes") + .HasColumnType("integer"); + + b.Property("FieldDefs") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("PosX") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PosY") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RoleLabel") + .HasMaxLength(60) + .HasColumnType("character varying(60)"); + + b.Property("TemplateId") + .HasColumnType("integer"); + + b.HasKey("StageId"); + + b.HasIndex("TemplateId"); + + b.ToTable("template_stages", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Uom", b => + { + b.Property("UomId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("UomId")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("UomId"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("uoms", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.User", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("UserId")); + + b.Property("AuthUserId") + .HasColumnType("uuid") + .HasColumnName("auth_user_id"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Email") + .HasMaxLength(320) + .HasColumnType("character varying(320)"); + + b.Property("RoleId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("UserId"); + + b.HasIndex("AuthUserId") + .IsUnique(); + + b.HasIndex("Email") + .IsUnique(); + + b.HasIndex("RoleId"); + + b.HasIndex("Username") + .IsUnique(); + + b.ToTable("users", (string)null); + + b.HasData( + new + { + UserId = 1, + DisplayName = "System", + Status = "Active", + Username = "system" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Vendor", b => + { + b.Property("VendorId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("VendorId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Currency") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(3) + .HasColumnType("character varying(3)") + .HasDefaultValue("LKR"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TaxReg") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Terms") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("VendorId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("vendors", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => + { + b.Property("QuotationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("QuotationId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("RfqId") + .HasColumnType("integer"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.HasKey("QuotationId"); + + b.HasIndex("VendorId"); + + b.HasIndex("RfqId", "VendorId") + .IsUnique(); + + b.ToTable("vendor_quotations", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotationLine", b => + { + b.Property("QuotationLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("QuotationLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LeadDays") + .HasColumnType("integer"); + + b.Property("QuotationId") + .HasColumnType("integer"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("QuotationLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("QuotationId"); + + b.ToTable("vendor_quotation_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Warehouse", b => + { + b.Property("WarehouseId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("WarehouseId")); + + b.Property("Address") + .HasColumnType("text"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Phone") + .HasColumnType("text"); + + b.HasKey("WarehouseId"); + + b.HasIndex("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("warehouses", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.WorkShift", b => + { + b.Property("WorkShiftId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("WorkShiftId")); + + b.Property("BreakMinutes") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EndTime") + .HasColumnType("interval"); + + b.Property("GraceMinutes") + .HasColumnType("integer"); + + b.Property("IsOvernight") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("OtMultiplier") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("StandardWorkingMinutes") + .HasColumnType("integer"); + + b.Property("StartTime") + .HasColumnType("interval"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WorkingDaysMask") + .HasColumnType("integer"); + + b.HasKey("WorkShiftId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_work_shifts", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceRecord", b => + { + b.HasOne("ERPCore.Domain.Entities.AttendanceUploadBatch", "AttendanceUploadBatch") + .WithMany() + .HasForeignKey("AttendanceUploadBatchId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.WorkShift", "WorkShift") + .WithMany() + .HasForeignKey("WorkShiftId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("AttendanceUploadBatch"); + + b.Navigation("Employee"); + + b.Navigation("WorkShift"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AuditLog", b => + { + b.HasOne("ERPCore.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Batch", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Bin", b => + { + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany("Bins") + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BranchConfig", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSale", b => + { + b.HasOne("ERPCore.Domain.Entities.BundleSaleTemplate", "BundleSaleTemplate") + .WithMany() + .HasForeignKey("BundleSaleTemplateId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "CashierUser") + .WithMany() + .HasForeignKey("CashierUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesDayEnd", "DayEnd") + .WithMany("BundleSales") + .HasForeignKey("DayEndId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BundleSaleTemplate"); + + b.Navigation("CashierUser"); + + b.Navigation("Customer"); + + b.Navigation("DayEnd"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleLine", b => + { + b.HasOne("ERPCore.Domain.Entities.BundleSale", "BundleSale") + .WithMany("Lines") + .HasForeignKey("BundleSaleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BundleSale"); + + b.Navigation("Item"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplateLine", b => + { + b.HasOne("ERPCore.Domain.Entities.BundleSaleTemplate", "BundleSaleTemplate") + .WithMany("Lines") + .HasForeignKey("BundleSaleTemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BundleSaleTemplate"); + + b.Navigation("Item"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Customer", b => + { + b.HasOne("ERPCore.Domain.Entities.Warehouse", "DefaultWarehouse") + .WithMany() + .HasForeignKey("DefaultWarehouseId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("DefaultWarehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Department", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Employee", "HeadEmployee") + .WithMany() + .HasForeignKey("HeadEmployeeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Department", "ParentDepartment") + .WithMany() + .HasForeignKey("ParentDepartmentId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Branch"); + + b.Navigation("HeadEmployee"); + + b.Navigation("ParentDepartment"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Employee", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Department", "Department") + .WithMany() + .HasForeignKey("DepartmentId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Designation", "Designation") + .WithMany() + .HasForeignKey("DesignationId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.EmploymentType", "EmploymentType") + .WithMany() + .HasForeignKey("EmploymentTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Employee", "ReportingManager") + .WithMany() + .HasForeignKey("ReportingManagerId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithOne() + .HasForeignKey("ERPCore.Domain.Entities.Employee", "UserId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.WorkShift", "WorkShift") + .WithMany() + .HasForeignKey("WorkShiftId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Department"); + + b.Navigation("Designation"); + + b.Navigation("EmploymentType"); + + b.Navigation("ReportingManager"); + + b.Navigation("User"); + + b.Navigation("WorkShift"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeBankDetail", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeDocument", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.HrDocumentType", "HrDocumentType") + .WithMany() + .HasForeignKey("HrDocumentTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("HrDocumentType"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeLoan", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructure", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructureLine", b => + { + b.HasOne("ERPCore.Domain.Entities.EmployeeSalaryStructure", "EmployeeSalaryStructure") + .WithMany("Lines") + .HasForeignKey("EmployeeSalaryStructureId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalaryComponent", "SalaryComponent") + .WithMany() + .HasForeignKey("SalaryComponentId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("EmployeeSalaryStructure"); + + b.Navigation("SalaryComponent"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Grn", 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.HasOne("ERPCore.Domain.Entities.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("PoId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.PurchaseInvoice", "PurchaseInvoice") + .WithMany() + .HasForeignKey("PurchaseInvoiceId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("PurchaseInvoice"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Vendor"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", "Batch") + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", "Bin") + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Grn", "Grn") + .WithMany("Lines") + .HasForeignKey("GrnId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PoLine", "PoLine") + .WithMany() + .HasForeignKey("PoLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Batch"); + + b.Navigation("Bin"); + + b.Navigation("Grn"); + + b.Navigation("Item"); + + b.Navigation("PoLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLineWarrantyNumber", b => + { + b.HasOne("ERPCore.Domain.Entities.GrnLine", "GrnLine") + .WithMany("WarrantyNumbers") + .HasForeignKey("GrnLineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GrnLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Item", b => + { + b.HasOne("ERPCore.Domain.Entities.Uom", "BaseUom") + .WithMany() + .HasForeignKey("BaseUomId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Brand", "Brand") + .WithMany() + .HasForeignKey("BrandId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Category", "Category") + .WithMany() + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "DefaultVendor") + .WithMany() + .HasForeignKey("DefaultVendorId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.SubCategory", "SubCategory") + .WithMany() + .HasForeignKey("SubCategoryId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("BaseUom"); + + b.Navigation("Brand"); + + b.Navigation("Category"); + + b.Navigation("DefaultVendor"); + + b.Navigation("SubCategory"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ItemReorder", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany("ReorderSettings") + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveBalance", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.LeaveType", "LeaveType") + .WithMany() + .HasForeignKey("LeaveTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("LeaveType"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveRequest", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.LeaveType", "LeaveType") + .WithMany() + .HasForeignKey("LeaveTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("LeaveType"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoanInstallment", b => + { + b.HasOne("ERPCore.Domain.Entities.EmployeeLoan", "EmployeeLoan") + .WithMany("Installments") + .HasForeignKey("EmployeeLoanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PayrollRun", "PayrollRun") + .WithMany() + .HasForeignKey("PayrollRunId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("EmployeeLoan"); + + b.Navigation("PayrollRun"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoginActivity", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfigModule", b => + { + b.HasOne("ERPCore.Domain.Entities.NotificationConfig", "NotificationConfig") + .WithMany("Modules") + .HasForeignKey("NotificationConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("NotificationConfig"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationRecipient", b => + { + b.HasOne("ERPCore.Domain.Entities.Notification", "Notification") + .WithMany("Recipients") + .HasForeignKey("NotificationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Notification"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PayrollRun", "PayrollRun") + .WithMany("Lines") + .HasForeignKey("PayrollRunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("PayrollRun"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLineComponent", b => + { + b.HasOne("ERPCore.Domain.Entities.PayrollLine", "PayrollLine") + .WithMany("Components") + .HasForeignKey("PayrollLineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalaryComponent", "SalaryComponent") + .WithMany() + .HasForeignKey("SalaryComponentId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("PayrollLine"); + + b.Navigation("SalaryComponent"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollRun", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Branch"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Payslip", b => + { + b.HasOne("ERPCore.Domain.Entities.PayrollLine", "PayrollLine") + .WithOne() + .HasForeignKey("ERPCore.Domain.Entities.Payslip", "PayrollLineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PayrollLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Permission", b => + { + b.HasOne("ERPCore.Domain.Entities.NavItem", "NavItem") + .WithMany() + .HasForeignKey("NavItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ERPCore.Domain.Entities.SubNavItem", "SubNavItem") + .WithMany() + .HasForeignKey("SubNavItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("NavItem"); + + b.Navigation("SubNavItem"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PoLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseOrder", "PurchaseOrder") + .WithMany("Lines") + .HasForeignKey("PoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductConfig", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b => + { + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "CancelReason") + .WithMany() + .HasForeignKey("CancelReasonCodeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Bin", "OutputBin") + .WithMany() + .HasForeignKey("OutputBinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") + .WithMany("Runs") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CancelReason"); + + b.Navigation("Creator"); + + b.Navigation("OutputBin"); + + b.Navigation("Template"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionTemplate", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoiceLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Grn", "Grn") + .WithMany() + .HasForeignKey("GrnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseInvoice", "PurchaseInvoice") + .WithMany("Lines") + .HasForeignKey("PurchaseInvoiceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Grn"); + + b.Navigation("PurchaseInvoice"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoicePayment", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseInvoice", "PurchaseInvoice") + .WithMany("Payments") + .HasForeignKey("PurchaseInvoiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("PurchaseInvoice"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") + .WithMany() + .HasForeignKey("RequisitionId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("Requisition"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturn", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ReasonCode") + .WithMany() + .HasForeignKey("ReasonCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("ReasonCode"); + + b.Navigation("Vendor"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturnLine", b => + { + b.HasOne("ERPCore.Domain.Entities.GrnLine", "GrnLine") + .WithMany() + .HasForeignKey("GrnLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseReturn", "Return") + .WithMany("Lines") + .HasForeignKey("ReturnId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GrnLine"); + + b.Navigation("Item"); + + b.Navigation("Return"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Requester") + .WithMany() + .HasForeignKey("RequestedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Requester"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RequisitionLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") + .WithMany("Lines") + .HasForeignKey("RequisitionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Requisition"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => + { + b.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") + .WithMany() + .HasForeignKey("RequisitionId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Requisition"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RfqLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Rfq", "Rfq") + .WithMany("Lines") + .HasForeignKey("RfqId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Rfq"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RolePermission", b => + { + b.HasOne("ERPCore.Domain.Entities.Permission", "Permission") + .WithMany() + .HasForeignKey("PermissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Role", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Permission"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunEdge", b => + { + b.HasOne("ERPCore.Domain.Entities.RunStage", "ChildRunStage") + .WithMany() + .HasForeignKey("ChildRunStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "ParentRunStage") + .WithMany() + .HasForeignKey("ParentRunStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ProductionRun", "Run") + .WithMany("Edges") + .HasForeignKey("RunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildRunStage"); + + b.Navigation("ParentRunStage"); + + b.Navigation("Run"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStage", b => + { + b.HasOne("ERPCore.Domain.Entities.ProductionRun", "Run") + .WithMany("Stages") + .HasForeignKey("RunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "TemplateStage") + .WithMany() + .HasForeignKey("TemplateStageId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Run"); + + b.Navigation("TemplateStage"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageEvent", b => + { + b.HasOne("ERPCore.Domain.Entities.ProductionRun", "Run") + .WithMany("Events") + .HasForeignKey("RunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "RunStage") + .WithMany("Events") + .HasForeignKey("RunStageId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Run"); + + b.Navigation("RunStage"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageInput", b => + { + b.HasOne("ERPCore.Domain.Entities.RunStageOutput", "FromRunOutput") + .WithMany() + .HasForeignKey("FromRunOutputId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "RunStage") + .WithMany("Inputs") + .HasForeignKey("RunStageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromRunOutput"); + + b.Navigation("Item"); + + b.Navigation("RunStage"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageOutput", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "RunStage") + .WithMany("Outputs") + .HasForeignKey("RunStageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ScrapReason") + .WithMany() + .HasForeignKey("ScrapReasonCodeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Uom", "Uom") + .WithMany() + .HasForeignKey("UomId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Item"); + + b.Navigation("RunStage"); + + b.Navigation("ScrapReason"); + + b.Navigation("Uom"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesDayEnd", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "CashierUser") + .WithMany() + .HasForeignKey("CashierUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "ClosedByUser") + .WithMany() + .HasForeignKey("ClosedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CashierUser"); + + b.Navigation("ClosedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoice", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatorUserId"); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("Customer"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoiceLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesInvoice", "SalesInvoice") + .WithMany("Lines") + .HasForeignKey("SalesInvoiceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SalesInvoice"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoicePayment", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesInvoice", "SalesInvoice") + .WithMany("Payments") + .HasForeignKey("SalesInvoiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("SalesInvoice"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturn", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ReasonCode") + .WithMany() + .HasForeignKey("ReasonCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("Customer"); + + b.Navigation("ReasonCode"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturnLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesReturn", "Return") + .WithMany("Lines") + .HasForeignKey("ReturnId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesInvoiceLine", "SalesInvoiceLine") + .WithMany() + .HasForeignKey("SalesInvoiceLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Item"); + + b.Navigation("Return"); + + b.Navigation("SalesInvoiceLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlip", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "CashierUser") + .WithMany() + .HasForeignKey("CashierUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesDayEnd", "DayEnd") + .WithMany("Slips") + .HasForeignKey("DayEndId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CashierUser"); + + b.Navigation("Customer"); + + b.Navigation("DayEnd"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlipLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesSlip", "SalesSlip") + .WithMany("Lines") + .HasForeignKey("SalesSlipId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SalesSlip"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Serial", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageEdge", b => + { + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "ChildStage") + .WithMany() + .HasForeignKey("ChildStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "ParentStage") + .WithMany() + .HasForeignKey("ParentStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") + .WithMany("Edges") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildStage"); + + b.Navigation("ParentStage"); + + b.Navigation("Template"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageInput", b => + { + b.HasOne("ERPCore.Domain.Entities.StageOutput", "FromOutput") + .WithMany() + .HasForeignKey("FromOutputId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "Stage") + .WithMany("Inputs") + .HasForeignKey("StageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromOutput"); + + b.Navigation("Item"); + + b.Navigation("Stage"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageOutput", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "Stage") + .WithMany("Outputs") + .HasForeignKey("StageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Uom", "Uom") + .WithMany() + .HasForeignKey("UomId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Item"); + + b.Navigation("Stage"); + + b.Navigation("Uom"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustment", 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.HasOne("ERPCore.Domain.Entities.ReasonCode", "ReasonCode") + .WithMany() + .HasForeignKey("ReasonCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("ReasonCode"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustmentLine", b => + { + b.HasOne("ERPCore.Domain.Entities.StockAdjustment", "Adjustment") + .WithMany("Lines") + .HasForeignKey("AdjustmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Batch", null) + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", null) + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Adjustment"); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCount", 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.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCountLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.StockCount", "Count") + .WithMany("Lines") + .HasForeignKey("CountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Count"); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLayer", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", "Batch") + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.GrnLine", "GrnLine") + .WithMany() + .HasForeignKey("GrnLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", "Serial") + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Batch"); + + b.Navigation("GrnLine"); + + b.Navigation("Item"); + + b.Navigation("Serial"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLedger", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", null) + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", null) + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", null) + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", null) + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransfer", 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.HasOne("ERPCore.Domain.Entities.Warehouse", "DestWarehouse") + .WithMany() + .HasForeignKey("DestWarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "SrcWarehouse") + .WithMany() + .HasForeignKey("SrcWarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("DestWarehouse"); + + b.Navigation("SrcWarehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransferLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", null) + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("DestBinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", null) + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("SrcBinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.StockTransfer", "Transfer") + .WithMany("Lines") + .HasForeignKey("TransferId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Transfer"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubCategory", b => + { + b.HasOne("ERPCore.Domain.Entities.Category", "Category") + .WithMany("SubCategories") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubNavItem", b => + { + b.HasOne("ERPCore.Domain.Entities.NavItem", "NavItem") + .WithMany("Children") + .HasForeignKey("NavItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("NavItem"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicketMessage", b => + { + b.HasOne("ERPCore.Domain.Entities.SupportTicket", "Ticket") + .WithMany("Messages") + .HasForeignKey("TicketId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ticket"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => + { + b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") + .WithMany("Stages") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Template"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.User", b => + { + b.HasOne("ERPCore.Domain.Entities.Role", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => + { + b.HasOne("ERPCore.Domain.Entities.Rfq", "Rfq") + .WithMany("Quotations") + .HasForeignKey("RfqId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Rfq"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotationLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.VendorQuotation", "Quotation") + .WithMany("Lines") + .HasForeignKey("QuotationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Quotation"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Warehouse", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSale", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplate", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Category", b => + { + b.Navigation("SubCategories"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeLoan", b => + { + b.Navigation("Installments"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructure", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Grn", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLine", b => + { + b.Navigation("WarrantyNumbers"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Item", b => + { + b.Navigation("ReorderSettings"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NavItem", b => + { + b.Navigation("Children"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Notification", b => + { + b.Navigation("Recipients"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => + { + b.Navigation("Modules"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => + { + b.Navigation("Components"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollRun", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b => + { + b.Navigation("Edges"); + + b.Navigation("Events"); + + b.Navigation("Stages"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionTemplate", b => + { + b.Navigation("Edges"); + + b.Navigation("Runs"); + + b.Navigation("Stages"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", b => + { + b.Navigation("Lines"); + + b.Navigation("Payments"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturn", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => + { + b.Navigation("Lines"); + + b.Navigation("Quotations"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStage", b => + { + b.Navigation("Events"); + + b.Navigation("Inputs"); + + b.Navigation("Outputs"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesDayEnd", b => + { + b.Navigation("BundleSales"); + + b.Navigation("Slips"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoice", b => + { + b.Navigation("Lines"); + + b.Navigation("Payments"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturn", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlip", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustment", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCount", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransfer", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicket", b => + { + b.Navigation("Messages"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => + { + b.Navigation("Inputs"); + + b.Navigation("Outputs"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Warehouse", b => + { + b.Navigation("Bins"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Backend/ERPCore/Migrations/20260915100820_AddWarehouseAddressPhone.cs b/Backend/ERPCore/Migrations/20260915100820_AddWarehouseAddressPhone.cs new file mode 100644 index 0000000..8ed6262 --- /dev/null +++ b/Backend/ERPCore/Migrations/20260915100820_AddWarehouseAddressPhone.cs @@ -0,0 +1,38 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace ERPCore.Migrations +{ + /// + public partial class AddWarehouseAddressPhone : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Address", + table: "warehouses", + type: "text", + nullable: true); + + migrationBuilder.AddColumn( + name: "Phone", + table: "warehouses", + type: "text", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Address", + table: "warehouses"); + + migrationBuilder.DropColumn( + name: "Phone", + table: "warehouses"); + } + } +} diff --git a/Backend/ERPCore/Migrations/20260915102006_AddWarehouseBranchingToggle.Designer.cs b/Backend/ERPCore/Migrations/20260915102006_AddWarehouseBranchingToggle.Designer.cs new file mode 100644 index 0000000..376b5e7 --- /dev/null +++ b/Backend/ERPCore/Migrations/20260915102006_AddWarehouseBranchingToggle.Designer.cs @@ -0,0 +1,8426 @@ +// +using System; +using ERPCore.Infra.Persistence; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace ERPCore.Migrations +{ + [DbContext(typeof(ErpDbContext))] + [Migration("20260915102006_AddWarehouseBranchingToggle")] + partial class AddWarehouseBranchingToggle + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.9") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceRecord", b => + { + b.Property("AttendanceRecordId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AttendanceRecordId")); + + b.Property("AttendanceDate") + .HasColumnType("timestamp with time zone"); + + b.Property("AttendanceStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("AttendanceUploadBatchId") + .HasColumnType("integer"); + + b.Property("CheckIn") + .HasColumnType("interval"); + + b.Property("CheckOut") + .HasColumnType("interval"); + + b.Property("DuplicateOfAttendanceRecordId") + .HasColumnType("integer"); + + b.Property("EarlyLeaveMinutes") + .HasColumnType("integer"); + + b.Property("EditedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EditedBy") + .HasColumnType("integer"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("IsManualOverride") + .HasColumnType("boolean"); + + b.Property("LateMinutes") + .HasColumnType("integer"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("OvertimeMinutes") + .HasColumnType("integer"); + + b.Property("RowValidationStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("WorkShiftId") + .HasColumnType("integer"); + + b.Property("WorkingMinutes") + .HasColumnType("integer"); + + b.HasKey("AttendanceRecordId"); + + b.HasIndex("AttendanceUploadBatchId"); + + b.HasIndex("WorkShiftId"); + + b.HasIndex("EmployeeId", "AttendanceDate"); + + b.ToTable("hr_attendance_records", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceUploadBatch", b => + { + b.Property("AttendanceUploadBatchId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AttendanceUploadBatchId")); + + b.Property("ConfirmedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ConfirmedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("OriginalFileName") + .HasMaxLength(260) + .HasColumnType("character varying(260)"); + + b.Property("PeriodEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("PeriodStart") + .HasColumnType("timestamp with time zone"); + + b.Property("RowCountDuplicate") + .HasColumnType("integer"); + + b.Property("RowCountError") + .HasColumnType("integer"); + + b.Property("RowCountTotal") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SourceType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UploadedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UploadedBy") + .HasColumnType("integer"); + + b.HasKey("AttendanceUploadBatchId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("PeriodStart", "PeriodEnd"); + + b.ToTable("hr_attendance_upload_batches", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AuditLog", b => + { + b.Property("AuditId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AuditId")); + + b.Property("Action") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("ChangeSet") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EntityId") + .HasColumnType("integer"); + + b.Property("EntityType") + .IsRequired() + .HasMaxLength(80) + .HasColumnType("character varying(80)"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("AuditId"); + + b.HasIndex("CreatedAt"); + + b.HasIndex("UserId"); + + b.HasIndex("EntityType", "EntityId"); + + b.ToTable("audit_logs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Batch", b => + { + b.Property("BatchId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BatchId")); + + b.Property("BatchNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ExpiryDate") + .HasColumnType("date"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.HasKey("BatchId"); + + b.HasIndex("ItemId", "BatchNo") + .IsUnique(); + + b.ToTable("batches", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Bin", b => + { + b.Property("BinId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BinId")); + + b.Property("BinType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BinId"); + + b.HasIndex("WarehouseId", "Code") + .IsUnique(); + + b.ToTable("bins", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Branch", b => + { + b.Property("BranchId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BranchId")); + + b.Property("Address") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("PhoneNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_branches", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BranchConfig", b => + { + b.Property("ConfigId") + .HasColumnType("integer"); + + b.Property("BranchingEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.Property("WarehouseBranchingEnabled") + .HasColumnType("boolean"); + + b.HasKey("ConfigId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("branch_config", null, t => + { + t.HasCheckConstraint("ck_branch_config_singleton", "\"ConfigId\" = 1"); + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Brand", b => + { + b.Property("BrandId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BrandId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("BrandId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("brands", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSale", b => + { + b.Property("BundleSaleId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleId")); + + b.Property("BundleCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BundleDate") + .HasColumnType("timestamp with time zone"); + + b.Property("BundleName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("BundleNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BundlePrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BundleSaleTemplateId") + .HasColumnType("integer"); + + b.Property("CashierUserId") + .HasColumnType("integer"); + + b.Property("ComponentSubtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("CustomerSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DayEndId") + .HasColumnType("integer"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("MarginAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BundleSaleId"); + + b.HasIndex("BundleNo") + .IsUnique(); + + b.HasIndex("BundleSaleTemplateId"); + + b.HasIndex("CashierUserId"); + + b.HasIndex("CustomerId"); + + b.HasIndex("DayEndId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("bundle_sales", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleLine", b => + { + b.Property("BundleSaleLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleLineId")); + + b.Property("BundleSaleId") + .HasColumnType("integer"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("IncludeInBundle") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("IsComponent") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ParentLineId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BundleSaleLineId"); + + b.HasIndex("BundleSaleId"); + + b.HasIndex("ItemId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("bundle_sale_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplate", b => + { + b.Property("BundleSaleTemplateId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleTemplateId")); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TemplateCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("TemplateName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("BundleSaleTemplateId"); + + b.HasIndex("TemplateCode") + .IsUnique(); + + b.ToTable("bundle_sale_templates", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplateLine", b => + { + b.Property("BundleSaleTemplateLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleTemplateLineId")); + + b.Property("BundleSaleTemplateId") + .HasColumnType("integer"); + + b.Property("IncludeInBundle") + .HasColumnType("boolean"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SortOrder") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BundleSaleTemplateLineId"); + + b.HasIndex("BundleSaleTemplateId"); + + b.HasIndex("ItemId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("bundle_sale_template_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Category", b => + { + b.Property("CategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CategoryId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("CategoryId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("categories", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Customer", b => + { + b.Property("CustomerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CustomerId")); + + b.Property("AddressLine1") + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("AddressLine2") + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("City") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Country") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreditDays") + .HasColumnType("integer"); + + b.Property("CreditLimit") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CustomerCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CustomerType") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("B2C"); + + b.Property("DefaultWarehouseId") + .HasColumnType("integer"); + + b.Property("DisplayName") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Email") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Phone") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TaxRegistrationNo") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("CustomerId"); + + b.HasIndex("CustomerCode") + .IsUnique(); + + b.HasIndex("CustomerType"); + + b.HasIndex("DefaultWarehouseId"); + + b.HasIndex("Status"); + + b.ToTable("customers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Department", b => + { + b.Property("DepartmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("DepartmentId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("HeadEmployeeId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("ParentDepartmentId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("DepartmentId"); + + b.HasIndex("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("HeadEmployeeId"); + + b.HasIndex("ParentDepartmentId"); + + b.HasIndex("Status"); + + b.ToTable("hr_departments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Designation", b => + { + b.Property("DesignationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("DesignationId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("DesignationId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_designations", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Employee", b => + { + b.Property("EmployeeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeId")); + + b.Property("AddressLine1") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("AddressLine2") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("City") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ConfirmationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Country") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DateOfBirth") + .HasColumnType("timestamp with time zone"); + + b.Property("DepartmentId") + .HasColumnType("integer"); + + b.Property("DesignationId") + .HasColumnType("integer"); + + b.Property("Email") + .HasMaxLength(320) + .HasColumnType("character varying(320)"); + + b.Property("EmergencyContactName") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("EmergencyContactPhone") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmergencyContactRelationship") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("EmployeeCode") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmploymentTypeId") + .HasColumnType("integer"); + + b.Property("EpfNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EtfNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Gender") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("HireDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LastWorkingDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Nationality") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Nic") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PersonalMobile") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PostalCode") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ProfilePhotoPath") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("ReportingManagerId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TaxIdentificationNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.Property("WorkShiftId") + .HasColumnType("integer"); + + b.HasKey("EmployeeId"); + + b.HasIndex("BranchId"); + + b.HasIndex("DepartmentId"); + + b.HasIndex("DesignationId"); + + b.HasIndex("Email"); + + b.HasIndex("EmployeeCode") + .IsUnique(); + + b.HasIndex("EmploymentTypeId"); + + b.HasIndex("ReportingManagerId"); + + b.HasIndex("Status"); + + b.HasIndex("UserId") + .IsUnique(); + + b.HasIndex("WorkShiftId"); + + b.ToTable("hr_employees", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeBankDetail", b => + { + b.Property("EmployeeBankDetailId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeBankDetailId")); + + b.Property("AccountHolderName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("AccountNumber") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BankName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("BranchName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("IsPrimary") + .HasColumnType("boolean"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("SwiftCode") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("EmployeeBankDetailId"); + + b.HasIndex("EmployeeId"); + + b.ToTable("hr_employee_bank_details", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeDocument", b => + { + b.Property("EmployeeDocumentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeDocumentId")); + + b.Property("ContentType") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("ExpiryDate") + .HasColumnType("timestamp with time zone"); + + b.Property("HrDocumentTypeId") + .HasColumnType("integer"); + + b.Property("IssueDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("OriginalFileName") + .IsRequired() + .HasMaxLength(260) + .HasColumnType("character varying(260)"); + + b.Property("RelativePath") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SizeBytes") + .HasColumnType("bigint"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("StoredFileName") + .IsRequired() + .HasMaxLength(260) + .HasColumnType("character varying(260)"); + + b.Property("UploadedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UploadedBy") + .HasColumnType("integer"); + + b.Property("VerifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VerifiedBy") + .HasColumnType("integer"); + + b.HasKey("EmployeeDocumentId"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("ExpiryDate"); + + b.HasIndex("HrDocumentTypeId"); + + b.ToTable("hr_employee_documents", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeLoan", b => + { + b.Property("EmployeeLoanId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeLoanId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("InstallmentAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("InterestRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("LoanKind") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("NumberOfInstallments") + .HasColumnType("integer"); + + b.Property("OutstandingBalance") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("PrincipalAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("StartMonth") + .HasColumnType("integer"); + + b.Property("StartYear") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("EmployeeLoanId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("EmployeeId"); + + b.HasIndex("Status"); + + b.ToTable("hr_employee_loans", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructure", b => + { + b.Property("EmployeeSalaryStructureId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeSalaryStructureId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("BasicSalary") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("Currency") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("character varying(3)"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveTo") + .HasColumnType("timestamp with time zone"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("EmployeeSalaryStructureId"); + + b.HasIndex("EmployeeId", "EffectiveTo"); + + b.ToTable("hr_employee_salary_structures", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructureLine", b => + { + b.Property("EmployeeSalaryStructureLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeSalaryStructureLineId")); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("EmployeeSalaryStructureId") + .HasColumnType("integer"); + + b.Property("SalaryComponentId") + .HasColumnType("integer"); + + b.HasKey("EmployeeSalaryStructureLineId"); + + b.HasIndex("EmployeeSalaryStructureId"); + + b.HasIndex("SalaryComponentId"); + + b.ToTable("hr_employee_salary_structure_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmploymentType", b => + { + b.Property("EmploymentTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmploymentTypeId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("EmploymentTypeId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_employment_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Grn", b => + { + b.Property("GrnId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("GrnId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PoId") + .HasColumnType("integer"); + + b.Property("PostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PurchaseInvoiceId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("GrnId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("PoId"); + + b.HasIndex("PurchaseInvoiceId"); + + b.HasIndex("Status"); + + b.HasIndex("VendorId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("grns", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLine", b => + { + b.Property("GrnLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("GrnLineId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("DiscountPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("GrnId") + .HasColumnType("integer"); + + b.Property("HoldStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("NetUnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("PoLineId") + .HasColumnType("integer"); + + b.Property("PoUnitPrice") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReceivedValue") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("VatAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("VatPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.HasKey("GrnLineId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("GrnId"); + + b.HasIndex("ItemId"); + + b.HasIndex("PoLineId"); + + b.ToTable("grn_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLineWarrantyNumber", b => + { + b.Property("GrnLineWarrantyNumberId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("GrnLineWarrantyNumberId")); + + b.Property("GrnLineId") + .HasColumnType("integer"); + + b.Property("WarrantyNo") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("WarrantyPeriodMonths") + .HasColumnType("integer"); + + b.HasKey("GrnLineWarrantyNumberId"); + + b.HasIndex("GrnLineId", "WarrantyNo") + .IsUnique(); + + b.ToTable("grn_line_warranty_numbers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.HrDocumentType", b => + { + b.Property("HrDocumentTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("HrDocumentTypeId")); + + b.Property("Category") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpiryTracked") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RequiredAtOnboarding") + .HasColumnType("boolean"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("HrDocumentTypeId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_document_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Item", b => + { + b.Property("ItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ItemId")); + + b.Property("BaseUomId") + .HasColumnType("integer"); + + b.Property("BrandId") + .HasColumnType("integer"); + + b.Property("CategoryId") + .HasColumnType("integer"); + + b.Property("ContentBaseQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ContentBaseUnit") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ContentQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ContentUnit") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DefaultVendorId") + .HasColumnType("integer"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SellingFlatPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SellingMaxPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SellingMinPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Sku") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("StockNature") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("SubCategoryId") + .HasColumnType("integer"); + + b.Property("TaxClass") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("TrackingMode") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Warranty") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("NonWarranty"); + + b.Property("WarrantyPeriodMonths") + .HasColumnType("integer"); + + b.HasKey("ItemId"); + + b.HasIndex("BaseUomId"); + + b.HasIndex("BrandId"); + + b.HasIndex("CategoryId"); + + b.HasIndex("DefaultVendorId"); + + b.HasIndex("Sku") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("SubCategoryId"); + + b.ToTable("items", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ItemReorder", b => + { + b.Property("ReorderId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReorderId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("ReorderPoint") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReorderQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("ReorderId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("ItemId", "WarehouseId") + .IsUnique(); + + b.ToTable("item_reorders", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ItemType", b => + { + b.Property("ItemTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ItemTypeId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsMeasurable") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("ItemTypeId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("item_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.JournalEntryStub", b => + { + b.Property("JournalId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("JournalId")); + + b.Property("Amount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CreditAccount") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("DebitAccount") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("SourceDocId") + .HasColumnType("integer"); + + b.Property("SourceDocType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.HasKey("JournalId"); + + b.HasIndex("SourceDocType", "SourceDocId"); + + b.ToTable("journal_entry_stubs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveBalance", b => + { + b.Property("LeaveBalanceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LeaveBalanceId")); + + b.Property("AdjustmentDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("CarriedForwardDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("EntitledDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("LeaveTypeId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("TakenDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Year") + .HasColumnType("integer"); + + b.HasKey("LeaveBalanceId"); + + b.HasIndex("LeaveTypeId"); + + b.HasIndex("EmployeeId", "LeaveTypeId", "Year") + .IsUnique(); + + b.ToTable("hr_leave_balances", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveRequest", b => + { + b.Property("LeaveRequestId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LeaveRequestId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DaysCount") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("EndDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LeaveTypeId") + .HasColumnType("integer"); + + b.Property("Reason") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("RejectionReason") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("StartDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("LeaveRequestId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("EmployeeId"); + + b.HasIndex("LeaveTypeId"); + + b.HasIndex("Status"); + + b.HasIndex("StartDate", "EndDate"); + + b.ToTable("hr_leave_requests", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveType", b => + { + b.Property("LeaveTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LeaveTypeId")); + + b.Property("AccrualPerYear") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("CarryForwardAllowed") + .HasColumnType("boolean"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CountsAsNoPay") + .HasColumnType("boolean"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsPaid") + .HasColumnType("boolean"); + + b.Property("MaxCarryForwardDays") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RequiresApproval") + .HasColumnType("boolean"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("LeaveTypeId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_leave_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoanInstallment", b => + { + b.Property("LoanInstallmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LoanInstallmentId")); + + b.Property("DueMonth") + .HasColumnType("integer"); + + b.Property("DueYear") + .HasColumnType("integer"); + + b.Property("EmployeeLoanId") + .HasColumnType("integer"); + + b.Property("InstallmentNumber") + .HasColumnType("integer"); + + b.Property("PaidAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("PayrollRunId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("ScheduledAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("LoanInstallmentId"); + + b.HasIndex("EmployeeLoanId"); + + b.HasIndex("PayrollRunId"); + + b.HasIndex("DueYear", "DueMonth"); + + b.ToTable("hr_loan_installments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoginActivity", b => + { + b.Property("LoginActivityId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LoginActivityId")); + + b.Property("DeviceLabel") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("IpAddress") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("LoginAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserAgent") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("LoginActivityId"); + + b.HasIndex("UserId", "LoginAt"); + + b.ToTable("login_activities", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NavItem", b => + { + b.Property("NavItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NavItemId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Href") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Icon") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.HasKey("NavItemId"); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("nav_items", (string)null); + + b.HasData( + new + { + NavItemId = 1, + Code = "dashboard", + Href = "/dashboard", + Label = "Dashboard", + SortOrder = 1, + Status = "Active" + }, + new + { + NavItemId = 2, + Code = "products", + Href = "/dashboard/products", + Label = "Products", + SortOrder = 2, + Status = "Active" + }, + new + { + NavItemId = 4, + Code = "procurement", + Href = "/dashboard/procurement", + Label = "Procurement", + SortOrder = 4, + Status = "Active" + }, + new + { + NavItemId = 5, + Code = "receiving", + Href = "/dashboard/receiving/grn", + Label = "Receiving", + SortOrder = 5, + Status = "Active" + }, + new + { + NavItemId = 6, + Code = "stock", + Href = "/dashboard/stock", + Label = "Stock", + SortOrder = 6, + Status = "Active" + }, + new + { + NavItemId = 7, + Code = "warehouses", + Href = "/dashboard/warehouse", + Label = "Warehouses", + SortOrder = 7, + Status = "Active" + }, + new + { + NavItemId = 8, + Code = "orders", + Href = "/dashboard/orders", + Label = "Orders", + SortOrder = 8, + Status = "Active" + }, + new + { + NavItemId = 9, + Code = "settings", + Href = "/dashboard/settings", + Label = "Settings", + SortOrder = 9, + Status = "Active" + }, + new + { + NavItemId = 10, + Code = "help", + Href = "/dashboard/help", + Label = "Help", + SortOrder = 10, + Status = "Active" + }, + new + { + NavItemId = 11, + Code = "ledgers", + Href = "/dashboard/ledgers", + Label = "Ledgers", + SortOrder = 11, + Status = "Active" + }, + new + { + NavItemId = 12, + Code = "accounts", + Href = "/dashboard/accounts", + Label = "Accounts", + SortOrder = 12, + Status = "Active" + }, + new + { + NavItemId = 13, + Code = "sales", + Href = "/dashboard/sales", + Label = "Sales", + SortOrder = 13, + Status = "Active" + }, + new + { + NavItemId = 14, + Code = "production", + Href = "/dashboard/production", + Label = "Production", + SortOrder = 14, + Status = "Active" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Notification", b => + { + b.Property("NotificationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NotificationId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("ModuleKey") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("RelatedEntityId") + .HasColumnType("integer"); + + b.Property("RelatedEntityType") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.HasKey("NotificationId"); + + b.HasIndex("CreatedAt"); + + b.ToTable("notifications", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => + { + b.Property("NotificationConfigId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.HasKey("NotificationConfigId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("notification_config", null, t => + { + t.HasCheckConstraint("ck_notification_config_singleton", "\"NotificationConfigId\" = 1"); + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfigModule", b => + { + b.Property("NotificationConfigModuleId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NotificationConfigModuleId")); + + b.Property("EmailEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("InAppEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("ModuleKey") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("NotificationConfigId") + .HasColumnType("integer"); + + b.Property("SmsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.HasKey("NotificationConfigModuleId"); + + b.HasIndex("ModuleKey") + .IsUnique(); + + b.HasIndex("NotificationConfigId"); + + b.ToTable("notification_config_modules", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationRecipient", b => + { + b.Property("NotificationRecipientId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NotificationRecipientId")); + + b.Property("IsRead") + .HasColumnType("boolean"); + + b.Property("NotificationId") + .HasColumnType("integer"); + + b.Property("ReadAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("NotificationRecipientId"); + + b.HasIndex("NotificationId"); + + b.HasIndex("UserId", "IsRead", "NotificationId"); + + b.ToTable("notification_recipients", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NumberSequence", b => + { + b.Property("SequenceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SequenceId")); + + b.Property("DocType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("doc_type"); + + b.Property("LastNumber") + .HasColumnType("integer") + .HasColumnName("last_number"); + + b.Property("Year") + .HasColumnType("integer") + .HasColumnName("year"); + + b.HasKey("SequenceId"); + + b.HasIndex("DocType", "Year") + .IsUnique(); + + b.ToTable("number_sequences", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => + { + b.Property("PayrollLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollLineId")); + + b.Property("AbsentDays") + .HasColumnType("integer"); + + b.Property("BasicSalary") + .HasColumnType("numeric(18,2)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("EpfEmployeeAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("EpfEmployerAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("EtfEmployerAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("GrossSalary") + .HasColumnType("numeric(18,2)"); + + b.Property("LateDeductionAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("LateMinutesTotal") + .HasColumnType("integer"); + + b.Property("LeaveDays") + .HasColumnType("integer"); + + b.Property("LoanDeductionAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("NetSalary") + .HasColumnType("numeric(18,2)"); + + b.Property("NoPayAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("OtMinutesTotal") + .HasColumnType("integer"); + + b.Property("OtherDeductionsAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("OvertimeAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("PayrollRunId") + .HasColumnType("integer"); + + b.Property("PresentDays") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("TaxAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("TotalAllowances") + .HasColumnType("numeric(18,2)"); + + b.Property("WorkingDays") + .HasColumnType("integer"); + + b.HasKey("PayrollLineId"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("PayrollRunId", "EmployeeId") + .IsUnique(); + + b.ToTable("hr_payroll_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLineComponent", b => + { + b.Property("PayrollLineComponentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollLineComponentId")); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("ComponentCategory") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("PayrollLineId") + .HasColumnType("integer"); + + b.Property("SalaryComponentId") + .HasColumnType("integer"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.HasKey("PayrollLineComponentId"); + + b.HasIndex("PayrollLineId"); + + b.HasIndex("SalaryComponentId"); + + b.ToTable("hr_payroll_line_components", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollRun", b => + { + b.Property("PayrollRunId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollRunId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GeneratedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GeneratedBy") + .HasColumnType("integer"); + + b.Property("LockedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("LockedBy") + .HasColumnType("integer"); + + b.Property("PeriodMonth") + .HasColumnType("integer"); + + b.Property("PeriodYear") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UnlockReason") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("UnlockedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UnlockedBy") + .HasColumnType("integer"); + + b.HasKey("PayrollRunId"); + + b.HasIndex("BranchId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("PeriodYear", "PeriodMonth", "BranchId"); + + b.ToTable("hr_payroll_runs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollStatutorySetting", b => + { + b.Property("PayrollStatutorySettingId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollStatutorySettingId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveTo") + .HasColumnType("timestamp with time zone"); + + b.Property("EpfEmployeeRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("EpfEmployerRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("EtfEmployerRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("OtMultiplierDefault") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.HasKey("PayrollStatutorySettingId"); + + b.HasIndex("EffectiveFrom"); + + b.ToTable("hr_payroll_statutory_settings", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Payslip", b => + { + b.Property("PayslipId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayslipId")); + + b.Property("GeneratedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PayrollLineId") + .HasColumnType("integer"); + + b.Property("ReleasedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReleasedBy") + .HasColumnType("integer"); + + b.HasKey("PayslipId"); + + b.HasIndex("PayrollLineId") + .IsUnique(); + + b.ToTable("hr_payslips", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Permission", b => + { + b.Property("PermissionId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PermissionId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(80) + .HasColumnType("character varying(80)"); + + b.Property("NavItemId") + .HasColumnType("integer"); + + b.Property("SubNavItemId") + .HasColumnType("integer"); + + b.HasKey("PermissionId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("NavItemId"); + + b.HasIndex("SubNavItemId"); + + b.ToTable("permissions", (string)null); + + b.HasData( + new + { + PermissionId = 1, + Code = "NAV:dashboard", + NavItemId = 1 + }, + new + { + PermissionId = 2, + Code = "NAV:products", + NavItemId = 2 + }, + new + { + PermissionId = 3, + Code = "NAV:procurement.vendors", + SubNavItemId = 30 + }, + new + { + PermissionId = 4, + Code = "NAV:procurement", + NavItemId = 4 + }, + new + { + PermissionId = 5, + Code = "NAV:receiving", + NavItemId = 5 + }, + new + { + PermissionId = 6, + Code = "NAV:stock", + NavItemId = 6 + }, + new + { + PermissionId = 7, + Code = "NAV:warehouses", + NavItemId = 7 + }, + new + { + PermissionId = 8, + Code = "NAV:orders", + NavItemId = 8 + }, + new + { + PermissionId = 9, + Code = "NAV:settings", + NavItemId = 9 + }, + new + { + PermissionId = 10, + Code = "NAV:help", + NavItemId = 10 + }, + new + { + PermissionId = 11, + Code = "NAV:products.item", + SubNavItemId = 1 + }, + new + { + PermissionId = 12, + Code = "NAV:products.category", + SubNavItemId = 2 + }, + new + { + PermissionId = 13, + Code = "NAV:products.brand", + SubNavItemId = 3 + }, + new + { + PermissionId = 14, + Code = "NAV:products.item-type", + SubNavItemId = 4 + }, + new + { + PermissionId = 15, + Code = "NAV:products.uom", + SubNavItemId = 5 + }, + new + { + PermissionId = 16, + Code = "NAV:products.configuration", + SubNavItemId = 6 + }, + new + { + PermissionId = 17, + Code = "NAV:settings.roles", + SubNavItemId = 7 + }, + new + { + PermissionId = 18, + Code = "NAV:settings.users", + SubNavItemId = 8 + }, + new + { + PermissionId = 28, + Code = "NAV:procurement.requisitions", + SubNavItemId = 17 + }, + new + { + PermissionId = 29, + Code = "NAV:procurement.rfqs", + SubNavItemId = 18 + }, + new + { + PermissionId = 30, + Code = "NAV:procurement.purchase-orders", + SubNavItemId = 19 + }, + new + { + PermissionId = 31, + Code = "NAV:procurement.purchase-returns", + SubNavItemId = 20 + }, + new + { + PermissionId = 19, + Code = "NAV:ledgers", + NavItemId = 11 + }, + new + { + PermissionId = 20, + Code = "NAV:ledgers.trial-balance", + SubNavItemId = 9 + }, + new + { + PermissionId = 21, + Code = "NAV:ledgers.balance-sheet", + SubNavItemId = 10 + }, + new + { + PermissionId = 22, + Code = "NAV:ledgers.general-ledger", + SubNavItemId = 11 + }, + new + { + PermissionId = 23, + Code = "NAV:ledgers.profit-and-loss", + SubNavItemId = 12 + }, + new + { + PermissionId = 24, + Code = "NAV:ledgers.cash-flow", + SubNavItemId = 13 + }, + new + { + PermissionId = 25, + Code = "NAV:ledgers.budget-vs-actual", + SubNavItemId = 14 + }, + new + { + PermissionId = 27, + Code = "NAV:ledgers.tax-report", + SubNavItemId = 16 + }, + new + { + PermissionId = 26, + Code = "NAV:accounts.bank-accounts", + SubNavItemId = 15 + }, + new + { + PermissionId = 32, + Code = "NAV:accounts", + NavItemId = 12 + }, + new + { + PermissionId = 33, + Code = "NAV:accounts.cheque-books", + SubNavItemId = 21 + }, + new + { + PermissionId = 34, + Code = "NAV:accounts.received-cheques", + SubNavItemId = 22 + }, + new + { + PermissionId = 35, + Code = "NAV:production", + NavItemId = 14 + }, + new + { + PermissionId = 36, + Code = "NAV:production.templates", + SubNavItemId = 27 + }, + new + { + PermissionId = 37, + Code = "NAV:production.runs", + SubNavItemId = 25 + }, + new + { + PermissionId = 38, + Code = "NAV:production.produced", + SubNavItemId = 26 + }, + new + { + PermissionId = 39, + Code = "NAV:procurement.purchase-invoices", + SubNavItemId = 28 + }, + new + { + PermissionId = 40, + Code = "NAV:settings.branches", + SubNavItemId = 29 + }, + new + { + PermissionId = 41, + Code = "NAV:stock.ledger", + SubNavItemId = 31 + }, + new + { + PermissionId = 42, + Code = "NAV:stock.enquiry", + SubNavItemId = 32 + }, + new + { + PermissionId = 43, + Code = "NAV:stock.valuation", + SubNavItemId = 33 + }, + new + { + PermissionId = 44, + Code = "NAV:stock.transfers", + SubNavItemId = 34 + }, + new + { + PermissionId = 45, + Code = "NAV:stock.adjustments", + SubNavItemId = 35 + }, + new + { + PermissionId = 46, + Code = "NAV:stock.counts", + SubNavItemId = 36 + }, + new + { + PermissionId = 47, + Code = "NAV:stock.reorder-alerts", + SubNavItemId = 37 + }, + new + { + PermissionId = 48, + Code = "NAV:stock.wastage", + SubNavItemId = 38 + }, + new + { + PermissionId = 49, + Code = "NAV:sales.bundle-templates", + SubNavItemId = 23 + }, + new + { + PermissionId = 50, + Code = "NAV:sales.invoices", + SubNavItemId = 40 + }, + new + { + PermissionId = 51, + Code = "NAV:sales.free-issues", + SubNavItemId = 41 + }, + new + { + PermissionId = 52, + Code = "NAV:sales.day-end", + SubNavItemId = 42 + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PoLine", b => + { + b.Property("PoLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PoLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("PoId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyReceived") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Tax") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("PoLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("PoId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("po_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductConfig", b => + { + b.Property("ConfigId") + .HasColumnType("integer"); + + b.Property("BatchListsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("BrandsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("ItemTypesEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SellingPricesEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("SerialNumbersEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("SubcategoriesEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.Property("WarrantyPeriodsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.HasKey("ConfigId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("product_config", null, t => + { + t.HasCheckConstraint("ck_product_config_singleton", "\"ConfigId\" = 1"); + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b => + { + b.Property("RunId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunId")); + + b.Property("CancelReasonCodeId") + .HasColumnType("integer"); + + b.Property("CompletedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("OutputBinId") + .HasColumnType("integer"); + + b.Property("ReworkCount") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("ScaleFactor") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("TargetQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TemplateId") + .HasColumnType("integer"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("RunId"); + + b.HasIndex("CancelReasonCodeId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("OutputBinId"); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("TemplateId", "Status"); + + b.ToTable("production_runs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionTemplate", b => + { + b.Property("TemplateId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TemplateId")); + + b.Property("Annotations") + .HasColumnType("jsonb"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("TemplateId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("CreatedBy"); + + b.HasIndex("Status"); + + b.ToTable("production_templates", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", b => + { + b.Property("PurchaseInvoiceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PurchaseInvoiceId")); + + b.Property("BalanceAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VatTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.Property("VendorInvoiceDate") + .HasColumnType("timestamp with time zone"); + + b.Property("VendorInvoiceNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("VendorSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("VendorSnapshotTaxNo") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("PurchaseInvoiceId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("VendorId"); + + b.HasIndex("VendorId", "VendorInvoiceNo"); + + b.ToTable("purchase_invoices", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoiceLine", b => + { + b.Property("PurchaseInvoiceLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PurchaseInvoiceLineId")); + + b.Property("GrnId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PurchaseInvoiceId") + .HasColumnType("integer"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("VatTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("PurchaseInvoiceLineId"); + + b.HasIndex("GrnId") + .IsUnique(); + + b.HasIndex("PurchaseInvoiceId"); + + b.ToTable("purchase_invoice_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoicePayment", b => + { + b.Property("PurchaseInvoicePaymentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PurchaseInvoicePaymentId")); + + b.Property("Amount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BankAccountName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("GlBankAccountId") + .HasColumnType("bigint"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PaymentDate") + .HasColumnType("timestamp with time zone"); + + b.Property("PurchaseInvoiceId") + .HasColumnType("integer"); + + b.Property("Reference") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("PurchaseInvoicePaymentId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("PurchaseInvoiceId"); + + b.ToTable("purchase_invoice_payments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => + { + b.Property("PoId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PoId")); + + b.Property("ApprovalRequired") + .HasColumnType("boolean"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RequisitionId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.HasKey("PoId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("RequisitionId"); + + b.HasIndex("Status"); + + b.HasIndex("VendorId"); + + b.ToTable("purchase_orders", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturn", b => + { + b.Property("ReturnId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReasonCodeId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("ReturnId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("ReasonCodeId"); + + b.HasIndex("VendorId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("purchase_returns", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturnLine", b => + { + b.Property("ReturnLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnLineId")); + + b.Property("GrnLineId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReturnId") + .HasColumnType("integer"); + + b.HasKey("ReturnLineId"); + + b.HasIndex("GrnLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("ReturnId"); + + b.ToTable("purchase_return_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ReasonCode", b => + { + b.Property("ReasonCodeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReasonCodeId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Context") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.HasKey("ReasonCodeId"); + + b.HasIndex("Context", "Code") + .IsUnique(); + + b.ToTable("reason_codes", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => + { + b.Property("RequisitionId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RequisitionId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RequestedBy") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("RequisitionId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("RequestedBy"); + + b.HasIndex("Status"); + + b.ToTable("requisitions", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RequisitionLine", b => + { + b.Property("ReqLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReqLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RequiredBy") + .HasColumnType("date"); + + b.Property("RequisitionId") + .HasColumnType("integer"); + + b.HasKey("ReqLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RequisitionId"); + + b.ToTable("requisition_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => + { + b.Property("RfqId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RfqId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RequisitionId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("RfqId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("RequisitionId"); + + b.ToTable("rfqs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RfqLine", b => + { + b.Property("RfqLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RfqLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RfqId") + .HasColumnType("integer"); + + b.HasKey("RfqLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RfqId"); + + b.ToTable("rfq_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Role", b => + { + b.Property("RoleId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RoleId")); + + b.Property("AuthRoleId") + .HasColumnType("uuid") + .HasColumnName("auth_role_id"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsSystemRole") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("RoleId"); + + b.HasIndex("AuthRoleId") + .IsUnique(); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("roles", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RolePermission", b => + { + b.Property("RoleId") + .HasColumnType("integer"); + + b.Property("PermissionId") + .HasColumnType("integer"); + + b.HasKey("RoleId", "PermissionId"); + + b.HasIndex("PermissionId"); + + b.ToTable("role_permissions", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunEdge", b => + { + b.Property("RunEdgeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunEdgeId")); + + b.Property("ChildRunStageId") + .HasColumnType("integer"); + + b.Property("ParentRunStageId") + .HasColumnType("integer"); + + b.Property("RunId") + .HasColumnType("integer"); + + b.HasKey("RunEdgeId"); + + b.HasIndex("ChildRunStageId"); + + b.HasIndex("RunId"); + + b.HasIndex("ParentRunStageId", "ChildRunStageId") + .IsUnique(); + + b.ToTable("run_edges", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStage", b => + { + b.Property("RunStageId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunStageId")); + + b.Property("ActualEndAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ActualStartAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EstimatedMinutes") + .HasColumnType("integer"); + + b.Property("FieldDefs") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("FieldValues") + .HasColumnType("jsonb"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("PosX") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PosY") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RoleLabel") + .HasMaxLength(60) + .HasColumnType("character varying(60)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("RunId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("TemplateStageId") + .HasColumnType("integer"); + + b.HasKey("RunStageId"); + + b.HasIndex("TemplateStageId"); + + b.HasIndex("RunId", "Status"); + + b.ToTable("run_stages", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageEvent", b => + { + b.Property("EventId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EventId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Note") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Payload") + .HasColumnType("jsonb"); + + b.Property("RunId") + .HasColumnType("integer"); + + b.Property("RunStageId") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("EventId"); + + b.HasIndex("RunStageId"); + + b.HasIndex("UserId"); + + b.HasIndex("RunId", "EventId"); + + b.ToTable("run_stage_events", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageInput", b => + { + b.Property("RunInputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunInputId")); + + b.Property("ConsumedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ConsumedValue") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DeliveredQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("FromRunOutputId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("PlannedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyUnit") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ReturnedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReturnedValue") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RunStageId") + .HasColumnType("integer"); + + b.Property("Source") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("RunInputId"); + + b.HasIndex("FromRunOutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RunStageId"); + + b.ToTable("run_stage_inputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageOutput", b => + { + b.Property("RunOutputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunOutputId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("PlannedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ProducedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RunStageId") + .HasColumnType("integer"); + + b.Property("ScrapReasonCodeId") + .HasColumnType("integer"); + + b.Property("ScrappedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TransferredQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UomId") + .HasColumnType("integer"); + + b.HasKey("RunOutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RunStageId"); + + b.HasIndex("ScrapReasonCodeId"); + + b.HasIndex("UomId"); + + b.ToTable("run_stage_outputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalaryComponent", b => + { + b.Property("SalaryComponentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalaryComponentId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ComponentType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsEpfEtfApplicable") + .HasColumnType("boolean"); + + b.Property("IsTaxable") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("SalaryComponentId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_salary_components", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesDayEnd", b => + { + b.Property("SalesDayEndId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesDayEndId")); + + b.Property("BundleCount") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("BusinessDate") + .HasColumnType("date"); + + b.Property("CashierUserId") + .HasColumnType("integer"); + + b.Property("ClosedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ClosedBy") + .HasColumnType("integer"); + + b.Property("CostOfGoodsSold") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SlipCount") + .HasColumnType("integer"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("SalesDayEndId"); + + b.HasIndex("ClosedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("CashierUserId", "BusinessDate") + .IsUnique(); + + b.ToTable("sales_day_ends", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoice", b => + { + b.Property("SalesInvoiceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesInvoiceId")); + + b.Property("BalanceAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("CreatorUserId") + .HasColumnType("integer"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("CustomerSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CustomerSnapshotTaxNo") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("InvoiceDate") + .HasColumnType("timestamp with time zone"); + + b.Property("InvoiceNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("InvoiceType") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("B2C"); + + b.Property("NetPayable") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RoundOff") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesInvoiceId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatorUserId"); + + b.HasIndex("CustomerId"); + + b.HasIndex("InvoiceDate"); + + b.HasIndex("InvoiceNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_invoices", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoiceLine", b => + { + b.Property("SalesInvoiceLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesInvoiceLineId")); + + b.Property("BaseCost") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DiscountAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DiscountMode") + .HasColumnType("integer"); + + b.Property("DiscountPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("FreeQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("IsFreeIssue") + .HasColumnType("boolean"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("NetUnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ParentLineId") + .HasColumnType("integer"); + + b.Property("PriceSource") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SalesInvoiceId") + .HasColumnType("integer"); + + b.Property("TaxAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesInvoiceLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SalesInvoiceId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_invoice_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoicePayment", b => + { + b.Property("SalesInvoicePaymentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesInvoicePaymentId")); + + b.Property("Amount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BankAccountName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("GlBankAccountId") + .HasColumnType("bigint"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PaymentDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Reference") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("SalesInvoiceId") + .HasColumnType("integer"); + + b.HasKey("SalesInvoicePaymentId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("SalesInvoiceId"); + + b.ToTable("sales_invoice_payments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturn", b => + { + b.Property("ReturnId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReasonCodeId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("ReturnId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("CustomerId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("ReasonCodeId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_returns", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturnLine", b => + { + b.Property("ReturnLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReturnId") + .HasColumnType("integer"); + + b.Property("SalesInvoiceLineId") + .HasColumnType("integer"); + + b.HasKey("ReturnLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("ReturnId"); + + b.HasIndex("SalesInvoiceLineId"); + + b.ToTable("sales_return_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlip", b => + { + b.Property("SalesSlipId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesSlipId")); + + b.Property("BalanceAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CashierUserId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("CustomerSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DayEndId") + .HasColumnType("integer"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SlipDate") + .HasColumnType("timestamp with time zone"); + + b.Property("SlipNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesSlipId"); + + b.HasIndex("CashierUserId"); + + b.HasIndex("CustomerId"); + + b.HasIndex("DayEndId"); + + b.HasIndex("SlipDate"); + + b.HasIndex("SlipNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_slips", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlipLine", b => + { + b.Property("SalesSlipLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesSlipLineId")); + + b.Property("BaseCost") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DiscountAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DiscountMode") + .HasColumnType("integer"); + + b.Property("DiscountPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("FreeQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("IsFreeIssue") + .HasColumnType("boolean"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("NetUnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ParentLineId") + .HasColumnType("integer"); + + b.Property("PriceSource") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SalesSlipId") + .HasColumnType("integer"); + + b.Property("TaxAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesSlipLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SalesSlipId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_slip_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Serial", b => + { + b.Property("SerialId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SerialId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("SerialNo") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("SerialId"); + + b.HasIndex("ItemId", "SerialNo") + .IsUnique(); + + b.ToTable("serials", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageEdge", b => + { + b.Property("EdgeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EdgeId")); + + b.Property("ChildStageId") + .HasColumnType("integer"); + + b.Property("ParentStageId") + .HasColumnType("integer"); + + b.Property("TemplateId") + .HasColumnType("integer"); + + b.HasKey("EdgeId"); + + b.HasIndex("ChildStageId"); + + b.HasIndex("TemplateId"); + + b.HasIndex("ParentStageId", "ChildStageId") + .IsUnique(); + + b.ToTable("stage_edges", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageInput", b => + { + b.Property("InputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("InputId")); + + b.Property("FromOutputId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyPerBatch") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyUnit") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Source") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("StageId") + .HasColumnType("integer"); + + b.HasKey("InputId"); + + b.HasIndex("FromOutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("StageId"); + + b.ToTable("stage_inputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageOutput", b => + { + b.Property("OutputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("OutputId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("QtyPerBatch") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("StageId") + .HasColumnType("integer"); + + b.Property("UomId") + .HasColumnType("integer"); + + b.HasKey("OutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("StageId"); + + b.HasIndex("UomId"); + + b.ToTable("stage_outputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustment", b => + { + b.Property("AdjustmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AdjustmentId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReasonCodeId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("AdjustmentId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("ReasonCodeId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("stock_adjustments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustmentLine", b => + { + b.Property("AdjLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AdjLineId")); + + b.Property("AdjustmentId") + .HasColumnType("integer"); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyDelta") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.HasKey("AdjLineId"); + + b.HasIndex("AdjustmentId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SerialId"); + + b.ToTable("stock_adjustment_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCount", b => + { + b.Property("CountId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CountId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CountType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("CountId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("stock_counts", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCountLine", b => + { + b.Property("CountLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CountLineId")); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("CountId") + .HasColumnType("integer"); + + b.Property("CountedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("SystemQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Variance") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("CountLineId"); + + b.HasIndex("BinId"); + + b.HasIndex("CountId"); + + b.HasIndex("ItemId"); + + b.ToTable("stock_count_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLayer", b => + { + b.Property("LayerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LayerId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("GrnLineId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyReceived") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyRemaining") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReceiptDate") + .HasColumnType("timestamp with time zone"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("LayerId"); + + b.HasIndex("BatchId"); + + b.HasIndex("GrnLineId"); + + b.HasIndex("SerialId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("ItemId", "WarehouseId", "ReceiptDate", "LayerId"); + + b.ToTable("stock_layers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLedger", b => + { + b.Property("LedgerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LedgerId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Direction") + .IsRequired() + .HasMaxLength(5) + .HasColumnType("character varying(5)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyBase") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RunningBalance") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("SourceDocId") + .HasColumnType("integer"); + + b.Property("SourceDocType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.Property("Value") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("LedgerId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("SerialId"); + + b.HasIndex("UserId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("SourceDocType", "SourceDocId"); + + b.HasIndex("ItemId", "WarehouseId", "CreatedAt"); + + b.HasIndex("ItemId", "WarehouseId", "LedgerId"); + + b.ToTable("stock_ledger", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransfer", b => + { + b.Property("TransferId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TransferId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DestWarehouseId") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SrcWarehouseId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("TransferId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DestWarehouseId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("SrcWarehouseId"); + + b.HasIndex("Status"); + + b.ToTable("stock_transfers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransferLine", b => + { + b.Property("TransferLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TransferLineId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("DestBinId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyReceived") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("SrcBinId") + .HasColumnType("integer"); + + b.Property("TransferId") + .HasColumnType("integer"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.HasKey("TransferLineId"); + + b.HasIndex("BatchId"); + + b.HasIndex("DestBinId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SerialId"); + + b.HasIndex("SrcBinId"); + + b.HasIndex("TransferId"); + + b.ToTable("stock_transfer_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubCategory", b => + { + b.Property("SubCategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SubCategoryId")); + + b.Property("CategoryId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("SubCategoryId"); + + b.HasIndex("Status"); + + b.HasIndex("CategoryId", "Name") + .IsUnique(); + + b.ToTable("subcategories", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubNavItem", b => + { + b.Property("SubNavItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SubNavItemId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Href") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Icon") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("NavItemId") + .HasColumnType("integer"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.HasKey("SubNavItemId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("NavItemId"); + + b.ToTable("sub_nav_items", (string)null); + + b.HasData( + new + { + SubNavItemId = 1, + Code = "products.item", + Href = "/dashboard/products", + Label = "Item", + NavItemId = 2, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 2, + Code = "products.category", + Href = "/dashboard/products/categories", + Label = "Category", + NavItemId = 2, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 3, + Code = "products.brand", + Href = "/dashboard/products/brands", + Label = "Brand", + NavItemId = 2, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 4, + Code = "products.item-type", + Href = "/dashboard/products/item-types", + Label = "Item Type", + NavItemId = 2, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 5, + Code = "products.uom", + Href = "/dashboard/products/uoms", + Label = "UOM", + NavItemId = 2, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 6, + Code = "products.configuration", + Href = "/dashboard/products/settings", + Label = "Configuration", + NavItemId = 2, + SortOrder = 6, + Status = "Active" + }, + new + { + SubNavItemId = 29, + Code = "settings.branches", + Href = "/dashboard/settings/branches", + Label = "Branches", + NavItemId = 9, + SortOrder = 0, + Status = "Active" + }, + new + { + SubNavItemId = 7, + Code = "settings.roles", + Href = "/dashboard/settings/roles", + Label = "Roles", + NavItemId = 9, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 8, + Code = "settings.users", + Href = "/dashboard/settings/users", + Label = "Users", + NavItemId = 9, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 24, + Code = "settings.notification-config", + Href = "/dashboard/settings/notification-config", + Label = "Notification Config", + NavItemId = 9, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 40, + Code = "sales.invoices", + Href = "/dashboard/sales/invoices", + Label = "Sales", + NavItemId = 13, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 23, + Code = "sales.bundle-templates", + Href = "/dashboard/sales/bundles/templates", + Label = "Bundle Templates", + NavItemId = 13, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 41, + Code = "sales.free-issues", + Href = "/dashboard/sales/free-issues", + Label = "Free Issues", + NavItemId = 13, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 42, + Code = "sales.day-end", + Href = "/dashboard/sales/day-end", + Label = "Day End", + NavItemId = 13, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 30, + Code = "procurement.vendors", + Href = "/dashboard/vendors", + Label = "Vendors", + NavItemId = 4, + SortOrder = 0, + Status = "Active" + }, + new + { + SubNavItemId = 17, + Code = "procurement.requisitions", + Href = "/dashboard/procurement/requisitions", + Label = "Requisitions", + NavItemId = 4, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 18, + Code = "procurement.rfqs", + Href = "/dashboard/procurement/rfqs", + Label = "RFQs", + NavItemId = 4, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 19, + Code = "procurement.purchase-orders", + Href = "/dashboard/procurement/purchase-orders", + Label = "Purchase Orders", + NavItemId = 4, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 20, + Code = "procurement.purchase-returns", + Href = "/dashboard/procurement/purchase-returns", + Label = "Purchase Returns", + NavItemId = 4, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 28, + Code = "procurement.purchase-invoices", + Href = "/dashboard/procurement/purchase-invoices", + Label = "Purchase Invoices", + NavItemId = 4, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 9, + Code = "ledgers.trial-balance", + Href = "/dashboard/ledgers/trial-balance", + Label = "Trial Balance", + NavItemId = 11, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 10, + Code = "ledgers.balance-sheet", + Href = "/dashboard/ledgers/balance-sheet", + Label = "Balance Sheet", + NavItemId = 11, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 11, + Code = "ledgers.general-ledger", + Href = "/dashboard/ledgers/general-ledger", + Label = "General Ledger", + NavItemId = 11, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 12, + Code = "ledgers.profit-and-loss", + Href = "/dashboard/ledgers/profit-and-loss", + Label = "Profit & Loss", + NavItemId = 11, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 13, + Code = "ledgers.cash-flow", + Href = "/dashboard/ledgers/cash-flow", + Label = "Cash Flow", + NavItemId = 11, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 14, + Code = "ledgers.budget-vs-actual", + Href = "/dashboard/ledgers/budget-vs-actual", + Label = "Budget vs Actual", + NavItemId = 11, + SortOrder = 6, + Status = "Active" + }, + new + { + SubNavItemId = 16, + Code = "ledgers.tax-report", + Href = "/dashboard/ledgers/tax-report", + Label = "Tax Report", + NavItemId = 11, + SortOrder = 7, + Status = "Active" + }, + new + { + SubNavItemId = 15, + Code = "accounts.bank-accounts", + Href = "/dashboard/accounts/bank-accounts", + Label = "Cash / Bank Accounts", + NavItemId = 12, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 21, + Code = "accounts.cheque-books", + Href = "/dashboard/accounts/cheque-books", + Label = "Cheque Books", + NavItemId = 12, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 22, + Code = "accounts.received-cheques", + Href = "/dashboard/accounts/received-cheques", + Label = "Received Cheques", + NavItemId = 12, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 27, + Code = "production.templates", + Href = "/dashboard/production/templates", + Label = "Templates", + NavItemId = 14, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 25, + Code = "production.runs", + Href = "/dashboard/production/runs", + Label = "Runs", + NavItemId = 14, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 26, + Code = "production.produced", + Href = "/dashboard/production/produced", + Label = "Produced", + NavItemId = 14, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 31, + Code = "stock.ledger", + Href = "/dashboard/stock/ledger", + Label = "Stock Ledger", + NavItemId = 6, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 32, + Code = "stock.enquiry", + Href = "/dashboard/stock/enquiry", + Label = "Stock Enquiry", + NavItemId = 6, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 33, + Code = "stock.valuation", + Href = "/dashboard/stock/valuation", + Label = "Valuation", + NavItemId = 6, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 34, + Code = "stock.transfers", + Href = "/dashboard/stock/transfers", + Label = "Transfers", + NavItemId = 6, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 35, + Code = "stock.adjustments", + Href = "/dashboard/stock/adjustments", + Label = "Adjustments", + NavItemId = 6, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 36, + Code = "stock.counts", + Href = "/dashboard/stock/counts", + Label = "Counts", + NavItemId = 6, + SortOrder = 6, + Status = "Active" + }, + new + { + SubNavItemId = 37, + Code = "stock.reorder-alerts", + Href = "/dashboard/stock/reorder-alerts", + Label = "Reorder Alerts", + NavItemId = 6, + SortOrder = 7, + Status = "Active" + }, + new + { + SubNavItemId = 38, + Code = "stock.wastage", + Href = "/dashboard/stock/wastage", + Label = "Wastage", + NavItemId = 6, + SortOrder = 8, + Status = "Active" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicket", b => + { + b.Property("TicketId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TicketId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Subject") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.HasKey("TicketId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("Status"); + + b.ToTable("support_tickets", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicketMessage", b => + { + b.Property("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("MessageId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsFromAdmin") + .HasColumnType("boolean"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("SenderUserId") + .HasColumnType("integer"); + + b.Property("TicketId") + .HasColumnType("integer"); + + b.HasKey("MessageId"); + + b.HasIndex("TicketId", "CreatedAt"); + + b.ToTable("support_ticket_messages", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TaxSlab", b => + { + b.Property("TaxSlabId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TaxSlabId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveTo") + .HasColumnType("timestamp with time zone"); + + b.Property("LowerBound") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("Rate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("UpperBound") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.HasKey("TaxSlabId"); + + b.HasIndex("EffectiveFrom"); + + b.ToTable("hr_tax_slabs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => + { + b.Property("StageId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("StageId")); + + b.Property("EstimatedMinutes") + .HasColumnType("integer"); + + b.Property("FieldDefs") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("PosX") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PosY") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RoleLabel") + .HasMaxLength(60) + .HasColumnType("character varying(60)"); + + b.Property("TemplateId") + .HasColumnType("integer"); + + b.HasKey("StageId"); + + b.HasIndex("TemplateId"); + + b.ToTable("template_stages", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Uom", b => + { + b.Property("UomId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("UomId")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("UomId"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("uoms", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.User", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("UserId")); + + b.Property("AuthUserId") + .HasColumnType("uuid") + .HasColumnName("auth_user_id"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Email") + .HasMaxLength(320) + .HasColumnType("character varying(320)"); + + b.Property("RoleId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("UserId"); + + b.HasIndex("AuthUserId") + .IsUnique(); + + b.HasIndex("Email") + .IsUnique(); + + b.HasIndex("RoleId"); + + b.HasIndex("Username") + .IsUnique(); + + b.ToTable("users", (string)null); + + b.HasData( + new + { + UserId = 1, + DisplayName = "System", + Status = "Active", + Username = "system" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Vendor", b => + { + b.Property("VendorId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("VendorId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Currency") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(3) + .HasColumnType("character varying(3)") + .HasDefaultValue("LKR"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TaxReg") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Terms") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("VendorId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("vendors", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => + { + b.Property("QuotationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("QuotationId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("RfqId") + .HasColumnType("integer"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.HasKey("QuotationId"); + + b.HasIndex("VendorId"); + + b.HasIndex("RfqId", "VendorId") + .IsUnique(); + + b.ToTable("vendor_quotations", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotationLine", b => + { + b.Property("QuotationLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("QuotationLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LeadDays") + .HasColumnType("integer"); + + b.Property("QuotationId") + .HasColumnType("integer"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("QuotationLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("QuotationId"); + + b.ToTable("vendor_quotation_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Warehouse", b => + { + b.Property("WarehouseId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("WarehouseId")); + + b.Property("Address") + .HasColumnType("text"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Phone") + .HasColumnType("text"); + + b.HasKey("WarehouseId"); + + b.HasIndex("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("warehouses", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.WorkShift", b => + { + b.Property("WorkShiftId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("WorkShiftId")); + + b.Property("BreakMinutes") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EndTime") + .HasColumnType("interval"); + + b.Property("GraceMinutes") + .HasColumnType("integer"); + + b.Property("IsOvernight") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("OtMultiplier") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("StandardWorkingMinutes") + .HasColumnType("integer"); + + b.Property("StartTime") + .HasColumnType("interval"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WorkingDaysMask") + .HasColumnType("integer"); + + b.HasKey("WorkShiftId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_work_shifts", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceRecord", b => + { + b.HasOne("ERPCore.Domain.Entities.AttendanceUploadBatch", "AttendanceUploadBatch") + .WithMany() + .HasForeignKey("AttendanceUploadBatchId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.WorkShift", "WorkShift") + .WithMany() + .HasForeignKey("WorkShiftId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("AttendanceUploadBatch"); + + b.Navigation("Employee"); + + b.Navigation("WorkShift"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AuditLog", b => + { + b.HasOne("ERPCore.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Batch", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Bin", b => + { + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany("Bins") + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BranchConfig", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSale", b => + { + b.HasOne("ERPCore.Domain.Entities.BundleSaleTemplate", "BundleSaleTemplate") + .WithMany() + .HasForeignKey("BundleSaleTemplateId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "CashierUser") + .WithMany() + .HasForeignKey("CashierUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesDayEnd", "DayEnd") + .WithMany("BundleSales") + .HasForeignKey("DayEndId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BundleSaleTemplate"); + + b.Navigation("CashierUser"); + + b.Navigation("Customer"); + + b.Navigation("DayEnd"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleLine", b => + { + b.HasOne("ERPCore.Domain.Entities.BundleSale", "BundleSale") + .WithMany("Lines") + .HasForeignKey("BundleSaleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BundleSale"); + + b.Navigation("Item"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplateLine", b => + { + b.HasOne("ERPCore.Domain.Entities.BundleSaleTemplate", "BundleSaleTemplate") + .WithMany("Lines") + .HasForeignKey("BundleSaleTemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BundleSaleTemplate"); + + b.Navigation("Item"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Customer", b => + { + b.HasOne("ERPCore.Domain.Entities.Warehouse", "DefaultWarehouse") + .WithMany() + .HasForeignKey("DefaultWarehouseId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("DefaultWarehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Department", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Employee", "HeadEmployee") + .WithMany() + .HasForeignKey("HeadEmployeeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Department", "ParentDepartment") + .WithMany() + .HasForeignKey("ParentDepartmentId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Branch"); + + b.Navigation("HeadEmployee"); + + b.Navigation("ParentDepartment"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Employee", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Department", "Department") + .WithMany() + .HasForeignKey("DepartmentId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Designation", "Designation") + .WithMany() + .HasForeignKey("DesignationId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.EmploymentType", "EmploymentType") + .WithMany() + .HasForeignKey("EmploymentTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Employee", "ReportingManager") + .WithMany() + .HasForeignKey("ReportingManagerId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithOne() + .HasForeignKey("ERPCore.Domain.Entities.Employee", "UserId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.WorkShift", "WorkShift") + .WithMany() + .HasForeignKey("WorkShiftId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Department"); + + b.Navigation("Designation"); + + b.Navigation("EmploymentType"); + + b.Navigation("ReportingManager"); + + b.Navigation("User"); + + b.Navigation("WorkShift"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeBankDetail", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeDocument", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.HrDocumentType", "HrDocumentType") + .WithMany() + .HasForeignKey("HrDocumentTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("HrDocumentType"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeLoan", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructure", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructureLine", b => + { + b.HasOne("ERPCore.Domain.Entities.EmployeeSalaryStructure", "EmployeeSalaryStructure") + .WithMany("Lines") + .HasForeignKey("EmployeeSalaryStructureId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalaryComponent", "SalaryComponent") + .WithMany() + .HasForeignKey("SalaryComponentId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("EmployeeSalaryStructure"); + + b.Navigation("SalaryComponent"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Grn", 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.HasOne("ERPCore.Domain.Entities.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("PoId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.PurchaseInvoice", "PurchaseInvoice") + .WithMany() + .HasForeignKey("PurchaseInvoiceId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("PurchaseInvoice"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Vendor"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", "Batch") + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", "Bin") + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Grn", "Grn") + .WithMany("Lines") + .HasForeignKey("GrnId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PoLine", "PoLine") + .WithMany() + .HasForeignKey("PoLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Batch"); + + b.Navigation("Bin"); + + b.Navigation("Grn"); + + b.Navigation("Item"); + + b.Navigation("PoLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLineWarrantyNumber", b => + { + b.HasOne("ERPCore.Domain.Entities.GrnLine", "GrnLine") + .WithMany("WarrantyNumbers") + .HasForeignKey("GrnLineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GrnLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Item", b => + { + b.HasOne("ERPCore.Domain.Entities.Uom", "BaseUom") + .WithMany() + .HasForeignKey("BaseUomId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Brand", "Brand") + .WithMany() + .HasForeignKey("BrandId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Category", "Category") + .WithMany() + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "DefaultVendor") + .WithMany() + .HasForeignKey("DefaultVendorId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.SubCategory", "SubCategory") + .WithMany() + .HasForeignKey("SubCategoryId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("BaseUom"); + + b.Navigation("Brand"); + + b.Navigation("Category"); + + b.Navigation("DefaultVendor"); + + b.Navigation("SubCategory"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ItemReorder", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany("ReorderSettings") + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveBalance", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.LeaveType", "LeaveType") + .WithMany() + .HasForeignKey("LeaveTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("LeaveType"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveRequest", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.LeaveType", "LeaveType") + .WithMany() + .HasForeignKey("LeaveTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("LeaveType"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoanInstallment", b => + { + b.HasOne("ERPCore.Domain.Entities.EmployeeLoan", "EmployeeLoan") + .WithMany("Installments") + .HasForeignKey("EmployeeLoanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PayrollRun", "PayrollRun") + .WithMany() + .HasForeignKey("PayrollRunId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("EmployeeLoan"); + + b.Navigation("PayrollRun"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoginActivity", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfigModule", b => + { + b.HasOne("ERPCore.Domain.Entities.NotificationConfig", "NotificationConfig") + .WithMany("Modules") + .HasForeignKey("NotificationConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("NotificationConfig"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationRecipient", b => + { + b.HasOne("ERPCore.Domain.Entities.Notification", "Notification") + .WithMany("Recipients") + .HasForeignKey("NotificationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Notification"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PayrollRun", "PayrollRun") + .WithMany("Lines") + .HasForeignKey("PayrollRunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("PayrollRun"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLineComponent", b => + { + b.HasOne("ERPCore.Domain.Entities.PayrollLine", "PayrollLine") + .WithMany("Components") + .HasForeignKey("PayrollLineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalaryComponent", "SalaryComponent") + .WithMany() + .HasForeignKey("SalaryComponentId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("PayrollLine"); + + b.Navigation("SalaryComponent"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollRun", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Branch"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Payslip", b => + { + b.HasOne("ERPCore.Domain.Entities.PayrollLine", "PayrollLine") + .WithOne() + .HasForeignKey("ERPCore.Domain.Entities.Payslip", "PayrollLineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PayrollLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Permission", b => + { + b.HasOne("ERPCore.Domain.Entities.NavItem", "NavItem") + .WithMany() + .HasForeignKey("NavItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ERPCore.Domain.Entities.SubNavItem", "SubNavItem") + .WithMany() + .HasForeignKey("SubNavItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("NavItem"); + + b.Navigation("SubNavItem"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PoLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseOrder", "PurchaseOrder") + .WithMany("Lines") + .HasForeignKey("PoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductConfig", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b => + { + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "CancelReason") + .WithMany() + .HasForeignKey("CancelReasonCodeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Bin", "OutputBin") + .WithMany() + .HasForeignKey("OutputBinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") + .WithMany("Runs") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CancelReason"); + + b.Navigation("Creator"); + + b.Navigation("OutputBin"); + + b.Navigation("Template"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionTemplate", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoiceLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Grn", "Grn") + .WithMany() + .HasForeignKey("GrnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseInvoice", "PurchaseInvoice") + .WithMany("Lines") + .HasForeignKey("PurchaseInvoiceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Grn"); + + b.Navigation("PurchaseInvoice"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoicePayment", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseInvoice", "PurchaseInvoice") + .WithMany("Payments") + .HasForeignKey("PurchaseInvoiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("PurchaseInvoice"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") + .WithMany() + .HasForeignKey("RequisitionId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("Requisition"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturn", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ReasonCode") + .WithMany() + .HasForeignKey("ReasonCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("ReasonCode"); + + b.Navigation("Vendor"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturnLine", b => + { + b.HasOne("ERPCore.Domain.Entities.GrnLine", "GrnLine") + .WithMany() + .HasForeignKey("GrnLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseReturn", "Return") + .WithMany("Lines") + .HasForeignKey("ReturnId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GrnLine"); + + b.Navigation("Item"); + + b.Navigation("Return"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Requester") + .WithMany() + .HasForeignKey("RequestedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Requester"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RequisitionLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") + .WithMany("Lines") + .HasForeignKey("RequisitionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Requisition"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => + { + b.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") + .WithMany() + .HasForeignKey("RequisitionId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Requisition"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RfqLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Rfq", "Rfq") + .WithMany("Lines") + .HasForeignKey("RfqId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Rfq"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RolePermission", b => + { + b.HasOne("ERPCore.Domain.Entities.Permission", "Permission") + .WithMany() + .HasForeignKey("PermissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Role", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Permission"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunEdge", b => + { + b.HasOne("ERPCore.Domain.Entities.RunStage", "ChildRunStage") + .WithMany() + .HasForeignKey("ChildRunStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "ParentRunStage") + .WithMany() + .HasForeignKey("ParentRunStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ProductionRun", "Run") + .WithMany("Edges") + .HasForeignKey("RunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildRunStage"); + + b.Navigation("ParentRunStage"); + + b.Navigation("Run"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStage", b => + { + b.HasOne("ERPCore.Domain.Entities.ProductionRun", "Run") + .WithMany("Stages") + .HasForeignKey("RunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "TemplateStage") + .WithMany() + .HasForeignKey("TemplateStageId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Run"); + + b.Navigation("TemplateStage"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageEvent", b => + { + b.HasOne("ERPCore.Domain.Entities.ProductionRun", "Run") + .WithMany("Events") + .HasForeignKey("RunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "RunStage") + .WithMany("Events") + .HasForeignKey("RunStageId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Run"); + + b.Navigation("RunStage"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageInput", b => + { + b.HasOne("ERPCore.Domain.Entities.RunStageOutput", "FromRunOutput") + .WithMany() + .HasForeignKey("FromRunOutputId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "RunStage") + .WithMany("Inputs") + .HasForeignKey("RunStageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromRunOutput"); + + b.Navigation("Item"); + + b.Navigation("RunStage"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageOutput", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "RunStage") + .WithMany("Outputs") + .HasForeignKey("RunStageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ScrapReason") + .WithMany() + .HasForeignKey("ScrapReasonCodeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Uom", "Uom") + .WithMany() + .HasForeignKey("UomId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Item"); + + b.Navigation("RunStage"); + + b.Navigation("ScrapReason"); + + b.Navigation("Uom"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesDayEnd", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "CashierUser") + .WithMany() + .HasForeignKey("CashierUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "ClosedByUser") + .WithMany() + .HasForeignKey("ClosedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CashierUser"); + + b.Navigation("ClosedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoice", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatorUserId"); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("Customer"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoiceLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesInvoice", "SalesInvoice") + .WithMany("Lines") + .HasForeignKey("SalesInvoiceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SalesInvoice"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoicePayment", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesInvoice", "SalesInvoice") + .WithMany("Payments") + .HasForeignKey("SalesInvoiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("SalesInvoice"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturn", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ReasonCode") + .WithMany() + .HasForeignKey("ReasonCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("Customer"); + + b.Navigation("ReasonCode"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturnLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesReturn", "Return") + .WithMany("Lines") + .HasForeignKey("ReturnId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesInvoiceLine", "SalesInvoiceLine") + .WithMany() + .HasForeignKey("SalesInvoiceLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Item"); + + b.Navigation("Return"); + + b.Navigation("SalesInvoiceLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlip", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "CashierUser") + .WithMany() + .HasForeignKey("CashierUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesDayEnd", "DayEnd") + .WithMany("Slips") + .HasForeignKey("DayEndId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CashierUser"); + + b.Navigation("Customer"); + + b.Navigation("DayEnd"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlipLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesSlip", "SalesSlip") + .WithMany("Lines") + .HasForeignKey("SalesSlipId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SalesSlip"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Serial", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageEdge", b => + { + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "ChildStage") + .WithMany() + .HasForeignKey("ChildStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "ParentStage") + .WithMany() + .HasForeignKey("ParentStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") + .WithMany("Edges") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildStage"); + + b.Navigation("ParentStage"); + + b.Navigation("Template"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageInput", b => + { + b.HasOne("ERPCore.Domain.Entities.StageOutput", "FromOutput") + .WithMany() + .HasForeignKey("FromOutputId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "Stage") + .WithMany("Inputs") + .HasForeignKey("StageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromOutput"); + + b.Navigation("Item"); + + b.Navigation("Stage"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageOutput", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "Stage") + .WithMany("Outputs") + .HasForeignKey("StageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Uom", "Uom") + .WithMany() + .HasForeignKey("UomId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Item"); + + b.Navigation("Stage"); + + b.Navigation("Uom"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustment", 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.HasOne("ERPCore.Domain.Entities.ReasonCode", "ReasonCode") + .WithMany() + .HasForeignKey("ReasonCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("ReasonCode"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustmentLine", b => + { + b.HasOne("ERPCore.Domain.Entities.StockAdjustment", "Adjustment") + .WithMany("Lines") + .HasForeignKey("AdjustmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Batch", null) + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", null) + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Adjustment"); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCount", 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.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCountLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.StockCount", "Count") + .WithMany("Lines") + .HasForeignKey("CountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Count"); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLayer", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", "Batch") + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.GrnLine", "GrnLine") + .WithMany() + .HasForeignKey("GrnLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", "Serial") + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Batch"); + + b.Navigation("GrnLine"); + + b.Navigation("Item"); + + b.Navigation("Serial"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLedger", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", null) + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", null) + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", null) + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", null) + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransfer", 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.HasOne("ERPCore.Domain.Entities.Warehouse", "DestWarehouse") + .WithMany() + .HasForeignKey("DestWarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "SrcWarehouse") + .WithMany() + .HasForeignKey("SrcWarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("DestWarehouse"); + + b.Navigation("SrcWarehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransferLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", null) + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("DestBinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", null) + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("SrcBinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.StockTransfer", "Transfer") + .WithMany("Lines") + .HasForeignKey("TransferId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Transfer"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubCategory", b => + { + b.HasOne("ERPCore.Domain.Entities.Category", "Category") + .WithMany("SubCategories") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubNavItem", b => + { + b.HasOne("ERPCore.Domain.Entities.NavItem", "NavItem") + .WithMany("Children") + .HasForeignKey("NavItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("NavItem"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicketMessage", b => + { + b.HasOne("ERPCore.Domain.Entities.SupportTicket", "Ticket") + .WithMany("Messages") + .HasForeignKey("TicketId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ticket"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => + { + b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") + .WithMany("Stages") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Template"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.User", b => + { + b.HasOne("ERPCore.Domain.Entities.Role", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => + { + b.HasOne("ERPCore.Domain.Entities.Rfq", "Rfq") + .WithMany("Quotations") + .HasForeignKey("RfqId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Rfq"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotationLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.VendorQuotation", "Quotation") + .WithMany("Lines") + .HasForeignKey("QuotationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Quotation"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Warehouse", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSale", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplate", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Category", b => + { + b.Navigation("SubCategories"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeLoan", b => + { + b.Navigation("Installments"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructure", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Grn", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLine", b => + { + b.Navigation("WarrantyNumbers"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Item", b => + { + b.Navigation("ReorderSettings"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NavItem", b => + { + b.Navigation("Children"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Notification", b => + { + b.Navigation("Recipients"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => + { + b.Navigation("Modules"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => + { + b.Navigation("Components"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollRun", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b => + { + b.Navigation("Edges"); + + b.Navigation("Events"); + + b.Navigation("Stages"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionTemplate", b => + { + b.Navigation("Edges"); + + b.Navigation("Runs"); + + b.Navigation("Stages"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", b => + { + b.Navigation("Lines"); + + b.Navigation("Payments"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturn", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => + { + b.Navigation("Lines"); + + b.Navigation("Quotations"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStage", b => + { + b.Navigation("Events"); + + b.Navigation("Inputs"); + + b.Navigation("Outputs"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesDayEnd", b => + { + b.Navigation("BundleSales"); + + b.Navigation("Slips"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoice", b => + { + b.Navigation("Lines"); + + b.Navigation("Payments"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturn", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlip", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustment", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCount", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransfer", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicket", b => + { + b.Navigation("Messages"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => + { + b.Navigation("Inputs"); + + b.Navigation("Outputs"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Warehouse", b => + { + b.Navigation("Bins"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Backend/ERPCore/Migrations/20260915102006_AddWarehouseBranchingToggle.cs b/Backend/ERPCore/Migrations/20260915102006_AddWarehouseBranchingToggle.cs new file mode 100644 index 0000000..6298d07 --- /dev/null +++ b/Backend/ERPCore/Migrations/20260915102006_AddWarehouseBranchingToggle.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace ERPCore.Migrations +{ + /// + public partial class AddWarehouseBranchingToggle : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "WarehouseBranchingEnabled", + table: "branch_config", + type: "boolean", + nullable: false, + defaultValue: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "WarehouseBranchingEnabled", + table: "branch_config"); + } + } +} diff --git a/Backend/ERPCore/Migrations/20260915110359_AddPurchaseOrderApprovalAudit.Designer.cs b/Backend/ERPCore/Migrations/20260915110359_AddPurchaseOrderApprovalAudit.Designer.cs new file mode 100644 index 0000000..7608d30 --- /dev/null +++ b/Backend/ERPCore/Migrations/20260915110359_AddPurchaseOrderApprovalAudit.Designer.cs @@ -0,0 +1,8443 @@ +// +using System; +using ERPCore.Infra.Persistence; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace ERPCore.Migrations +{ + [DbContext(typeof(ErpDbContext))] + [Migration("20260915110359_AddPurchaseOrderApprovalAudit")] + partial class AddPurchaseOrderApprovalAudit + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.9") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceRecord", b => + { + b.Property("AttendanceRecordId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AttendanceRecordId")); + + b.Property("AttendanceDate") + .HasColumnType("timestamp with time zone"); + + b.Property("AttendanceStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("AttendanceUploadBatchId") + .HasColumnType("integer"); + + b.Property("CheckIn") + .HasColumnType("interval"); + + b.Property("CheckOut") + .HasColumnType("interval"); + + b.Property("DuplicateOfAttendanceRecordId") + .HasColumnType("integer"); + + b.Property("EarlyLeaveMinutes") + .HasColumnType("integer"); + + b.Property("EditedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EditedBy") + .HasColumnType("integer"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("IsManualOverride") + .HasColumnType("boolean"); + + b.Property("LateMinutes") + .HasColumnType("integer"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("OvertimeMinutes") + .HasColumnType("integer"); + + b.Property("RowValidationStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("WorkShiftId") + .HasColumnType("integer"); + + b.Property("WorkingMinutes") + .HasColumnType("integer"); + + b.HasKey("AttendanceRecordId"); + + b.HasIndex("AttendanceUploadBatchId"); + + b.HasIndex("WorkShiftId"); + + b.HasIndex("EmployeeId", "AttendanceDate"); + + b.ToTable("hr_attendance_records", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceUploadBatch", b => + { + b.Property("AttendanceUploadBatchId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AttendanceUploadBatchId")); + + b.Property("ConfirmedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ConfirmedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("OriginalFileName") + .HasMaxLength(260) + .HasColumnType("character varying(260)"); + + b.Property("PeriodEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("PeriodStart") + .HasColumnType("timestamp with time zone"); + + b.Property("RowCountDuplicate") + .HasColumnType("integer"); + + b.Property("RowCountError") + .HasColumnType("integer"); + + b.Property("RowCountTotal") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SourceType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UploadedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UploadedBy") + .HasColumnType("integer"); + + b.HasKey("AttendanceUploadBatchId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("PeriodStart", "PeriodEnd"); + + b.ToTable("hr_attendance_upload_batches", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AuditLog", b => + { + b.Property("AuditId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AuditId")); + + b.Property("Action") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("ChangeSet") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EntityId") + .HasColumnType("integer"); + + b.Property("EntityType") + .IsRequired() + .HasMaxLength(80) + .HasColumnType("character varying(80)"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("AuditId"); + + b.HasIndex("CreatedAt"); + + b.HasIndex("UserId"); + + b.HasIndex("EntityType", "EntityId"); + + b.ToTable("audit_logs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Batch", b => + { + b.Property("BatchId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BatchId")); + + b.Property("BatchNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ExpiryDate") + .HasColumnType("date"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.HasKey("BatchId"); + + b.HasIndex("ItemId", "BatchNo") + .IsUnique(); + + b.ToTable("batches", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Bin", b => + { + b.Property("BinId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BinId")); + + b.Property("BinType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BinId"); + + b.HasIndex("WarehouseId", "Code") + .IsUnique(); + + b.ToTable("bins", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Branch", b => + { + b.Property("BranchId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BranchId")); + + b.Property("Address") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("PhoneNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_branches", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BranchConfig", b => + { + b.Property("ConfigId") + .HasColumnType("integer"); + + b.Property("BranchingEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.Property("WarehouseBranchingEnabled") + .HasColumnType("boolean"); + + b.HasKey("ConfigId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("branch_config", null, t => + { + t.HasCheckConstraint("ck_branch_config_singleton", "\"ConfigId\" = 1"); + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Brand", b => + { + b.Property("BrandId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BrandId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("BrandId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("brands", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSale", b => + { + b.Property("BundleSaleId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleId")); + + b.Property("BundleCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BundleDate") + .HasColumnType("timestamp with time zone"); + + b.Property("BundleName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("BundleNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BundlePrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BundleSaleTemplateId") + .HasColumnType("integer"); + + b.Property("CashierUserId") + .HasColumnType("integer"); + + b.Property("ComponentSubtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("CustomerSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DayEndId") + .HasColumnType("integer"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("MarginAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BundleSaleId"); + + b.HasIndex("BundleNo") + .IsUnique(); + + b.HasIndex("BundleSaleTemplateId"); + + b.HasIndex("CashierUserId"); + + b.HasIndex("CustomerId"); + + b.HasIndex("DayEndId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("bundle_sales", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleLine", b => + { + b.Property("BundleSaleLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleLineId")); + + b.Property("BundleSaleId") + .HasColumnType("integer"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("IncludeInBundle") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("IsComponent") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ParentLineId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BundleSaleLineId"); + + b.HasIndex("BundleSaleId"); + + b.HasIndex("ItemId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("bundle_sale_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplate", b => + { + b.Property("BundleSaleTemplateId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleTemplateId")); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TemplateCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("TemplateName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("BundleSaleTemplateId"); + + b.HasIndex("TemplateCode") + .IsUnique(); + + b.ToTable("bundle_sale_templates", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplateLine", b => + { + b.Property("BundleSaleTemplateLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleTemplateLineId")); + + b.Property("BundleSaleTemplateId") + .HasColumnType("integer"); + + b.Property("IncludeInBundle") + .HasColumnType("boolean"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SortOrder") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BundleSaleTemplateLineId"); + + b.HasIndex("BundleSaleTemplateId"); + + b.HasIndex("ItemId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("bundle_sale_template_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Category", b => + { + b.Property("CategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CategoryId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("CategoryId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("categories", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Customer", b => + { + b.Property("CustomerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CustomerId")); + + b.Property("AddressLine1") + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("AddressLine2") + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("City") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Country") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreditDays") + .HasColumnType("integer"); + + b.Property("CreditLimit") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CustomerCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CustomerType") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("B2C"); + + b.Property("DefaultWarehouseId") + .HasColumnType("integer"); + + b.Property("DisplayName") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Email") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Phone") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TaxRegistrationNo") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("CustomerId"); + + b.HasIndex("CustomerCode") + .IsUnique(); + + b.HasIndex("CustomerType"); + + b.HasIndex("DefaultWarehouseId"); + + b.HasIndex("Status"); + + b.ToTable("customers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Department", b => + { + b.Property("DepartmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("DepartmentId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("HeadEmployeeId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("ParentDepartmentId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("DepartmentId"); + + b.HasIndex("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("HeadEmployeeId"); + + b.HasIndex("ParentDepartmentId"); + + b.HasIndex("Status"); + + b.ToTable("hr_departments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Designation", b => + { + b.Property("DesignationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("DesignationId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("DesignationId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_designations", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Employee", b => + { + b.Property("EmployeeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeId")); + + b.Property("AddressLine1") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("AddressLine2") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("City") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ConfirmationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Country") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DateOfBirth") + .HasColumnType("timestamp with time zone"); + + b.Property("DepartmentId") + .HasColumnType("integer"); + + b.Property("DesignationId") + .HasColumnType("integer"); + + b.Property("Email") + .HasMaxLength(320) + .HasColumnType("character varying(320)"); + + b.Property("EmergencyContactName") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("EmergencyContactPhone") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmergencyContactRelationship") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("EmployeeCode") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmploymentTypeId") + .HasColumnType("integer"); + + b.Property("EpfNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EtfNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Gender") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("HireDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LastWorkingDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Nationality") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Nic") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PersonalMobile") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PostalCode") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ProfilePhotoPath") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("ReportingManagerId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TaxIdentificationNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.Property("WorkShiftId") + .HasColumnType("integer"); + + b.HasKey("EmployeeId"); + + b.HasIndex("BranchId"); + + b.HasIndex("DepartmentId"); + + b.HasIndex("DesignationId"); + + b.HasIndex("Email"); + + b.HasIndex("EmployeeCode") + .IsUnique(); + + b.HasIndex("EmploymentTypeId"); + + b.HasIndex("ReportingManagerId"); + + b.HasIndex("Status"); + + b.HasIndex("UserId") + .IsUnique(); + + b.HasIndex("WorkShiftId"); + + b.ToTable("hr_employees", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeBankDetail", b => + { + b.Property("EmployeeBankDetailId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeBankDetailId")); + + b.Property("AccountHolderName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("AccountNumber") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BankName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("BranchName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("IsPrimary") + .HasColumnType("boolean"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("SwiftCode") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("EmployeeBankDetailId"); + + b.HasIndex("EmployeeId"); + + b.ToTable("hr_employee_bank_details", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeDocument", b => + { + b.Property("EmployeeDocumentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeDocumentId")); + + b.Property("ContentType") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("ExpiryDate") + .HasColumnType("timestamp with time zone"); + + b.Property("HrDocumentTypeId") + .HasColumnType("integer"); + + b.Property("IssueDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("OriginalFileName") + .IsRequired() + .HasMaxLength(260) + .HasColumnType("character varying(260)"); + + b.Property("RelativePath") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SizeBytes") + .HasColumnType("bigint"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("StoredFileName") + .IsRequired() + .HasMaxLength(260) + .HasColumnType("character varying(260)"); + + b.Property("UploadedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UploadedBy") + .HasColumnType("integer"); + + b.Property("VerifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VerifiedBy") + .HasColumnType("integer"); + + b.HasKey("EmployeeDocumentId"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("ExpiryDate"); + + b.HasIndex("HrDocumentTypeId"); + + b.ToTable("hr_employee_documents", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeLoan", b => + { + b.Property("EmployeeLoanId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeLoanId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("InstallmentAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("InterestRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("LoanKind") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("NumberOfInstallments") + .HasColumnType("integer"); + + b.Property("OutstandingBalance") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("PrincipalAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("StartMonth") + .HasColumnType("integer"); + + b.Property("StartYear") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("EmployeeLoanId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("EmployeeId"); + + b.HasIndex("Status"); + + b.ToTable("hr_employee_loans", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructure", b => + { + b.Property("EmployeeSalaryStructureId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeSalaryStructureId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("BasicSalary") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("Currency") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("character varying(3)"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveTo") + .HasColumnType("timestamp with time zone"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("EmployeeSalaryStructureId"); + + b.HasIndex("EmployeeId", "EffectiveTo"); + + b.ToTable("hr_employee_salary_structures", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructureLine", b => + { + b.Property("EmployeeSalaryStructureLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeSalaryStructureLineId")); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("EmployeeSalaryStructureId") + .HasColumnType("integer"); + + b.Property("SalaryComponentId") + .HasColumnType("integer"); + + b.HasKey("EmployeeSalaryStructureLineId"); + + b.HasIndex("EmployeeSalaryStructureId"); + + b.HasIndex("SalaryComponentId"); + + b.ToTable("hr_employee_salary_structure_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmploymentType", b => + { + b.Property("EmploymentTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmploymentTypeId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("EmploymentTypeId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_employment_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Grn", b => + { + b.Property("GrnId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("GrnId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PoId") + .HasColumnType("integer"); + + b.Property("PostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PurchaseInvoiceId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("GrnId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("PoId"); + + b.HasIndex("PurchaseInvoiceId"); + + b.HasIndex("Status"); + + b.HasIndex("VendorId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("grns", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLine", b => + { + b.Property("GrnLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("GrnLineId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("DiscountPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("GrnId") + .HasColumnType("integer"); + + b.Property("HoldStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("NetUnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("PoLineId") + .HasColumnType("integer"); + + b.Property("PoUnitPrice") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReceivedValue") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("VatAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("VatPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.HasKey("GrnLineId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("GrnId"); + + b.HasIndex("ItemId"); + + b.HasIndex("PoLineId"); + + b.ToTable("grn_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLineWarrantyNumber", b => + { + b.Property("GrnLineWarrantyNumberId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("GrnLineWarrantyNumberId")); + + b.Property("GrnLineId") + .HasColumnType("integer"); + + b.Property("WarrantyNo") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("WarrantyPeriodMonths") + .HasColumnType("integer"); + + b.HasKey("GrnLineWarrantyNumberId"); + + b.HasIndex("GrnLineId", "WarrantyNo") + .IsUnique(); + + b.ToTable("grn_line_warranty_numbers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.HrDocumentType", b => + { + b.Property("HrDocumentTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("HrDocumentTypeId")); + + b.Property("Category") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpiryTracked") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RequiredAtOnboarding") + .HasColumnType("boolean"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("HrDocumentTypeId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_document_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Item", b => + { + b.Property("ItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ItemId")); + + b.Property("BaseUomId") + .HasColumnType("integer"); + + b.Property("BrandId") + .HasColumnType("integer"); + + b.Property("CategoryId") + .HasColumnType("integer"); + + b.Property("ContentBaseQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ContentBaseUnit") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ContentQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ContentUnit") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DefaultVendorId") + .HasColumnType("integer"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SellingFlatPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SellingMaxPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SellingMinPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Sku") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("StockNature") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("SubCategoryId") + .HasColumnType("integer"); + + b.Property("TaxClass") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("TrackingMode") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Warranty") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("NonWarranty"); + + b.Property("WarrantyPeriodMonths") + .HasColumnType("integer"); + + b.HasKey("ItemId"); + + b.HasIndex("BaseUomId"); + + b.HasIndex("BrandId"); + + b.HasIndex("CategoryId"); + + b.HasIndex("DefaultVendorId"); + + b.HasIndex("Sku") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("SubCategoryId"); + + b.ToTable("items", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ItemReorder", b => + { + b.Property("ReorderId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReorderId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("ReorderPoint") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReorderQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("ReorderId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("ItemId", "WarehouseId") + .IsUnique(); + + b.ToTable("item_reorders", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ItemType", b => + { + b.Property("ItemTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ItemTypeId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsMeasurable") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("ItemTypeId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("item_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.JournalEntryStub", b => + { + b.Property("JournalId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("JournalId")); + + b.Property("Amount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CreditAccount") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("DebitAccount") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("SourceDocId") + .HasColumnType("integer"); + + b.Property("SourceDocType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.HasKey("JournalId"); + + b.HasIndex("SourceDocType", "SourceDocId"); + + b.ToTable("journal_entry_stubs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveBalance", b => + { + b.Property("LeaveBalanceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LeaveBalanceId")); + + b.Property("AdjustmentDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("CarriedForwardDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("EntitledDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("LeaveTypeId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("TakenDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Year") + .HasColumnType("integer"); + + b.HasKey("LeaveBalanceId"); + + b.HasIndex("LeaveTypeId"); + + b.HasIndex("EmployeeId", "LeaveTypeId", "Year") + .IsUnique(); + + b.ToTable("hr_leave_balances", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveRequest", b => + { + b.Property("LeaveRequestId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LeaveRequestId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DaysCount") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("EndDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LeaveTypeId") + .HasColumnType("integer"); + + b.Property("Reason") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("RejectionReason") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("StartDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("LeaveRequestId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("EmployeeId"); + + b.HasIndex("LeaveTypeId"); + + b.HasIndex("Status"); + + b.HasIndex("StartDate", "EndDate"); + + b.ToTable("hr_leave_requests", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveType", b => + { + b.Property("LeaveTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LeaveTypeId")); + + b.Property("AccrualPerYear") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("CarryForwardAllowed") + .HasColumnType("boolean"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CountsAsNoPay") + .HasColumnType("boolean"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsPaid") + .HasColumnType("boolean"); + + b.Property("MaxCarryForwardDays") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RequiresApproval") + .HasColumnType("boolean"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("LeaveTypeId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_leave_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoanInstallment", b => + { + b.Property("LoanInstallmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LoanInstallmentId")); + + b.Property("DueMonth") + .HasColumnType("integer"); + + b.Property("DueYear") + .HasColumnType("integer"); + + b.Property("EmployeeLoanId") + .HasColumnType("integer"); + + b.Property("InstallmentNumber") + .HasColumnType("integer"); + + b.Property("PaidAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("PayrollRunId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("ScheduledAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("LoanInstallmentId"); + + b.HasIndex("EmployeeLoanId"); + + b.HasIndex("PayrollRunId"); + + b.HasIndex("DueYear", "DueMonth"); + + b.ToTable("hr_loan_installments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoginActivity", b => + { + b.Property("LoginActivityId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LoginActivityId")); + + b.Property("DeviceLabel") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("IpAddress") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("LoginAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserAgent") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("LoginActivityId"); + + b.HasIndex("UserId", "LoginAt"); + + b.ToTable("login_activities", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NavItem", b => + { + b.Property("NavItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NavItemId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Href") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Icon") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.HasKey("NavItemId"); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("nav_items", (string)null); + + b.HasData( + new + { + NavItemId = 1, + Code = "dashboard", + Href = "/dashboard", + Label = "Dashboard", + SortOrder = 1, + Status = "Active" + }, + new + { + NavItemId = 2, + Code = "products", + Href = "/dashboard/products", + Label = "Products", + SortOrder = 2, + Status = "Active" + }, + new + { + NavItemId = 4, + Code = "procurement", + Href = "/dashboard/procurement", + Label = "Procurement", + SortOrder = 4, + Status = "Active" + }, + new + { + NavItemId = 5, + Code = "receiving", + Href = "/dashboard/receiving/grn", + Label = "Receiving", + SortOrder = 5, + Status = "Active" + }, + new + { + NavItemId = 6, + Code = "stock", + Href = "/dashboard/stock", + Label = "Stock", + SortOrder = 6, + Status = "Active" + }, + new + { + NavItemId = 7, + Code = "warehouses", + Href = "/dashboard/warehouse", + Label = "Warehouses", + SortOrder = 7, + Status = "Active" + }, + new + { + NavItemId = 8, + Code = "orders", + Href = "/dashboard/orders", + Label = "Orders", + SortOrder = 8, + Status = "Active" + }, + new + { + NavItemId = 9, + Code = "settings", + Href = "/dashboard/settings", + Label = "Settings", + SortOrder = 9, + Status = "Active" + }, + new + { + NavItemId = 10, + Code = "help", + Href = "/dashboard/help", + Label = "Help", + SortOrder = 10, + Status = "Active" + }, + new + { + NavItemId = 11, + Code = "ledgers", + Href = "/dashboard/ledgers", + Label = "Ledgers", + SortOrder = 11, + Status = "Active" + }, + new + { + NavItemId = 12, + Code = "accounts", + Href = "/dashboard/accounts", + Label = "Accounts", + SortOrder = 12, + Status = "Active" + }, + new + { + NavItemId = 13, + Code = "sales", + Href = "/dashboard/sales", + Label = "Sales", + SortOrder = 13, + Status = "Active" + }, + new + { + NavItemId = 14, + Code = "production", + Href = "/dashboard/production", + Label = "Production", + SortOrder = 14, + Status = "Active" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Notification", b => + { + b.Property("NotificationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NotificationId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("ModuleKey") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("RelatedEntityId") + .HasColumnType("integer"); + + b.Property("RelatedEntityType") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.HasKey("NotificationId"); + + b.HasIndex("CreatedAt"); + + b.ToTable("notifications", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => + { + b.Property("NotificationConfigId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.HasKey("NotificationConfigId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("notification_config", null, t => + { + t.HasCheckConstraint("ck_notification_config_singleton", "\"NotificationConfigId\" = 1"); + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfigModule", b => + { + b.Property("NotificationConfigModuleId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NotificationConfigModuleId")); + + b.Property("EmailEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("InAppEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("ModuleKey") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("NotificationConfigId") + .HasColumnType("integer"); + + b.Property("SmsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.HasKey("NotificationConfigModuleId"); + + b.HasIndex("ModuleKey") + .IsUnique(); + + b.HasIndex("NotificationConfigId"); + + b.ToTable("notification_config_modules", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationRecipient", b => + { + b.Property("NotificationRecipientId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NotificationRecipientId")); + + b.Property("IsRead") + .HasColumnType("boolean"); + + b.Property("NotificationId") + .HasColumnType("integer"); + + b.Property("ReadAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("NotificationRecipientId"); + + b.HasIndex("NotificationId"); + + b.HasIndex("UserId", "IsRead", "NotificationId"); + + b.ToTable("notification_recipients", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NumberSequence", b => + { + b.Property("SequenceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SequenceId")); + + b.Property("DocType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("doc_type"); + + b.Property("LastNumber") + .HasColumnType("integer") + .HasColumnName("last_number"); + + b.Property("Year") + .HasColumnType("integer") + .HasColumnName("year"); + + b.HasKey("SequenceId"); + + b.HasIndex("DocType", "Year") + .IsUnique(); + + b.ToTable("number_sequences", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => + { + b.Property("PayrollLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollLineId")); + + b.Property("AbsentDays") + .HasColumnType("integer"); + + b.Property("BasicSalary") + .HasColumnType("numeric(18,2)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("EpfEmployeeAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("EpfEmployerAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("EtfEmployerAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("GrossSalary") + .HasColumnType("numeric(18,2)"); + + b.Property("LateDeductionAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("LateMinutesTotal") + .HasColumnType("integer"); + + b.Property("LeaveDays") + .HasColumnType("integer"); + + b.Property("LoanDeductionAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("NetSalary") + .HasColumnType("numeric(18,2)"); + + b.Property("NoPayAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("OtMinutesTotal") + .HasColumnType("integer"); + + b.Property("OtherDeductionsAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("OvertimeAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("PayrollRunId") + .HasColumnType("integer"); + + b.Property("PresentDays") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("TaxAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("TotalAllowances") + .HasColumnType("numeric(18,2)"); + + b.Property("WorkingDays") + .HasColumnType("integer"); + + b.HasKey("PayrollLineId"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("PayrollRunId", "EmployeeId") + .IsUnique(); + + b.ToTable("hr_payroll_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLineComponent", b => + { + b.Property("PayrollLineComponentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollLineComponentId")); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("ComponentCategory") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("PayrollLineId") + .HasColumnType("integer"); + + b.Property("SalaryComponentId") + .HasColumnType("integer"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.HasKey("PayrollLineComponentId"); + + b.HasIndex("PayrollLineId"); + + b.HasIndex("SalaryComponentId"); + + b.ToTable("hr_payroll_line_components", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollRun", b => + { + b.Property("PayrollRunId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollRunId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GeneratedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GeneratedBy") + .HasColumnType("integer"); + + b.Property("LockedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("LockedBy") + .HasColumnType("integer"); + + b.Property("PeriodMonth") + .HasColumnType("integer"); + + b.Property("PeriodYear") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UnlockReason") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("UnlockedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UnlockedBy") + .HasColumnType("integer"); + + b.HasKey("PayrollRunId"); + + b.HasIndex("BranchId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("PeriodYear", "PeriodMonth", "BranchId"); + + b.ToTable("hr_payroll_runs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollStatutorySetting", b => + { + b.Property("PayrollStatutorySettingId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollStatutorySettingId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveTo") + .HasColumnType("timestamp with time zone"); + + b.Property("EpfEmployeeRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("EpfEmployerRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("EtfEmployerRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("OtMultiplierDefault") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.HasKey("PayrollStatutorySettingId"); + + b.HasIndex("EffectiveFrom"); + + b.ToTable("hr_payroll_statutory_settings", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Payslip", b => + { + b.Property("PayslipId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayslipId")); + + b.Property("GeneratedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PayrollLineId") + .HasColumnType("integer"); + + b.Property("ReleasedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReleasedBy") + .HasColumnType("integer"); + + b.HasKey("PayslipId"); + + b.HasIndex("PayrollLineId") + .IsUnique(); + + b.ToTable("hr_payslips", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Permission", b => + { + b.Property("PermissionId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PermissionId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(80) + .HasColumnType("character varying(80)"); + + b.Property("NavItemId") + .HasColumnType("integer"); + + b.Property("SubNavItemId") + .HasColumnType("integer"); + + b.HasKey("PermissionId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("NavItemId"); + + b.HasIndex("SubNavItemId"); + + b.ToTable("permissions", (string)null); + + b.HasData( + new + { + PermissionId = 1, + Code = "NAV:dashboard", + NavItemId = 1 + }, + new + { + PermissionId = 2, + Code = "NAV:products", + NavItemId = 2 + }, + new + { + PermissionId = 3, + Code = "NAV:procurement.vendors", + SubNavItemId = 30 + }, + new + { + PermissionId = 4, + Code = "NAV:procurement", + NavItemId = 4 + }, + new + { + PermissionId = 5, + Code = "NAV:receiving", + NavItemId = 5 + }, + new + { + PermissionId = 6, + Code = "NAV:stock", + NavItemId = 6 + }, + new + { + PermissionId = 7, + Code = "NAV:warehouses", + NavItemId = 7 + }, + new + { + PermissionId = 8, + Code = "NAV:orders", + NavItemId = 8 + }, + new + { + PermissionId = 9, + Code = "NAV:settings", + NavItemId = 9 + }, + new + { + PermissionId = 10, + Code = "NAV:help", + NavItemId = 10 + }, + new + { + PermissionId = 11, + Code = "NAV:products.item", + SubNavItemId = 1 + }, + new + { + PermissionId = 12, + Code = "NAV:products.category", + SubNavItemId = 2 + }, + new + { + PermissionId = 13, + Code = "NAV:products.brand", + SubNavItemId = 3 + }, + new + { + PermissionId = 14, + Code = "NAV:products.item-type", + SubNavItemId = 4 + }, + new + { + PermissionId = 15, + Code = "NAV:products.uom", + SubNavItemId = 5 + }, + new + { + PermissionId = 16, + Code = "NAV:products.configuration", + SubNavItemId = 6 + }, + new + { + PermissionId = 17, + Code = "NAV:settings.roles", + SubNavItemId = 7 + }, + new + { + PermissionId = 18, + Code = "NAV:settings.users", + SubNavItemId = 8 + }, + new + { + PermissionId = 28, + Code = "NAV:procurement.requisitions", + SubNavItemId = 17 + }, + new + { + PermissionId = 29, + Code = "NAV:procurement.rfqs", + SubNavItemId = 18 + }, + new + { + PermissionId = 30, + Code = "NAV:procurement.purchase-orders", + SubNavItemId = 19 + }, + new + { + PermissionId = 31, + Code = "NAV:procurement.purchase-returns", + SubNavItemId = 20 + }, + new + { + PermissionId = 19, + Code = "NAV:ledgers", + NavItemId = 11 + }, + new + { + PermissionId = 20, + Code = "NAV:ledgers.trial-balance", + SubNavItemId = 9 + }, + new + { + PermissionId = 21, + Code = "NAV:ledgers.balance-sheet", + SubNavItemId = 10 + }, + new + { + PermissionId = 22, + Code = "NAV:ledgers.general-ledger", + SubNavItemId = 11 + }, + new + { + PermissionId = 23, + Code = "NAV:ledgers.profit-and-loss", + SubNavItemId = 12 + }, + new + { + PermissionId = 24, + Code = "NAV:ledgers.cash-flow", + SubNavItemId = 13 + }, + new + { + PermissionId = 25, + Code = "NAV:ledgers.budget-vs-actual", + SubNavItemId = 14 + }, + new + { + PermissionId = 27, + Code = "NAV:ledgers.tax-report", + SubNavItemId = 16 + }, + new + { + PermissionId = 26, + Code = "NAV:accounts.bank-accounts", + SubNavItemId = 15 + }, + new + { + PermissionId = 32, + Code = "NAV:accounts", + NavItemId = 12 + }, + new + { + PermissionId = 33, + Code = "NAV:accounts.cheque-books", + SubNavItemId = 21 + }, + new + { + PermissionId = 34, + Code = "NAV:accounts.received-cheques", + SubNavItemId = 22 + }, + new + { + PermissionId = 35, + Code = "NAV:production", + NavItemId = 14 + }, + new + { + PermissionId = 36, + Code = "NAV:production.templates", + SubNavItemId = 27 + }, + new + { + PermissionId = 37, + Code = "NAV:production.runs", + SubNavItemId = 25 + }, + new + { + PermissionId = 38, + Code = "NAV:production.produced", + SubNavItemId = 26 + }, + new + { + PermissionId = 39, + Code = "NAV:procurement.purchase-invoices", + SubNavItemId = 28 + }, + new + { + PermissionId = 40, + Code = "NAV:settings.branches", + SubNavItemId = 29 + }, + new + { + PermissionId = 41, + Code = "NAV:stock.ledger", + SubNavItemId = 31 + }, + new + { + PermissionId = 42, + Code = "NAV:stock.enquiry", + SubNavItemId = 32 + }, + new + { + PermissionId = 43, + Code = "NAV:stock.valuation", + SubNavItemId = 33 + }, + new + { + PermissionId = 44, + Code = "NAV:stock.transfers", + SubNavItemId = 34 + }, + new + { + PermissionId = 45, + Code = "NAV:stock.adjustments", + SubNavItemId = 35 + }, + new + { + PermissionId = 46, + Code = "NAV:stock.counts", + SubNavItemId = 36 + }, + new + { + PermissionId = 47, + Code = "NAV:stock.reorder-alerts", + SubNavItemId = 37 + }, + new + { + PermissionId = 48, + Code = "NAV:stock.wastage", + SubNavItemId = 38 + }, + new + { + PermissionId = 49, + Code = "NAV:sales.bundle-templates", + SubNavItemId = 23 + }, + new + { + PermissionId = 50, + Code = "NAV:sales.invoices", + SubNavItemId = 40 + }, + new + { + PermissionId = 51, + Code = "NAV:sales.free-issues", + SubNavItemId = 41 + }, + new + { + PermissionId = 52, + Code = "NAV:sales.day-end", + SubNavItemId = 42 + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PoLine", b => + { + b.Property("PoLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PoLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("PoId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyReceived") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Tax") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("PoLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("PoId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("po_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductConfig", b => + { + b.Property("ConfigId") + .HasColumnType("integer"); + + b.Property("BatchListsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("BrandsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("ItemTypesEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SellingPricesEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("SerialNumbersEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("SubcategoriesEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.Property("WarrantyPeriodsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.HasKey("ConfigId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("product_config", null, t => + { + t.HasCheckConstraint("ck_product_config_singleton", "\"ConfigId\" = 1"); + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b => + { + b.Property("RunId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunId")); + + b.Property("CancelReasonCodeId") + .HasColumnType("integer"); + + b.Property("CompletedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("OutputBinId") + .HasColumnType("integer"); + + b.Property("ReworkCount") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("ScaleFactor") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("TargetQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TemplateId") + .HasColumnType("integer"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("RunId"); + + b.HasIndex("CancelReasonCodeId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("OutputBinId"); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("TemplateId", "Status"); + + b.ToTable("production_runs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionTemplate", b => + { + b.Property("TemplateId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TemplateId")); + + b.Property("Annotations") + .HasColumnType("jsonb"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("TemplateId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("CreatedBy"); + + b.HasIndex("Status"); + + b.ToTable("production_templates", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", b => + { + b.Property("PurchaseInvoiceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PurchaseInvoiceId")); + + b.Property("BalanceAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VatTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.Property("VendorInvoiceDate") + .HasColumnType("timestamp with time zone"); + + b.Property("VendorInvoiceNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("VendorSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("VendorSnapshotTaxNo") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("PurchaseInvoiceId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("VendorId"); + + b.HasIndex("VendorId", "VendorInvoiceNo"); + + b.ToTable("purchase_invoices", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoiceLine", b => + { + b.Property("PurchaseInvoiceLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PurchaseInvoiceLineId")); + + b.Property("GrnId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PurchaseInvoiceId") + .HasColumnType("integer"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("VatTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("PurchaseInvoiceLineId"); + + b.HasIndex("GrnId") + .IsUnique(); + + b.HasIndex("PurchaseInvoiceId"); + + b.ToTable("purchase_invoice_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoicePayment", b => + { + b.Property("PurchaseInvoicePaymentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PurchaseInvoicePaymentId")); + + b.Property("Amount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BankAccountName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("GlBankAccountId") + .HasColumnType("bigint"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PaymentDate") + .HasColumnType("timestamp with time zone"); + + b.Property("PurchaseInvoiceId") + .HasColumnType("integer"); + + b.Property("Reference") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("PurchaseInvoicePaymentId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("PurchaseInvoiceId"); + + b.ToTable("purchase_invoice_payments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => + { + b.Property("PoId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PoId")); + + b.Property("ApprovalRequired") + .HasColumnType("boolean"); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("ApproverUserId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RequisitionId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.HasKey("PoId"); + + b.HasIndex("ApproverUserId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("RequisitionId"); + + b.HasIndex("Status"); + + b.HasIndex("VendorId"); + + b.ToTable("purchase_orders", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturn", b => + { + b.Property("ReturnId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReasonCodeId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("ReturnId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("ReasonCodeId"); + + b.HasIndex("VendorId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("purchase_returns", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturnLine", b => + { + b.Property("ReturnLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnLineId")); + + b.Property("GrnLineId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReturnId") + .HasColumnType("integer"); + + b.HasKey("ReturnLineId"); + + b.HasIndex("GrnLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("ReturnId"); + + b.ToTable("purchase_return_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ReasonCode", b => + { + b.Property("ReasonCodeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReasonCodeId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Context") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.HasKey("ReasonCodeId"); + + b.HasIndex("Context", "Code") + .IsUnique(); + + b.ToTable("reason_codes", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => + { + b.Property("RequisitionId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RequisitionId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RequestedBy") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("RequisitionId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("RequestedBy"); + + b.HasIndex("Status"); + + b.ToTable("requisitions", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RequisitionLine", b => + { + b.Property("ReqLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReqLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RequiredBy") + .HasColumnType("date"); + + b.Property("RequisitionId") + .HasColumnType("integer"); + + b.HasKey("ReqLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RequisitionId"); + + b.ToTable("requisition_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => + { + b.Property("RfqId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RfqId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RequisitionId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("RfqId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("RequisitionId"); + + b.ToTable("rfqs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RfqLine", b => + { + b.Property("RfqLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RfqLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RfqId") + .HasColumnType("integer"); + + b.HasKey("RfqLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RfqId"); + + b.ToTable("rfq_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Role", b => + { + b.Property("RoleId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RoleId")); + + b.Property("AuthRoleId") + .HasColumnType("uuid") + .HasColumnName("auth_role_id"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsSystemRole") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("RoleId"); + + b.HasIndex("AuthRoleId") + .IsUnique(); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("roles", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RolePermission", b => + { + b.Property("RoleId") + .HasColumnType("integer"); + + b.Property("PermissionId") + .HasColumnType("integer"); + + b.HasKey("RoleId", "PermissionId"); + + b.HasIndex("PermissionId"); + + b.ToTable("role_permissions", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunEdge", b => + { + b.Property("RunEdgeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunEdgeId")); + + b.Property("ChildRunStageId") + .HasColumnType("integer"); + + b.Property("ParentRunStageId") + .HasColumnType("integer"); + + b.Property("RunId") + .HasColumnType("integer"); + + b.HasKey("RunEdgeId"); + + b.HasIndex("ChildRunStageId"); + + b.HasIndex("RunId"); + + b.HasIndex("ParentRunStageId", "ChildRunStageId") + .IsUnique(); + + b.ToTable("run_edges", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStage", b => + { + b.Property("RunStageId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunStageId")); + + b.Property("ActualEndAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ActualStartAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EstimatedMinutes") + .HasColumnType("integer"); + + b.Property("FieldDefs") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("FieldValues") + .HasColumnType("jsonb"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("PosX") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PosY") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RoleLabel") + .HasMaxLength(60) + .HasColumnType("character varying(60)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("RunId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("TemplateStageId") + .HasColumnType("integer"); + + b.HasKey("RunStageId"); + + b.HasIndex("TemplateStageId"); + + b.HasIndex("RunId", "Status"); + + b.ToTable("run_stages", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageEvent", b => + { + b.Property("EventId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EventId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Note") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Payload") + .HasColumnType("jsonb"); + + b.Property("RunId") + .HasColumnType("integer"); + + b.Property("RunStageId") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("EventId"); + + b.HasIndex("RunStageId"); + + b.HasIndex("UserId"); + + b.HasIndex("RunId", "EventId"); + + b.ToTable("run_stage_events", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageInput", b => + { + b.Property("RunInputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunInputId")); + + b.Property("ConsumedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ConsumedValue") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DeliveredQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("FromRunOutputId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("PlannedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyUnit") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ReturnedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReturnedValue") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RunStageId") + .HasColumnType("integer"); + + b.Property("Source") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("RunInputId"); + + b.HasIndex("FromRunOutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RunStageId"); + + b.ToTable("run_stage_inputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageOutput", b => + { + b.Property("RunOutputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunOutputId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("PlannedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ProducedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RunStageId") + .HasColumnType("integer"); + + b.Property("ScrapReasonCodeId") + .HasColumnType("integer"); + + b.Property("ScrappedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TransferredQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UomId") + .HasColumnType("integer"); + + b.HasKey("RunOutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RunStageId"); + + b.HasIndex("ScrapReasonCodeId"); + + b.HasIndex("UomId"); + + b.ToTable("run_stage_outputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalaryComponent", b => + { + b.Property("SalaryComponentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalaryComponentId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ComponentType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsEpfEtfApplicable") + .HasColumnType("boolean"); + + b.Property("IsTaxable") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("SalaryComponentId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_salary_components", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesDayEnd", b => + { + b.Property("SalesDayEndId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesDayEndId")); + + b.Property("BundleCount") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("BusinessDate") + .HasColumnType("date"); + + b.Property("CashierUserId") + .HasColumnType("integer"); + + b.Property("ClosedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ClosedBy") + .HasColumnType("integer"); + + b.Property("CostOfGoodsSold") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SlipCount") + .HasColumnType("integer"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("SalesDayEndId"); + + b.HasIndex("ClosedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("CashierUserId", "BusinessDate") + .IsUnique(); + + b.ToTable("sales_day_ends", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoice", b => + { + b.Property("SalesInvoiceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesInvoiceId")); + + b.Property("BalanceAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("CreatorUserId") + .HasColumnType("integer"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("CustomerSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CustomerSnapshotTaxNo") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("InvoiceDate") + .HasColumnType("timestamp with time zone"); + + b.Property("InvoiceNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("InvoiceType") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("B2C"); + + b.Property("NetPayable") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RoundOff") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesInvoiceId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatorUserId"); + + b.HasIndex("CustomerId"); + + b.HasIndex("InvoiceDate"); + + b.HasIndex("InvoiceNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_invoices", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoiceLine", b => + { + b.Property("SalesInvoiceLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesInvoiceLineId")); + + b.Property("BaseCost") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DiscountAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DiscountMode") + .HasColumnType("integer"); + + b.Property("DiscountPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("FreeQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("IsFreeIssue") + .HasColumnType("boolean"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("NetUnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ParentLineId") + .HasColumnType("integer"); + + b.Property("PriceSource") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SalesInvoiceId") + .HasColumnType("integer"); + + b.Property("TaxAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesInvoiceLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SalesInvoiceId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_invoice_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoicePayment", b => + { + b.Property("SalesInvoicePaymentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesInvoicePaymentId")); + + b.Property("Amount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BankAccountName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("GlBankAccountId") + .HasColumnType("bigint"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PaymentDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Reference") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("SalesInvoiceId") + .HasColumnType("integer"); + + b.HasKey("SalesInvoicePaymentId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("SalesInvoiceId"); + + b.ToTable("sales_invoice_payments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturn", b => + { + b.Property("ReturnId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReasonCodeId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("ReturnId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("CustomerId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("ReasonCodeId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_returns", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturnLine", b => + { + b.Property("ReturnLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReturnId") + .HasColumnType("integer"); + + b.Property("SalesInvoiceLineId") + .HasColumnType("integer"); + + b.HasKey("ReturnLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("ReturnId"); + + b.HasIndex("SalesInvoiceLineId"); + + b.ToTable("sales_return_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlip", b => + { + b.Property("SalesSlipId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesSlipId")); + + b.Property("BalanceAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CashierUserId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("CustomerSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DayEndId") + .HasColumnType("integer"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SlipDate") + .HasColumnType("timestamp with time zone"); + + b.Property("SlipNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesSlipId"); + + b.HasIndex("CashierUserId"); + + b.HasIndex("CustomerId"); + + b.HasIndex("DayEndId"); + + b.HasIndex("SlipDate"); + + b.HasIndex("SlipNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_slips", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlipLine", b => + { + b.Property("SalesSlipLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesSlipLineId")); + + b.Property("BaseCost") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DiscountAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DiscountMode") + .HasColumnType("integer"); + + b.Property("DiscountPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("FreeQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("IsFreeIssue") + .HasColumnType("boolean"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("NetUnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ParentLineId") + .HasColumnType("integer"); + + b.Property("PriceSource") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SalesSlipId") + .HasColumnType("integer"); + + b.Property("TaxAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesSlipLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SalesSlipId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_slip_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Serial", b => + { + b.Property("SerialId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SerialId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("SerialNo") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("SerialId"); + + b.HasIndex("ItemId", "SerialNo") + .IsUnique(); + + b.ToTable("serials", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageEdge", b => + { + b.Property("EdgeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EdgeId")); + + b.Property("ChildStageId") + .HasColumnType("integer"); + + b.Property("ParentStageId") + .HasColumnType("integer"); + + b.Property("TemplateId") + .HasColumnType("integer"); + + b.HasKey("EdgeId"); + + b.HasIndex("ChildStageId"); + + b.HasIndex("TemplateId"); + + b.HasIndex("ParentStageId", "ChildStageId") + .IsUnique(); + + b.ToTable("stage_edges", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageInput", b => + { + b.Property("InputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("InputId")); + + b.Property("FromOutputId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyPerBatch") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyUnit") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Source") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("StageId") + .HasColumnType("integer"); + + b.HasKey("InputId"); + + b.HasIndex("FromOutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("StageId"); + + b.ToTable("stage_inputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageOutput", b => + { + b.Property("OutputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("OutputId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("QtyPerBatch") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("StageId") + .HasColumnType("integer"); + + b.Property("UomId") + .HasColumnType("integer"); + + b.HasKey("OutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("StageId"); + + b.HasIndex("UomId"); + + b.ToTable("stage_outputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustment", b => + { + b.Property("AdjustmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AdjustmentId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReasonCodeId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("AdjustmentId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("ReasonCodeId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("stock_adjustments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustmentLine", b => + { + b.Property("AdjLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AdjLineId")); + + b.Property("AdjustmentId") + .HasColumnType("integer"); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyDelta") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.HasKey("AdjLineId"); + + b.HasIndex("AdjustmentId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SerialId"); + + b.ToTable("stock_adjustment_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCount", b => + { + b.Property("CountId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CountId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CountType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("CountId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("stock_counts", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCountLine", b => + { + b.Property("CountLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CountLineId")); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("CountId") + .HasColumnType("integer"); + + b.Property("CountedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("SystemQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Variance") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("CountLineId"); + + b.HasIndex("BinId"); + + b.HasIndex("CountId"); + + b.HasIndex("ItemId"); + + b.ToTable("stock_count_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLayer", b => + { + b.Property("LayerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LayerId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("GrnLineId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyReceived") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyRemaining") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReceiptDate") + .HasColumnType("timestamp with time zone"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("LayerId"); + + b.HasIndex("BatchId"); + + b.HasIndex("GrnLineId"); + + b.HasIndex("SerialId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("ItemId", "WarehouseId", "ReceiptDate", "LayerId"); + + b.ToTable("stock_layers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLedger", b => + { + b.Property("LedgerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LedgerId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Direction") + .IsRequired() + .HasMaxLength(5) + .HasColumnType("character varying(5)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyBase") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RunningBalance") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("SourceDocId") + .HasColumnType("integer"); + + b.Property("SourceDocType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.Property("Value") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("LedgerId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("SerialId"); + + b.HasIndex("UserId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("SourceDocType", "SourceDocId"); + + b.HasIndex("ItemId", "WarehouseId", "CreatedAt"); + + b.HasIndex("ItemId", "WarehouseId", "LedgerId"); + + b.ToTable("stock_ledger", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransfer", b => + { + b.Property("TransferId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TransferId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DestWarehouseId") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SrcWarehouseId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("TransferId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DestWarehouseId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("SrcWarehouseId"); + + b.HasIndex("Status"); + + b.ToTable("stock_transfers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransferLine", b => + { + b.Property("TransferLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TransferLineId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("DestBinId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyReceived") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("SrcBinId") + .HasColumnType("integer"); + + b.Property("TransferId") + .HasColumnType("integer"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.HasKey("TransferLineId"); + + b.HasIndex("BatchId"); + + b.HasIndex("DestBinId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SerialId"); + + b.HasIndex("SrcBinId"); + + b.HasIndex("TransferId"); + + b.ToTable("stock_transfer_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubCategory", b => + { + b.Property("SubCategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SubCategoryId")); + + b.Property("CategoryId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("SubCategoryId"); + + b.HasIndex("Status"); + + b.HasIndex("CategoryId", "Name") + .IsUnique(); + + b.ToTable("subcategories", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubNavItem", b => + { + b.Property("SubNavItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SubNavItemId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Href") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Icon") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("NavItemId") + .HasColumnType("integer"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.HasKey("SubNavItemId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("NavItemId"); + + b.ToTable("sub_nav_items", (string)null); + + b.HasData( + new + { + SubNavItemId = 1, + Code = "products.item", + Href = "/dashboard/products", + Label = "Item", + NavItemId = 2, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 2, + Code = "products.category", + Href = "/dashboard/products/categories", + Label = "Category", + NavItemId = 2, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 3, + Code = "products.brand", + Href = "/dashboard/products/brands", + Label = "Brand", + NavItemId = 2, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 4, + Code = "products.item-type", + Href = "/dashboard/products/item-types", + Label = "Item Type", + NavItemId = 2, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 5, + Code = "products.uom", + Href = "/dashboard/products/uoms", + Label = "UOM", + NavItemId = 2, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 6, + Code = "products.configuration", + Href = "/dashboard/products/settings", + Label = "Configuration", + NavItemId = 2, + SortOrder = 6, + Status = "Active" + }, + new + { + SubNavItemId = 29, + Code = "settings.branches", + Href = "/dashboard/settings/branches", + Label = "Branches", + NavItemId = 9, + SortOrder = 0, + Status = "Active" + }, + new + { + SubNavItemId = 7, + Code = "settings.roles", + Href = "/dashboard/settings/roles", + Label = "Roles", + NavItemId = 9, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 8, + Code = "settings.users", + Href = "/dashboard/settings/users", + Label = "Users", + NavItemId = 9, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 24, + Code = "settings.notification-config", + Href = "/dashboard/settings/notification-config", + Label = "Notification Config", + NavItemId = 9, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 40, + Code = "sales.invoices", + Href = "/dashboard/sales/invoices", + Label = "Sales", + NavItemId = 13, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 23, + Code = "sales.bundle-templates", + Href = "/dashboard/sales/bundles/templates", + Label = "Bundle Templates", + NavItemId = 13, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 41, + Code = "sales.free-issues", + Href = "/dashboard/sales/free-issues", + Label = "Free Issues", + NavItemId = 13, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 42, + Code = "sales.day-end", + Href = "/dashboard/sales/day-end", + Label = "Day End", + NavItemId = 13, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 30, + Code = "procurement.vendors", + Href = "/dashboard/vendors", + Label = "Vendors", + NavItemId = 4, + SortOrder = 0, + Status = "Active" + }, + new + { + SubNavItemId = 17, + Code = "procurement.requisitions", + Href = "/dashboard/procurement/requisitions", + Label = "Requisitions", + NavItemId = 4, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 18, + Code = "procurement.rfqs", + Href = "/dashboard/procurement/rfqs", + Label = "RFQs", + NavItemId = 4, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 19, + Code = "procurement.purchase-orders", + Href = "/dashboard/procurement/purchase-orders", + Label = "Purchase Orders", + NavItemId = 4, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 20, + Code = "procurement.purchase-returns", + Href = "/dashboard/procurement/purchase-returns", + Label = "Purchase Returns", + NavItemId = 4, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 28, + Code = "procurement.purchase-invoices", + Href = "/dashboard/procurement/purchase-invoices", + Label = "Purchase Invoices", + NavItemId = 4, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 9, + Code = "ledgers.trial-balance", + Href = "/dashboard/ledgers/trial-balance", + Label = "Trial Balance", + NavItemId = 11, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 10, + Code = "ledgers.balance-sheet", + Href = "/dashboard/ledgers/balance-sheet", + Label = "Balance Sheet", + NavItemId = 11, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 11, + Code = "ledgers.general-ledger", + Href = "/dashboard/ledgers/general-ledger", + Label = "General Ledger", + NavItemId = 11, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 12, + Code = "ledgers.profit-and-loss", + Href = "/dashboard/ledgers/profit-and-loss", + Label = "Profit & Loss", + NavItemId = 11, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 13, + Code = "ledgers.cash-flow", + Href = "/dashboard/ledgers/cash-flow", + Label = "Cash Flow", + NavItemId = 11, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 14, + Code = "ledgers.budget-vs-actual", + Href = "/dashboard/ledgers/budget-vs-actual", + Label = "Budget vs Actual", + NavItemId = 11, + SortOrder = 6, + Status = "Active" + }, + new + { + SubNavItemId = 16, + Code = "ledgers.tax-report", + Href = "/dashboard/ledgers/tax-report", + Label = "Tax Report", + NavItemId = 11, + SortOrder = 7, + Status = "Active" + }, + new + { + SubNavItemId = 15, + Code = "accounts.bank-accounts", + Href = "/dashboard/accounts/bank-accounts", + Label = "Cash / Bank Accounts", + NavItemId = 12, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 21, + Code = "accounts.cheque-books", + Href = "/dashboard/accounts/cheque-books", + Label = "Cheque Books", + NavItemId = 12, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 22, + Code = "accounts.received-cheques", + Href = "/dashboard/accounts/received-cheques", + Label = "Received Cheques", + NavItemId = 12, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 27, + Code = "production.templates", + Href = "/dashboard/production/templates", + Label = "Templates", + NavItemId = 14, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 25, + Code = "production.runs", + Href = "/dashboard/production/runs", + Label = "Runs", + NavItemId = 14, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 26, + Code = "production.produced", + Href = "/dashboard/production/produced", + Label = "Produced", + NavItemId = 14, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 31, + Code = "stock.ledger", + Href = "/dashboard/stock/ledger", + Label = "Stock Ledger", + NavItemId = 6, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 32, + Code = "stock.enquiry", + Href = "/dashboard/stock/enquiry", + Label = "Stock Enquiry", + NavItemId = 6, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 33, + Code = "stock.valuation", + Href = "/dashboard/stock/valuation", + Label = "Valuation", + NavItemId = 6, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 34, + Code = "stock.transfers", + Href = "/dashboard/stock/transfers", + Label = "Transfers", + NavItemId = 6, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 35, + Code = "stock.adjustments", + Href = "/dashboard/stock/adjustments", + Label = "Adjustments", + NavItemId = 6, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 36, + Code = "stock.counts", + Href = "/dashboard/stock/counts", + Label = "Counts", + NavItemId = 6, + SortOrder = 6, + Status = "Active" + }, + new + { + SubNavItemId = 37, + Code = "stock.reorder-alerts", + Href = "/dashboard/stock/reorder-alerts", + Label = "Reorder Alerts", + NavItemId = 6, + SortOrder = 7, + Status = "Active" + }, + new + { + SubNavItemId = 38, + Code = "stock.wastage", + Href = "/dashboard/stock/wastage", + Label = "Wastage", + NavItemId = 6, + SortOrder = 8, + Status = "Active" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicket", b => + { + b.Property("TicketId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TicketId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Subject") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.HasKey("TicketId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("Status"); + + b.ToTable("support_tickets", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicketMessage", b => + { + b.Property("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("MessageId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsFromAdmin") + .HasColumnType("boolean"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("SenderUserId") + .HasColumnType("integer"); + + b.Property("TicketId") + .HasColumnType("integer"); + + b.HasKey("MessageId"); + + b.HasIndex("TicketId", "CreatedAt"); + + b.ToTable("support_ticket_messages", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TaxSlab", b => + { + b.Property("TaxSlabId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TaxSlabId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveTo") + .HasColumnType("timestamp with time zone"); + + b.Property("LowerBound") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("Rate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("UpperBound") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.HasKey("TaxSlabId"); + + b.HasIndex("EffectiveFrom"); + + b.ToTable("hr_tax_slabs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => + { + b.Property("StageId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("StageId")); + + b.Property("EstimatedMinutes") + .HasColumnType("integer"); + + b.Property("FieldDefs") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("PosX") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PosY") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RoleLabel") + .HasMaxLength(60) + .HasColumnType("character varying(60)"); + + b.Property("TemplateId") + .HasColumnType("integer"); + + b.HasKey("StageId"); + + b.HasIndex("TemplateId"); + + b.ToTable("template_stages", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Uom", b => + { + b.Property("UomId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("UomId")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("UomId"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("uoms", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.User", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("UserId")); + + b.Property("AuthUserId") + .HasColumnType("uuid") + .HasColumnName("auth_user_id"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Email") + .HasMaxLength(320) + .HasColumnType("character varying(320)"); + + b.Property("RoleId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("UserId"); + + b.HasIndex("AuthUserId") + .IsUnique(); + + b.HasIndex("Email") + .IsUnique(); + + b.HasIndex("RoleId"); + + b.HasIndex("Username") + .IsUnique(); + + b.ToTable("users", (string)null); + + b.HasData( + new + { + UserId = 1, + DisplayName = "System", + Status = "Active", + Username = "system" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Vendor", b => + { + b.Property("VendorId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("VendorId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Currency") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(3) + .HasColumnType("character varying(3)") + .HasDefaultValue("LKR"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TaxReg") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Terms") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("VendorId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("vendors", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => + { + b.Property("QuotationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("QuotationId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("RfqId") + .HasColumnType("integer"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.HasKey("QuotationId"); + + b.HasIndex("VendorId"); + + b.HasIndex("RfqId", "VendorId") + .IsUnique(); + + b.ToTable("vendor_quotations", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotationLine", b => + { + b.Property("QuotationLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("QuotationLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LeadDays") + .HasColumnType("integer"); + + b.Property("QuotationId") + .HasColumnType("integer"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("QuotationLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("QuotationId"); + + b.ToTable("vendor_quotation_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Warehouse", b => + { + b.Property("WarehouseId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("WarehouseId")); + + b.Property("Address") + .HasColumnType("text"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Phone") + .HasColumnType("text"); + + b.HasKey("WarehouseId"); + + b.HasIndex("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("warehouses", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.WorkShift", b => + { + b.Property("WorkShiftId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("WorkShiftId")); + + b.Property("BreakMinutes") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EndTime") + .HasColumnType("interval"); + + b.Property("GraceMinutes") + .HasColumnType("integer"); + + b.Property("IsOvernight") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("OtMultiplier") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("StandardWorkingMinutes") + .HasColumnType("integer"); + + b.Property("StartTime") + .HasColumnType("interval"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WorkingDaysMask") + .HasColumnType("integer"); + + b.HasKey("WorkShiftId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_work_shifts", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceRecord", b => + { + b.HasOne("ERPCore.Domain.Entities.AttendanceUploadBatch", "AttendanceUploadBatch") + .WithMany() + .HasForeignKey("AttendanceUploadBatchId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.WorkShift", "WorkShift") + .WithMany() + .HasForeignKey("WorkShiftId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("AttendanceUploadBatch"); + + b.Navigation("Employee"); + + b.Navigation("WorkShift"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AuditLog", b => + { + b.HasOne("ERPCore.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Batch", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Bin", b => + { + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany("Bins") + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BranchConfig", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSale", b => + { + b.HasOne("ERPCore.Domain.Entities.BundleSaleTemplate", "BundleSaleTemplate") + .WithMany() + .HasForeignKey("BundleSaleTemplateId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "CashierUser") + .WithMany() + .HasForeignKey("CashierUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesDayEnd", "DayEnd") + .WithMany("BundleSales") + .HasForeignKey("DayEndId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BundleSaleTemplate"); + + b.Navigation("CashierUser"); + + b.Navigation("Customer"); + + b.Navigation("DayEnd"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleLine", b => + { + b.HasOne("ERPCore.Domain.Entities.BundleSale", "BundleSale") + .WithMany("Lines") + .HasForeignKey("BundleSaleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BundleSale"); + + b.Navigation("Item"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplateLine", b => + { + b.HasOne("ERPCore.Domain.Entities.BundleSaleTemplate", "BundleSaleTemplate") + .WithMany("Lines") + .HasForeignKey("BundleSaleTemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BundleSaleTemplate"); + + b.Navigation("Item"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Customer", b => + { + b.HasOne("ERPCore.Domain.Entities.Warehouse", "DefaultWarehouse") + .WithMany() + .HasForeignKey("DefaultWarehouseId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("DefaultWarehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Department", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Employee", "HeadEmployee") + .WithMany() + .HasForeignKey("HeadEmployeeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Department", "ParentDepartment") + .WithMany() + .HasForeignKey("ParentDepartmentId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Branch"); + + b.Navigation("HeadEmployee"); + + b.Navigation("ParentDepartment"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Employee", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Department", "Department") + .WithMany() + .HasForeignKey("DepartmentId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Designation", "Designation") + .WithMany() + .HasForeignKey("DesignationId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.EmploymentType", "EmploymentType") + .WithMany() + .HasForeignKey("EmploymentTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Employee", "ReportingManager") + .WithMany() + .HasForeignKey("ReportingManagerId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithOne() + .HasForeignKey("ERPCore.Domain.Entities.Employee", "UserId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.WorkShift", "WorkShift") + .WithMany() + .HasForeignKey("WorkShiftId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Department"); + + b.Navigation("Designation"); + + b.Navigation("EmploymentType"); + + b.Navigation("ReportingManager"); + + b.Navigation("User"); + + b.Navigation("WorkShift"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeBankDetail", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeDocument", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.HrDocumentType", "HrDocumentType") + .WithMany() + .HasForeignKey("HrDocumentTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("HrDocumentType"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeLoan", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructure", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructureLine", b => + { + b.HasOne("ERPCore.Domain.Entities.EmployeeSalaryStructure", "EmployeeSalaryStructure") + .WithMany("Lines") + .HasForeignKey("EmployeeSalaryStructureId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalaryComponent", "SalaryComponent") + .WithMany() + .HasForeignKey("SalaryComponentId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("EmployeeSalaryStructure"); + + b.Navigation("SalaryComponent"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Grn", 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.HasOne("ERPCore.Domain.Entities.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("PoId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.PurchaseInvoice", "PurchaseInvoice") + .WithMany() + .HasForeignKey("PurchaseInvoiceId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("PurchaseInvoice"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Vendor"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", "Batch") + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", "Bin") + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Grn", "Grn") + .WithMany("Lines") + .HasForeignKey("GrnId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PoLine", "PoLine") + .WithMany() + .HasForeignKey("PoLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Batch"); + + b.Navigation("Bin"); + + b.Navigation("Grn"); + + b.Navigation("Item"); + + b.Navigation("PoLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLineWarrantyNumber", b => + { + b.HasOne("ERPCore.Domain.Entities.GrnLine", "GrnLine") + .WithMany("WarrantyNumbers") + .HasForeignKey("GrnLineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GrnLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Item", b => + { + b.HasOne("ERPCore.Domain.Entities.Uom", "BaseUom") + .WithMany() + .HasForeignKey("BaseUomId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Brand", "Brand") + .WithMany() + .HasForeignKey("BrandId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Category", "Category") + .WithMany() + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "DefaultVendor") + .WithMany() + .HasForeignKey("DefaultVendorId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.SubCategory", "SubCategory") + .WithMany() + .HasForeignKey("SubCategoryId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("BaseUom"); + + b.Navigation("Brand"); + + b.Navigation("Category"); + + b.Navigation("DefaultVendor"); + + b.Navigation("SubCategory"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ItemReorder", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany("ReorderSettings") + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveBalance", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.LeaveType", "LeaveType") + .WithMany() + .HasForeignKey("LeaveTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("LeaveType"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveRequest", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.LeaveType", "LeaveType") + .WithMany() + .HasForeignKey("LeaveTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("LeaveType"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoanInstallment", b => + { + b.HasOne("ERPCore.Domain.Entities.EmployeeLoan", "EmployeeLoan") + .WithMany("Installments") + .HasForeignKey("EmployeeLoanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PayrollRun", "PayrollRun") + .WithMany() + .HasForeignKey("PayrollRunId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("EmployeeLoan"); + + b.Navigation("PayrollRun"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoginActivity", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfigModule", b => + { + b.HasOne("ERPCore.Domain.Entities.NotificationConfig", "NotificationConfig") + .WithMany("Modules") + .HasForeignKey("NotificationConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("NotificationConfig"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationRecipient", b => + { + b.HasOne("ERPCore.Domain.Entities.Notification", "Notification") + .WithMany("Recipients") + .HasForeignKey("NotificationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Notification"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PayrollRun", "PayrollRun") + .WithMany("Lines") + .HasForeignKey("PayrollRunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("PayrollRun"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLineComponent", b => + { + b.HasOne("ERPCore.Domain.Entities.PayrollLine", "PayrollLine") + .WithMany("Components") + .HasForeignKey("PayrollLineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalaryComponent", "SalaryComponent") + .WithMany() + .HasForeignKey("SalaryComponentId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("PayrollLine"); + + b.Navigation("SalaryComponent"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollRun", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Branch"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Payslip", b => + { + b.HasOne("ERPCore.Domain.Entities.PayrollLine", "PayrollLine") + .WithOne() + .HasForeignKey("ERPCore.Domain.Entities.Payslip", "PayrollLineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PayrollLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Permission", b => + { + b.HasOne("ERPCore.Domain.Entities.NavItem", "NavItem") + .WithMany() + .HasForeignKey("NavItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ERPCore.Domain.Entities.SubNavItem", "SubNavItem") + .WithMany() + .HasForeignKey("SubNavItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("NavItem"); + + b.Navigation("SubNavItem"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PoLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseOrder", "PurchaseOrder") + .WithMany("Lines") + .HasForeignKey("PoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductConfig", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b => + { + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "CancelReason") + .WithMany() + .HasForeignKey("CancelReasonCodeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Bin", "OutputBin") + .WithMany() + .HasForeignKey("OutputBinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") + .WithMany("Runs") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CancelReason"); + + b.Navigation("Creator"); + + b.Navigation("OutputBin"); + + b.Navigation("Template"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionTemplate", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoiceLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Grn", "Grn") + .WithMany() + .HasForeignKey("GrnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseInvoice", "PurchaseInvoice") + .WithMany("Lines") + .HasForeignKey("PurchaseInvoiceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Grn"); + + b.Navigation("PurchaseInvoice"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoicePayment", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseInvoice", "PurchaseInvoice") + .WithMany("Payments") + .HasForeignKey("PurchaseInvoiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("PurchaseInvoice"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Approver") + .WithMany() + .HasForeignKey("ApproverUserId"); + + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") + .WithMany() + .HasForeignKey("RequisitionId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Approver"); + + b.Navigation("Creator"); + + b.Navigation("Requisition"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturn", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ReasonCode") + .WithMany() + .HasForeignKey("ReasonCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("ReasonCode"); + + b.Navigation("Vendor"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturnLine", b => + { + b.HasOne("ERPCore.Domain.Entities.GrnLine", "GrnLine") + .WithMany() + .HasForeignKey("GrnLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseReturn", "Return") + .WithMany("Lines") + .HasForeignKey("ReturnId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GrnLine"); + + b.Navigation("Item"); + + b.Navigation("Return"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Requester") + .WithMany() + .HasForeignKey("RequestedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Requester"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RequisitionLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") + .WithMany("Lines") + .HasForeignKey("RequisitionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Requisition"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => + { + b.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") + .WithMany() + .HasForeignKey("RequisitionId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Requisition"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RfqLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Rfq", "Rfq") + .WithMany("Lines") + .HasForeignKey("RfqId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Rfq"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RolePermission", b => + { + b.HasOne("ERPCore.Domain.Entities.Permission", "Permission") + .WithMany() + .HasForeignKey("PermissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Role", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Permission"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunEdge", b => + { + b.HasOne("ERPCore.Domain.Entities.RunStage", "ChildRunStage") + .WithMany() + .HasForeignKey("ChildRunStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "ParentRunStage") + .WithMany() + .HasForeignKey("ParentRunStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ProductionRun", "Run") + .WithMany("Edges") + .HasForeignKey("RunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildRunStage"); + + b.Navigation("ParentRunStage"); + + b.Navigation("Run"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStage", b => + { + b.HasOne("ERPCore.Domain.Entities.ProductionRun", "Run") + .WithMany("Stages") + .HasForeignKey("RunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "TemplateStage") + .WithMany() + .HasForeignKey("TemplateStageId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Run"); + + b.Navigation("TemplateStage"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageEvent", b => + { + b.HasOne("ERPCore.Domain.Entities.ProductionRun", "Run") + .WithMany("Events") + .HasForeignKey("RunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "RunStage") + .WithMany("Events") + .HasForeignKey("RunStageId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Run"); + + b.Navigation("RunStage"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageInput", b => + { + b.HasOne("ERPCore.Domain.Entities.RunStageOutput", "FromRunOutput") + .WithMany() + .HasForeignKey("FromRunOutputId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "RunStage") + .WithMany("Inputs") + .HasForeignKey("RunStageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromRunOutput"); + + b.Navigation("Item"); + + b.Navigation("RunStage"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageOutput", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "RunStage") + .WithMany("Outputs") + .HasForeignKey("RunStageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ScrapReason") + .WithMany() + .HasForeignKey("ScrapReasonCodeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Uom", "Uom") + .WithMany() + .HasForeignKey("UomId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Item"); + + b.Navigation("RunStage"); + + b.Navigation("ScrapReason"); + + b.Navigation("Uom"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesDayEnd", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "CashierUser") + .WithMany() + .HasForeignKey("CashierUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "ClosedByUser") + .WithMany() + .HasForeignKey("ClosedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CashierUser"); + + b.Navigation("ClosedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoice", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatorUserId"); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("Customer"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoiceLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesInvoice", "SalesInvoice") + .WithMany("Lines") + .HasForeignKey("SalesInvoiceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SalesInvoice"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoicePayment", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesInvoice", "SalesInvoice") + .WithMany("Payments") + .HasForeignKey("SalesInvoiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("SalesInvoice"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturn", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ReasonCode") + .WithMany() + .HasForeignKey("ReasonCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("Customer"); + + b.Navigation("ReasonCode"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturnLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesReturn", "Return") + .WithMany("Lines") + .HasForeignKey("ReturnId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesInvoiceLine", "SalesInvoiceLine") + .WithMany() + .HasForeignKey("SalesInvoiceLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Item"); + + b.Navigation("Return"); + + b.Navigation("SalesInvoiceLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlip", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "CashierUser") + .WithMany() + .HasForeignKey("CashierUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesDayEnd", "DayEnd") + .WithMany("Slips") + .HasForeignKey("DayEndId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CashierUser"); + + b.Navigation("Customer"); + + b.Navigation("DayEnd"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlipLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesSlip", "SalesSlip") + .WithMany("Lines") + .HasForeignKey("SalesSlipId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SalesSlip"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Serial", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageEdge", b => + { + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "ChildStage") + .WithMany() + .HasForeignKey("ChildStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "ParentStage") + .WithMany() + .HasForeignKey("ParentStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") + .WithMany("Edges") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildStage"); + + b.Navigation("ParentStage"); + + b.Navigation("Template"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageInput", b => + { + b.HasOne("ERPCore.Domain.Entities.StageOutput", "FromOutput") + .WithMany() + .HasForeignKey("FromOutputId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "Stage") + .WithMany("Inputs") + .HasForeignKey("StageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromOutput"); + + b.Navigation("Item"); + + b.Navigation("Stage"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageOutput", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "Stage") + .WithMany("Outputs") + .HasForeignKey("StageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Uom", "Uom") + .WithMany() + .HasForeignKey("UomId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Item"); + + b.Navigation("Stage"); + + b.Navigation("Uom"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustment", 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.HasOne("ERPCore.Domain.Entities.ReasonCode", "ReasonCode") + .WithMany() + .HasForeignKey("ReasonCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("ReasonCode"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustmentLine", b => + { + b.HasOne("ERPCore.Domain.Entities.StockAdjustment", "Adjustment") + .WithMany("Lines") + .HasForeignKey("AdjustmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Batch", null) + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", null) + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Adjustment"); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCount", 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.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCountLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.StockCount", "Count") + .WithMany("Lines") + .HasForeignKey("CountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Count"); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLayer", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", "Batch") + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.GrnLine", "GrnLine") + .WithMany() + .HasForeignKey("GrnLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", "Serial") + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Batch"); + + b.Navigation("GrnLine"); + + b.Navigation("Item"); + + b.Navigation("Serial"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLedger", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", null) + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", null) + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", null) + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", null) + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransfer", 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.HasOne("ERPCore.Domain.Entities.Warehouse", "DestWarehouse") + .WithMany() + .HasForeignKey("DestWarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "SrcWarehouse") + .WithMany() + .HasForeignKey("SrcWarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("DestWarehouse"); + + b.Navigation("SrcWarehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransferLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", null) + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("DestBinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", null) + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("SrcBinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.StockTransfer", "Transfer") + .WithMany("Lines") + .HasForeignKey("TransferId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Transfer"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubCategory", b => + { + b.HasOne("ERPCore.Domain.Entities.Category", "Category") + .WithMany("SubCategories") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubNavItem", b => + { + b.HasOne("ERPCore.Domain.Entities.NavItem", "NavItem") + .WithMany("Children") + .HasForeignKey("NavItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("NavItem"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicketMessage", b => + { + b.HasOne("ERPCore.Domain.Entities.SupportTicket", "Ticket") + .WithMany("Messages") + .HasForeignKey("TicketId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ticket"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => + { + b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") + .WithMany("Stages") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Template"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.User", b => + { + b.HasOne("ERPCore.Domain.Entities.Role", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => + { + b.HasOne("ERPCore.Domain.Entities.Rfq", "Rfq") + .WithMany("Quotations") + .HasForeignKey("RfqId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Rfq"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotationLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.VendorQuotation", "Quotation") + .WithMany("Lines") + .HasForeignKey("QuotationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Quotation"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Warehouse", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSale", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplate", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Category", b => + { + b.Navigation("SubCategories"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeLoan", b => + { + b.Navigation("Installments"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructure", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Grn", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLine", b => + { + b.Navigation("WarrantyNumbers"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Item", b => + { + b.Navigation("ReorderSettings"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NavItem", b => + { + b.Navigation("Children"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Notification", b => + { + b.Navigation("Recipients"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => + { + b.Navigation("Modules"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => + { + b.Navigation("Components"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollRun", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b => + { + b.Navigation("Edges"); + + b.Navigation("Events"); + + b.Navigation("Stages"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionTemplate", b => + { + b.Navigation("Edges"); + + b.Navigation("Runs"); + + b.Navigation("Stages"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", b => + { + b.Navigation("Lines"); + + b.Navigation("Payments"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturn", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => + { + b.Navigation("Lines"); + + b.Navigation("Quotations"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStage", b => + { + b.Navigation("Events"); + + b.Navigation("Inputs"); + + b.Navigation("Outputs"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesDayEnd", b => + { + b.Navigation("BundleSales"); + + b.Navigation("Slips"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoice", b => + { + b.Navigation("Lines"); + + b.Navigation("Payments"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturn", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlip", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustment", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCount", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransfer", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicket", b => + { + b.Navigation("Messages"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => + { + b.Navigation("Inputs"); + + b.Navigation("Outputs"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Warehouse", b => + { + b.Navigation("Bins"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Backend/ERPCore/Migrations/20260915110359_AddPurchaseOrderApprovalAudit.cs b/Backend/ERPCore/Migrations/20260915110359_AddPurchaseOrderApprovalAudit.cs new file mode 100644 index 0000000..4cac8b4 --- /dev/null +++ b/Backend/ERPCore/Migrations/20260915110359_AddPurchaseOrderApprovalAudit.cs @@ -0,0 +1,69 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace ERPCore.Migrations +{ + /// + public partial class AddPurchaseOrderApprovalAudit : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "ApprovedAt", + table: "purchase_orders", + type: "timestamp with time zone", + nullable: true); + + migrationBuilder.AddColumn( + name: "ApprovedBy", + table: "purchase_orders", + type: "integer", + nullable: true); + + migrationBuilder.AddColumn( + name: "ApproverUserId", + table: "purchase_orders", + type: "integer", + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_purchase_orders_ApproverUserId", + table: "purchase_orders", + column: "ApproverUserId"); + + migrationBuilder.AddForeignKey( + name: "FK_purchase_orders_users_ApproverUserId", + table: "purchase_orders", + column: "ApproverUserId", + principalTable: "users", + principalColumn: "UserId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_purchase_orders_users_ApproverUserId", + table: "purchase_orders"); + + migrationBuilder.DropIndex( + name: "IX_purchase_orders_ApproverUserId", + table: "purchase_orders"); + + migrationBuilder.DropColumn( + name: "ApprovedAt", + table: "purchase_orders"); + + migrationBuilder.DropColumn( + name: "ApprovedBy", + table: "purchase_orders"); + + migrationBuilder.DropColumn( + name: "ApproverUserId", + table: "purchase_orders"); + } + } +} diff --git a/Backend/ERPCore/Migrations/20260916051856_AddRolePermissionActions.Designer.cs b/Backend/ERPCore/Migrations/20260916051856_AddRolePermissionActions.Designer.cs new file mode 100644 index 0000000..62869e9 --- /dev/null +++ b/Backend/ERPCore/Migrations/20260916051856_AddRolePermissionActions.Designer.cs @@ -0,0 +1,8448 @@ +// +using System; +using ERPCore.Infra.Persistence; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace ERPCore.Migrations +{ + [DbContext(typeof(ErpDbContext))] + [Migration("20260916051856_AddRolePermissionActions")] + partial class AddRolePermissionActions + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.9") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceRecord", b => + { + b.Property("AttendanceRecordId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AttendanceRecordId")); + + b.Property("AttendanceDate") + .HasColumnType("timestamp with time zone"); + + b.Property("AttendanceStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("AttendanceUploadBatchId") + .HasColumnType("integer"); + + b.Property("CheckIn") + .HasColumnType("interval"); + + b.Property("CheckOut") + .HasColumnType("interval"); + + b.Property("DuplicateOfAttendanceRecordId") + .HasColumnType("integer"); + + b.Property("EarlyLeaveMinutes") + .HasColumnType("integer"); + + b.Property("EditedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EditedBy") + .HasColumnType("integer"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("IsManualOverride") + .HasColumnType("boolean"); + + b.Property("LateMinutes") + .HasColumnType("integer"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("OvertimeMinutes") + .HasColumnType("integer"); + + b.Property("RowValidationStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("WorkShiftId") + .HasColumnType("integer"); + + b.Property("WorkingMinutes") + .HasColumnType("integer"); + + b.HasKey("AttendanceRecordId"); + + b.HasIndex("AttendanceUploadBatchId"); + + b.HasIndex("WorkShiftId"); + + b.HasIndex("EmployeeId", "AttendanceDate"); + + b.ToTable("hr_attendance_records", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceUploadBatch", b => + { + b.Property("AttendanceUploadBatchId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AttendanceUploadBatchId")); + + b.Property("ConfirmedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ConfirmedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("OriginalFileName") + .HasMaxLength(260) + .HasColumnType("character varying(260)"); + + b.Property("PeriodEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("PeriodStart") + .HasColumnType("timestamp with time zone"); + + b.Property("RowCountDuplicate") + .HasColumnType("integer"); + + b.Property("RowCountError") + .HasColumnType("integer"); + + b.Property("RowCountTotal") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SourceType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UploadedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UploadedBy") + .HasColumnType("integer"); + + b.HasKey("AttendanceUploadBatchId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("PeriodStart", "PeriodEnd"); + + b.ToTable("hr_attendance_upload_batches", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AuditLog", b => + { + b.Property("AuditId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AuditId")); + + b.Property("Action") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("ChangeSet") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EntityId") + .HasColumnType("integer"); + + b.Property("EntityType") + .IsRequired() + .HasMaxLength(80) + .HasColumnType("character varying(80)"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("AuditId"); + + b.HasIndex("CreatedAt"); + + b.HasIndex("UserId"); + + b.HasIndex("EntityType", "EntityId"); + + b.ToTable("audit_logs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Batch", b => + { + b.Property("BatchId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BatchId")); + + b.Property("BatchNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ExpiryDate") + .HasColumnType("date"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.HasKey("BatchId"); + + b.HasIndex("ItemId", "BatchNo") + .IsUnique(); + + b.ToTable("batches", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Bin", b => + { + b.Property("BinId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BinId")); + + b.Property("BinType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BinId"); + + b.HasIndex("WarehouseId", "Code") + .IsUnique(); + + b.ToTable("bins", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Branch", b => + { + b.Property("BranchId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BranchId")); + + b.Property("Address") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("PhoneNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_branches", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BranchConfig", b => + { + b.Property("ConfigId") + .HasColumnType("integer"); + + b.Property("BranchingEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.Property("WarehouseBranchingEnabled") + .HasColumnType("boolean"); + + b.HasKey("ConfigId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("branch_config", null, t => + { + t.HasCheckConstraint("ck_branch_config_singleton", "\"ConfigId\" = 1"); + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Brand", b => + { + b.Property("BrandId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BrandId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("BrandId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("brands", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSale", b => + { + b.Property("BundleSaleId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleId")); + + b.Property("BundleCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BundleDate") + .HasColumnType("timestamp with time zone"); + + b.Property("BundleName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("BundleNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BundlePrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BundleSaleTemplateId") + .HasColumnType("integer"); + + b.Property("CashierUserId") + .HasColumnType("integer"); + + b.Property("ComponentSubtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("CustomerSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DayEndId") + .HasColumnType("integer"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("MarginAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BundleSaleId"); + + b.HasIndex("BundleNo") + .IsUnique(); + + b.HasIndex("BundleSaleTemplateId"); + + b.HasIndex("CashierUserId"); + + b.HasIndex("CustomerId"); + + b.HasIndex("DayEndId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("bundle_sales", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleLine", b => + { + b.Property("BundleSaleLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleLineId")); + + b.Property("BundleSaleId") + .HasColumnType("integer"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("IncludeInBundle") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("IsComponent") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ParentLineId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BundleSaleLineId"); + + b.HasIndex("BundleSaleId"); + + b.HasIndex("ItemId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("bundle_sale_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplate", b => + { + b.Property("BundleSaleTemplateId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleTemplateId")); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TemplateCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("TemplateName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("BundleSaleTemplateId"); + + b.HasIndex("TemplateCode") + .IsUnique(); + + b.ToTable("bundle_sale_templates", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplateLine", b => + { + b.Property("BundleSaleTemplateLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleTemplateLineId")); + + b.Property("BundleSaleTemplateId") + .HasColumnType("integer"); + + b.Property("IncludeInBundle") + .HasColumnType("boolean"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SortOrder") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BundleSaleTemplateLineId"); + + b.HasIndex("BundleSaleTemplateId"); + + b.HasIndex("ItemId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("bundle_sale_template_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Category", b => + { + b.Property("CategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CategoryId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("CategoryId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("categories", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Customer", b => + { + b.Property("CustomerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CustomerId")); + + b.Property("AddressLine1") + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("AddressLine2") + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("City") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Country") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreditDays") + .HasColumnType("integer"); + + b.Property("CreditLimit") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CustomerCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CustomerType") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("B2C"); + + b.Property("DefaultWarehouseId") + .HasColumnType("integer"); + + b.Property("DisplayName") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Email") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Phone") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TaxRegistrationNo") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("CustomerId"); + + b.HasIndex("CustomerCode") + .IsUnique(); + + b.HasIndex("CustomerType"); + + b.HasIndex("DefaultWarehouseId"); + + b.HasIndex("Status"); + + b.ToTable("customers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Department", b => + { + b.Property("DepartmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("DepartmentId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("HeadEmployeeId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("ParentDepartmentId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("DepartmentId"); + + b.HasIndex("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("HeadEmployeeId"); + + b.HasIndex("ParentDepartmentId"); + + b.HasIndex("Status"); + + b.ToTable("hr_departments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Designation", b => + { + b.Property("DesignationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("DesignationId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("DesignationId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_designations", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Employee", b => + { + b.Property("EmployeeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeId")); + + b.Property("AddressLine1") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("AddressLine2") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("City") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ConfirmationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Country") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DateOfBirth") + .HasColumnType("timestamp with time zone"); + + b.Property("DepartmentId") + .HasColumnType("integer"); + + b.Property("DesignationId") + .HasColumnType("integer"); + + b.Property("Email") + .HasMaxLength(320) + .HasColumnType("character varying(320)"); + + b.Property("EmergencyContactName") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("EmergencyContactPhone") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmergencyContactRelationship") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("EmployeeCode") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmploymentTypeId") + .HasColumnType("integer"); + + b.Property("EpfNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EtfNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Gender") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("HireDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LastWorkingDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Nationality") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Nic") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PersonalMobile") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PostalCode") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ProfilePhotoPath") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("ReportingManagerId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TaxIdentificationNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.Property("WorkShiftId") + .HasColumnType("integer"); + + b.HasKey("EmployeeId"); + + b.HasIndex("BranchId"); + + b.HasIndex("DepartmentId"); + + b.HasIndex("DesignationId"); + + b.HasIndex("Email"); + + b.HasIndex("EmployeeCode") + .IsUnique(); + + b.HasIndex("EmploymentTypeId"); + + b.HasIndex("ReportingManagerId"); + + b.HasIndex("Status"); + + b.HasIndex("UserId") + .IsUnique(); + + b.HasIndex("WorkShiftId"); + + b.ToTable("hr_employees", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeBankDetail", b => + { + b.Property("EmployeeBankDetailId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeBankDetailId")); + + b.Property("AccountHolderName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("AccountNumber") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BankName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("BranchName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("IsPrimary") + .HasColumnType("boolean"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("SwiftCode") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("EmployeeBankDetailId"); + + b.HasIndex("EmployeeId"); + + b.ToTable("hr_employee_bank_details", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeDocument", b => + { + b.Property("EmployeeDocumentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeDocumentId")); + + b.Property("ContentType") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("ExpiryDate") + .HasColumnType("timestamp with time zone"); + + b.Property("HrDocumentTypeId") + .HasColumnType("integer"); + + b.Property("IssueDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("OriginalFileName") + .IsRequired() + .HasMaxLength(260) + .HasColumnType("character varying(260)"); + + b.Property("RelativePath") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SizeBytes") + .HasColumnType("bigint"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("StoredFileName") + .IsRequired() + .HasMaxLength(260) + .HasColumnType("character varying(260)"); + + b.Property("UploadedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UploadedBy") + .HasColumnType("integer"); + + b.Property("VerifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VerifiedBy") + .HasColumnType("integer"); + + b.HasKey("EmployeeDocumentId"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("ExpiryDate"); + + b.HasIndex("HrDocumentTypeId"); + + b.ToTable("hr_employee_documents", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeLoan", b => + { + b.Property("EmployeeLoanId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeLoanId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("InstallmentAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("InterestRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("LoanKind") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("NumberOfInstallments") + .HasColumnType("integer"); + + b.Property("OutstandingBalance") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("PrincipalAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("StartMonth") + .HasColumnType("integer"); + + b.Property("StartYear") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("EmployeeLoanId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("EmployeeId"); + + b.HasIndex("Status"); + + b.ToTable("hr_employee_loans", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructure", b => + { + b.Property("EmployeeSalaryStructureId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeSalaryStructureId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("BasicSalary") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("Currency") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("character varying(3)"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveTo") + .HasColumnType("timestamp with time zone"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("EmployeeSalaryStructureId"); + + b.HasIndex("EmployeeId", "EffectiveTo"); + + b.ToTable("hr_employee_salary_structures", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructureLine", b => + { + b.Property("EmployeeSalaryStructureLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeSalaryStructureLineId")); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("EmployeeSalaryStructureId") + .HasColumnType("integer"); + + b.Property("SalaryComponentId") + .HasColumnType("integer"); + + b.HasKey("EmployeeSalaryStructureLineId"); + + b.HasIndex("EmployeeSalaryStructureId"); + + b.HasIndex("SalaryComponentId"); + + b.ToTable("hr_employee_salary_structure_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmploymentType", b => + { + b.Property("EmploymentTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmploymentTypeId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("EmploymentTypeId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_employment_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Grn", b => + { + b.Property("GrnId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("GrnId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PoId") + .HasColumnType("integer"); + + b.Property("PostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PurchaseInvoiceId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("GrnId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("PoId"); + + b.HasIndex("PurchaseInvoiceId"); + + b.HasIndex("Status"); + + b.HasIndex("VendorId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("grns", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLine", b => + { + b.Property("GrnLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("GrnLineId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("DiscountPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("GrnId") + .HasColumnType("integer"); + + b.Property("HoldStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("NetUnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("PoLineId") + .HasColumnType("integer"); + + b.Property("PoUnitPrice") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReceivedValue") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("VatAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("VatPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.HasKey("GrnLineId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("GrnId"); + + b.HasIndex("ItemId"); + + b.HasIndex("PoLineId"); + + b.ToTable("grn_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLineWarrantyNumber", b => + { + b.Property("GrnLineWarrantyNumberId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("GrnLineWarrantyNumberId")); + + b.Property("GrnLineId") + .HasColumnType("integer"); + + b.Property("WarrantyNo") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("WarrantyPeriodMonths") + .HasColumnType("integer"); + + b.HasKey("GrnLineWarrantyNumberId"); + + b.HasIndex("GrnLineId", "WarrantyNo") + .IsUnique(); + + b.ToTable("grn_line_warranty_numbers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.HrDocumentType", b => + { + b.Property("HrDocumentTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("HrDocumentTypeId")); + + b.Property("Category") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpiryTracked") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RequiredAtOnboarding") + .HasColumnType("boolean"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("HrDocumentTypeId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_document_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Item", b => + { + b.Property("ItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ItemId")); + + b.Property("BaseUomId") + .HasColumnType("integer"); + + b.Property("BrandId") + .HasColumnType("integer"); + + b.Property("CategoryId") + .HasColumnType("integer"); + + b.Property("ContentBaseQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ContentBaseUnit") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ContentQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ContentUnit") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DefaultVendorId") + .HasColumnType("integer"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SellingFlatPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SellingMaxPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SellingMinPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Sku") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("StockNature") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("SubCategoryId") + .HasColumnType("integer"); + + b.Property("TaxClass") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("TrackingMode") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Warranty") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("NonWarranty"); + + b.Property("WarrantyPeriodMonths") + .HasColumnType("integer"); + + b.HasKey("ItemId"); + + b.HasIndex("BaseUomId"); + + b.HasIndex("BrandId"); + + b.HasIndex("CategoryId"); + + b.HasIndex("DefaultVendorId"); + + b.HasIndex("Sku") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("SubCategoryId"); + + b.ToTable("items", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ItemReorder", b => + { + b.Property("ReorderId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReorderId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("ReorderPoint") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReorderQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("ReorderId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("ItemId", "WarehouseId") + .IsUnique(); + + b.ToTable("item_reorders", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ItemType", b => + { + b.Property("ItemTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ItemTypeId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsMeasurable") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("ItemTypeId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("item_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.JournalEntryStub", b => + { + b.Property("JournalId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("JournalId")); + + b.Property("Amount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CreditAccount") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("DebitAccount") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("SourceDocId") + .HasColumnType("integer"); + + b.Property("SourceDocType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.HasKey("JournalId"); + + b.HasIndex("SourceDocType", "SourceDocId"); + + b.ToTable("journal_entry_stubs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveBalance", b => + { + b.Property("LeaveBalanceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LeaveBalanceId")); + + b.Property("AdjustmentDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("CarriedForwardDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("EntitledDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("LeaveTypeId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("TakenDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Year") + .HasColumnType("integer"); + + b.HasKey("LeaveBalanceId"); + + b.HasIndex("LeaveTypeId"); + + b.HasIndex("EmployeeId", "LeaveTypeId", "Year") + .IsUnique(); + + b.ToTable("hr_leave_balances", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveRequest", b => + { + b.Property("LeaveRequestId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LeaveRequestId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DaysCount") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("EndDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LeaveTypeId") + .HasColumnType("integer"); + + b.Property("Reason") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("RejectionReason") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("StartDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("LeaveRequestId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("EmployeeId"); + + b.HasIndex("LeaveTypeId"); + + b.HasIndex("Status"); + + b.HasIndex("StartDate", "EndDate"); + + b.ToTable("hr_leave_requests", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveType", b => + { + b.Property("LeaveTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LeaveTypeId")); + + b.Property("AccrualPerYear") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("CarryForwardAllowed") + .HasColumnType("boolean"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CountsAsNoPay") + .HasColumnType("boolean"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsPaid") + .HasColumnType("boolean"); + + b.Property("MaxCarryForwardDays") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RequiresApproval") + .HasColumnType("boolean"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("LeaveTypeId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_leave_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoanInstallment", b => + { + b.Property("LoanInstallmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LoanInstallmentId")); + + b.Property("DueMonth") + .HasColumnType("integer"); + + b.Property("DueYear") + .HasColumnType("integer"); + + b.Property("EmployeeLoanId") + .HasColumnType("integer"); + + b.Property("InstallmentNumber") + .HasColumnType("integer"); + + b.Property("PaidAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("PayrollRunId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("ScheduledAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("LoanInstallmentId"); + + b.HasIndex("EmployeeLoanId"); + + b.HasIndex("PayrollRunId"); + + b.HasIndex("DueYear", "DueMonth"); + + b.ToTable("hr_loan_installments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoginActivity", b => + { + b.Property("LoginActivityId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LoginActivityId")); + + b.Property("DeviceLabel") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("IpAddress") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("LoginAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserAgent") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("LoginActivityId"); + + b.HasIndex("UserId", "LoginAt"); + + b.ToTable("login_activities", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NavItem", b => + { + b.Property("NavItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NavItemId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Href") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Icon") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.HasKey("NavItemId"); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("nav_items", (string)null); + + b.HasData( + new + { + NavItemId = 1, + Code = "dashboard", + Href = "/dashboard", + Label = "Dashboard", + SortOrder = 1, + Status = "Active" + }, + new + { + NavItemId = 2, + Code = "products", + Href = "/dashboard/products", + Label = "Products", + SortOrder = 2, + Status = "Active" + }, + new + { + NavItemId = 4, + Code = "procurement", + Href = "/dashboard/procurement", + Label = "Procurement", + SortOrder = 4, + Status = "Active" + }, + new + { + NavItemId = 5, + Code = "receiving", + Href = "/dashboard/receiving/grn", + Label = "Receiving", + SortOrder = 5, + Status = "Active" + }, + new + { + NavItemId = 6, + Code = "stock", + Href = "/dashboard/stock", + Label = "Stock", + SortOrder = 6, + Status = "Active" + }, + new + { + NavItemId = 7, + Code = "warehouses", + Href = "/dashboard/warehouse", + Label = "Warehouses", + SortOrder = 7, + Status = "Active" + }, + new + { + NavItemId = 8, + Code = "orders", + Href = "/dashboard/orders", + Label = "Orders", + SortOrder = 8, + Status = "Active" + }, + new + { + NavItemId = 9, + Code = "settings", + Href = "/dashboard/settings", + Label = "Settings", + SortOrder = 9, + Status = "Active" + }, + new + { + NavItemId = 10, + Code = "help", + Href = "/dashboard/help", + Label = "Help", + SortOrder = 10, + Status = "Active" + }, + new + { + NavItemId = 11, + Code = "ledgers", + Href = "/dashboard/ledgers", + Label = "Ledgers", + SortOrder = 11, + Status = "Active" + }, + new + { + NavItemId = 12, + Code = "accounts", + Href = "/dashboard/accounts", + Label = "Accounts", + SortOrder = 12, + Status = "Active" + }, + new + { + NavItemId = 13, + Code = "sales", + Href = "/dashboard/sales", + Label = "Sales", + SortOrder = 13, + Status = "Active" + }, + new + { + NavItemId = 14, + Code = "production", + Href = "/dashboard/production", + Label = "Production", + SortOrder = 14, + Status = "Active" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Notification", b => + { + b.Property("NotificationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NotificationId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("ModuleKey") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("RelatedEntityId") + .HasColumnType("integer"); + + b.Property("RelatedEntityType") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.HasKey("NotificationId"); + + b.HasIndex("CreatedAt"); + + b.ToTable("notifications", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => + { + b.Property("NotificationConfigId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.HasKey("NotificationConfigId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("notification_config", null, t => + { + t.HasCheckConstraint("ck_notification_config_singleton", "\"NotificationConfigId\" = 1"); + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfigModule", b => + { + b.Property("NotificationConfigModuleId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NotificationConfigModuleId")); + + b.Property("EmailEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("InAppEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("ModuleKey") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("NotificationConfigId") + .HasColumnType("integer"); + + b.Property("SmsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.HasKey("NotificationConfigModuleId"); + + b.HasIndex("ModuleKey") + .IsUnique(); + + b.HasIndex("NotificationConfigId"); + + b.ToTable("notification_config_modules", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationRecipient", b => + { + b.Property("NotificationRecipientId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NotificationRecipientId")); + + b.Property("IsRead") + .HasColumnType("boolean"); + + b.Property("NotificationId") + .HasColumnType("integer"); + + b.Property("ReadAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("NotificationRecipientId"); + + b.HasIndex("NotificationId"); + + b.HasIndex("UserId", "IsRead", "NotificationId"); + + b.ToTable("notification_recipients", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NumberSequence", b => + { + b.Property("SequenceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SequenceId")); + + b.Property("DocType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("doc_type"); + + b.Property("LastNumber") + .HasColumnType("integer") + .HasColumnName("last_number"); + + b.Property("Year") + .HasColumnType("integer") + .HasColumnName("year"); + + b.HasKey("SequenceId"); + + b.HasIndex("DocType", "Year") + .IsUnique(); + + b.ToTable("number_sequences", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => + { + b.Property("PayrollLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollLineId")); + + b.Property("AbsentDays") + .HasColumnType("integer"); + + b.Property("BasicSalary") + .HasColumnType("numeric(18,2)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("EpfEmployeeAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("EpfEmployerAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("EtfEmployerAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("GrossSalary") + .HasColumnType("numeric(18,2)"); + + b.Property("LateDeductionAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("LateMinutesTotal") + .HasColumnType("integer"); + + b.Property("LeaveDays") + .HasColumnType("integer"); + + b.Property("LoanDeductionAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("NetSalary") + .HasColumnType("numeric(18,2)"); + + b.Property("NoPayAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("OtMinutesTotal") + .HasColumnType("integer"); + + b.Property("OtherDeductionsAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("OvertimeAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("PayrollRunId") + .HasColumnType("integer"); + + b.Property("PresentDays") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("TaxAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("TotalAllowances") + .HasColumnType("numeric(18,2)"); + + b.Property("WorkingDays") + .HasColumnType("integer"); + + b.HasKey("PayrollLineId"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("PayrollRunId", "EmployeeId") + .IsUnique(); + + b.ToTable("hr_payroll_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLineComponent", b => + { + b.Property("PayrollLineComponentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollLineComponentId")); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("ComponentCategory") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("PayrollLineId") + .HasColumnType("integer"); + + b.Property("SalaryComponentId") + .HasColumnType("integer"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.HasKey("PayrollLineComponentId"); + + b.HasIndex("PayrollLineId"); + + b.HasIndex("SalaryComponentId"); + + b.ToTable("hr_payroll_line_components", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollRun", b => + { + b.Property("PayrollRunId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollRunId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GeneratedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GeneratedBy") + .HasColumnType("integer"); + + b.Property("LockedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("LockedBy") + .HasColumnType("integer"); + + b.Property("PeriodMonth") + .HasColumnType("integer"); + + b.Property("PeriodYear") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UnlockReason") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("UnlockedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UnlockedBy") + .HasColumnType("integer"); + + b.HasKey("PayrollRunId"); + + b.HasIndex("BranchId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("PeriodYear", "PeriodMonth", "BranchId"); + + b.ToTable("hr_payroll_runs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollStatutorySetting", b => + { + b.Property("PayrollStatutorySettingId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollStatutorySettingId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveTo") + .HasColumnType("timestamp with time zone"); + + b.Property("EpfEmployeeRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("EpfEmployerRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("EtfEmployerRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("OtMultiplierDefault") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.HasKey("PayrollStatutorySettingId"); + + b.HasIndex("EffectiveFrom"); + + b.ToTable("hr_payroll_statutory_settings", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Payslip", b => + { + b.Property("PayslipId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayslipId")); + + b.Property("GeneratedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PayrollLineId") + .HasColumnType("integer"); + + b.Property("ReleasedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReleasedBy") + .HasColumnType("integer"); + + b.HasKey("PayslipId"); + + b.HasIndex("PayrollLineId") + .IsUnique(); + + b.ToTable("hr_payslips", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Permission", b => + { + b.Property("PermissionId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PermissionId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(80) + .HasColumnType("character varying(80)"); + + b.Property("NavItemId") + .HasColumnType("integer"); + + b.Property("SubNavItemId") + .HasColumnType("integer"); + + b.HasKey("PermissionId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("NavItemId"); + + b.HasIndex("SubNavItemId"); + + b.ToTable("permissions", (string)null); + + b.HasData( + new + { + PermissionId = 1, + Code = "NAV:dashboard", + NavItemId = 1 + }, + new + { + PermissionId = 2, + Code = "NAV:products", + NavItemId = 2 + }, + new + { + PermissionId = 3, + Code = "NAV:procurement.vendors", + SubNavItemId = 30 + }, + new + { + PermissionId = 4, + Code = "NAV:procurement", + NavItemId = 4 + }, + new + { + PermissionId = 5, + Code = "NAV:receiving", + NavItemId = 5 + }, + new + { + PermissionId = 6, + Code = "NAV:stock", + NavItemId = 6 + }, + new + { + PermissionId = 7, + Code = "NAV:warehouses", + NavItemId = 7 + }, + new + { + PermissionId = 8, + Code = "NAV:orders", + NavItemId = 8 + }, + new + { + PermissionId = 9, + Code = "NAV:settings", + NavItemId = 9 + }, + new + { + PermissionId = 10, + Code = "NAV:help", + NavItemId = 10 + }, + new + { + PermissionId = 11, + Code = "NAV:products.item", + SubNavItemId = 1 + }, + new + { + PermissionId = 12, + Code = "NAV:products.category", + SubNavItemId = 2 + }, + new + { + PermissionId = 13, + Code = "NAV:products.brand", + SubNavItemId = 3 + }, + new + { + PermissionId = 14, + Code = "NAV:products.item-type", + SubNavItemId = 4 + }, + new + { + PermissionId = 15, + Code = "NAV:products.uom", + SubNavItemId = 5 + }, + new + { + PermissionId = 16, + Code = "NAV:products.configuration", + SubNavItemId = 6 + }, + new + { + PermissionId = 17, + Code = "NAV:settings.roles", + SubNavItemId = 7 + }, + new + { + PermissionId = 18, + Code = "NAV:settings.users", + SubNavItemId = 8 + }, + new + { + PermissionId = 28, + Code = "NAV:procurement.requisitions", + SubNavItemId = 17 + }, + new + { + PermissionId = 29, + Code = "NAV:procurement.rfqs", + SubNavItemId = 18 + }, + new + { + PermissionId = 30, + Code = "NAV:procurement.purchase-orders", + SubNavItemId = 19 + }, + new + { + PermissionId = 31, + Code = "NAV:procurement.purchase-returns", + SubNavItemId = 20 + }, + new + { + PermissionId = 19, + Code = "NAV:ledgers", + NavItemId = 11 + }, + new + { + PermissionId = 20, + Code = "NAV:ledgers.trial-balance", + SubNavItemId = 9 + }, + new + { + PermissionId = 21, + Code = "NAV:ledgers.balance-sheet", + SubNavItemId = 10 + }, + new + { + PermissionId = 22, + Code = "NAV:ledgers.general-ledger", + SubNavItemId = 11 + }, + new + { + PermissionId = 23, + Code = "NAV:ledgers.profit-and-loss", + SubNavItemId = 12 + }, + new + { + PermissionId = 24, + Code = "NAV:ledgers.cash-flow", + SubNavItemId = 13 + }, + new + { + PermissionId = 25, + Code = "NAV:ledgers.budget-vs-actual", + SubNavItemId = 14 + }, + new + { + PermissionId = 27, + Code = "NAV:ledgers.tax-report", + SubNavItemId = 16 + }, + new + { + PermissionId = 26, + Code = "NAV:accounts.bank-accounts", + SubNavItemId = 15 + }, + new + { + PermissionId = 32, + Code = "NAV:accounts", + NavItemId = 12 + }, + new + { + PermissionId = 33, + Code = "NAV:accounts.cheque-books", + SubNavItemId = 21 + }, + new + { + PermissionId = 34, + Code = "NAV:accounts.received-cheques", + SubNavItemId = 22 + }, + new + { + PermissionId = 35, + Code = "NAV:production", + NavItemId = 14 + }, + new + { + PermissionId = 36, + Code = "NAV:production.templates", + SubNavItemId = 27 + }, + new + { + PermissionId = 37, + Code = "NAV:production.runs", + SubNavItemId = 25 + }, + new + { + PermissionId = 38, + Code = "NAV:production.produced", + SubNavItemId = 26 + }, + new + { + PermissionId = 39, + Code = "NAV:procurement.purchase-invoices", + SubNavItemId = 28 + }, + new + { + PermissionId = 40, + Code = "NAV:settings.branches", + SubNavItemId = 29 + }, + new + { + PermissionId = 41, + Code = "NAV:stock.ledger", + SubNavItemId = 31 + }, + new + { + PermissionId = 42, + Code = "NAV:stock.enquiry", + SubNavItemId = 32 + }, + new + { + PermissionId = 43, + Code = "NAV:stock.valuation", + SubNavItemId = 33 + }, + new + { + PermissionId = 44, + Code = "NAV:stock.transfers", + SubNavItemId = 34 + }, + new + { + PermissionId = 45, + Code = "NAV:stock.adjustments", + SubNavItemId = 35 + }, + new + { + PermissionId = 46, + Code = "NAV:stock.counts", + SubNavItemId = 36 + }, + new + { + PermissionId = 47, + Code = "NAV:stock.reorder-alerts", + SubNavItemId = 37 + }, + new + { + PermissionId = 48, + Code = "NAV:stock.wastage", + SubNavItemId = 38 + }, + new + { + PermissionId = 49, + Code = "NAV:sales.bundle-templates", + SubNavItemId = 23 + }, + new + { + PermissionId = 50, + Code = "NAV:sales.invoices", + SubNavItemId = 40 + }, + new + { + PermissionId = 51, + Code = "NAV:sales.free-issues", + SubNavItemId = 41 + }, + new + { + PermissionId = 52, + Code = "NAV:sales.day-end", + SubNavItemId = 42 + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PoLine", b => + { + b.Property("PoLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PoLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("PoId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyReceived") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Tax") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("PoLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("PoId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("po_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductConfig", b => + { + b.Property("ConfigId") + .HasColumnType("integer"); + + b.Property("BatchListsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("BrandsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("ItemTypesEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SellingPricesEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("SerialNumbersEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("SubcategoriesEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.Property("WarrantyPeriodsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.HasKey("ConfigId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("product_config", null, t => + { + t.HasCheckConstraint("ck_product_config_singleton", "\"ConfigId\" = 1"); + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b => + { + b.Property("RunId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunId")); + + b.Property("CancelReasonCodeId") + .HasColumnType("integer"); + + b.Property("CompletedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("OutputBinId") + .HasColumnType("integer"); + + b.Property("ReworkCount") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("ScaleFactor") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("TargetQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TemplateId") + .HasColumnType("integer"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("RunId"); + + b.HasIndex("CancelReasonCodeId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("OutputBinId"); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("TemplateId", "Status"); + + b.ToTable("production_runs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionTemplate", b => + { + b.Property("TemplateId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TemplateId")); + + b.Property("Annotations") + .HasColumnType("jsonb"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("TemplateId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("CreatedBy"); + + b.HasIndex("Status"); + + b.ToTable("production_templates", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", b => + { + b.Property("PurchaseInvoiceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PurchaseInvoiceId")); + + b.Property("BalanceAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VatTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.Property("VendorInvoiceDate") + .HasColumnType("timestamp with time zone"); + + b.Property("VendorInvoiceNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("VendorSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("VendorSnapshotTaxNo") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("PurchaseInvoiceId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("VendorId"); + + b.HasIndex("VendorId", "VendorInvoiceNo"); + + b.ToTable("purchase_invoices", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoiceLine", b => + { + b.Property("PurchaseInvoiceLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PurchaseInvoiceLineId")); + + b.Property("GrnId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PurchaseInvoiceId") + .HasColumnType("integer"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("VatTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("PurchaseInvoiceLineId"); + + b.HasIndex("GrnId") + .IsUnique(); + + b.HasIndex("PurchaseInvoiceId"); + + b.ToTable("purchase_invoice_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoicePayment", b => + { + b.Property("PurchaseInvoicePaymentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PurchaseInvoicePaymentId")); + + b.Property("Amount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BankAccountName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("GlBankAccountId") + .HasColumnType("bigint"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PaymentDate") + .HasColumnType("timestamp with time zone"); + + b.Property("PurchaseInvoiceId") + .HasColumnType("integer"); + + b.Property("Reference") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("PurchaseInvoicePaymentId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("PurchaseInvoiceId"); + + b.ToTable("purchase_invoice_payments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => + { + b.Property("PoId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PoId")); + + b.Property("ApprovalRequired") + .HasColumnType("boolean"); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("ApproverUserId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RequisitionId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.HasKey("PoId"); + + b.HasIndex("ApproverUserId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("RequisitionId"); + + b.HasIndex("Status"); + + b.HasIndex("VendorId"); + + b.ToTable("purchase_orders", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturn", b => + { + b.Property("ReturnId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReasonCodeId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("ReturnId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("ReasonCodeId"); + + b.HasIndex("VendorId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("purchase_returns", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturnLine", b => + { + b.Property("ReturnLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnLineId")); + + b.Property("GrnLineId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReturnId") + .HasColumnType("integer"); + + b.HasKey("ReturnLineId"); + + b.HasIndex("GrnLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("ReturnId"); + + b.ToTable("purchase_return_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ReasonCode", b => + { + b.Property("ReasonCodeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReasonCodeId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Context") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.HasKey("ReasonCodeId"); + + b.HasIndex("Context", "Code") + .IsUnique(); + + b.ToTable("reason_codes", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => + { + b.Property("RequisitionId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RequisitionId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RequestedBy") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("RequisitionId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("RequestedBy"); + + b.HasIndex("Status"); + + b.ToTable("requisitions", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RequisitionLine", b => + { + b.Property("ReqLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReqLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RequiredBy") + .HasColumnType("date"); + + b.Property("RequisitionId") + .HasColumnType("integer"); + + b.HasKey("ReqLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RequisitionId"); + + b.ToTable("requisition_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => + { + b.Property("RfqId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RfqId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RequisitionId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("RfqId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("RequisitionId"); + + b.ToTable("rfqs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RfqLine", b => + { + b.Property("RfqLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RfqLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RfqId") + .HasColumnType("integer"); + + b.HasKey("RfqLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RfqId"); + + b.ToTable("rfq_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Role", b => + { + b.Property("RoleId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RoleId")); + + b.Property("AuthRoleId") + .HasColumnType("uuid") + .HasColumnName("auth_role_id"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsSystemRole") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("RoleId"); + + b.HasIndex("AuthRoleId") + .IsUnique(); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("roles", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RolePermission", b => + { + b.Property("RoleId") + .HasColumnType("integer"); + + b.Property("PermissionId") + .HasColumnType("integer"); + + b.Property("Actions") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(31); + + b.HasKey("RoleId", "PermissionId"); + + b.HasIndex("PermissionId"); + + b.ToTable("role_permissions", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunEdge", b => + { + b.Property("RunEdgeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunEdgeId")); + + b.Property("ChildRunStageId") + .HasColumnType("integer"); + + b.Property("ParentRunStageId") + .HasColumnType("integer"); + + b.Property("RunId") + .HasColumnType("integer"); + + b.HasKey("RunEdgeId"); + + b.HasIndex("ChildRunStageId"); + + b.HasIndex("RunId"); + + b.HasIndex("ParentRunStageId", "ChildRunStageId") + .IsUnique(); + + b.ToTable("run_edges", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStage", b => + { + b.Property("RunStageId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunStageId")); + + b.Property("ActualEndAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ActualStartAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EstimatedMinutes") + .HasColumnType("integer"); + + b.Property("FieldDefs") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("FieldValues") + .HasColumnType("jsonb"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("PosX") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PosY") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RoleLabel") + .HasMaxLength(60) + .HasColumnType("character varying(60)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("RunId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("TemplateStageId") + .HasColumnType("integer"); + + b.HasKey("RunStageId"); + + b.HasIndex("TemplateStageId"); + + b.HasIndex("RunId", "Status"); + + b.ToTable("run_stages", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageEvent", b => + { + b.Property("EventId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EventId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Note") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Payload") + .HasColumnType("jsonb"); + + b.Property("RunId") + .HasColumnType("integer"); + + b.Property("RunStageId") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("EventId"); + + b.HasIndex("RunStageId"); + + b.HasIndex("UserId"); + + b.HasIndex("RunId", "EventId"); + + b.ToTable("run_stage_events", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageInput", b => + { + b.Property("RunInputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunInputId")); + + b.Property("ConsumedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ConsumedValue") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DeliveredQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("FromRunOutputId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("PlannedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyUnit") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ReturnedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReturnedValue") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RunStageId") + .HasColumnType("integer"); + + b.Property("Source") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("RunInputId"); + + b.HasIndex("FromRunOutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RunStageId"); + + b.ToTable("run_stage_inputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageOutput", b => + { + b.Property("RunOutputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunOutputId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("PlannedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ProducedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RunStageId") + .HasColumnType("integer"); + + b.Property("ScrapReasonCodeId") + .HasColumnType("integer"); + + b.Property("ScrappedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TransferredQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UomId") + .HasColumnType("integer"); + + b.HasKey("RunOutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RunStageId"); + + b.HasIndex("ScrapReasonCodeId"); + + b.HasIndex("UomId"); + + b.ToTable("run_stage_outputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalaryComponent", b => + { + b.Property("SalaryComponentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalaryComponentId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ComponentType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsEpfEtfApplicable") + .HasColumnType("boolean"); + + b.Property("IsTaxable") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("SalaryComponentId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_salary_components", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesDayEnd", b => + { + b.Property("SalesDayEndId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesDayEndId")); + + b.Property("BundleCount") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("BusinessDate") + .HasColumnType("date"); + + b.Property("CashierUserId") + .HasColumnType("integer"); + + b.Property("ClosedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ClosedBy") + .HasColumnType("integer"); + + b.Property("CostOfGoodsSold") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SlipCount") + .HasColumnType("integer"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("SalesDayEndId"); + + b.HasIndex("ClosedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("CashierUserId", "BusinessDate") + .IsUnique(); + + b.ToTable("sales_day_ends", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoice", b => + { + b.Property("SalesInvoiceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesInvoiceId")); + + b.Property("BalanceAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("CreatorUserId") + .HasColumnType("integer"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("CustomerSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CustomerSnapshotTaxNo") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("InvoiceDate") + .HasColumnType("timestamp with time zone"); + + b.Property("InvoiceNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("InvoiceType") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("B2C"); + + b.Property("NetPayable") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RoundOff") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesInvoiceId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatorUserId"); + + b.HasIndex("CustomerId"); + + b.HasIndex("InvoiceDate"); + + b.HasIndex("InvoiceNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_invoices", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoiceLine", b => + { + b.Property("SalesInvoiceLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesInvoiceLineId")); + + b.Property("BaseCost") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DiscountAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DiscountMode") + .HasColumnType("integer"); + + b.Property("DiscountPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("FreeQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("IsFreeIssue") + .HasColumnType("boolean"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("NetUnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ParentLineId") + .HasColumnType("integer"); + + b.Property("PriceSource") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SalesInvoiceId") + .HasColumnType("integer"); + + b.Property("TaxAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesInvoiceLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SalesInvoiceId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_invoice_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoicePayment", b => + { + b.Property("SalesInvoicePaymentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesInvoicePaymentId")); + + b.Property("Amount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BankAccountName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("GlBankAccountId") + .HasColumnType("bigint"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PaymentDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Reference") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("SalesInvoiceId") + .HasColumnType("integer"); + + b.HasKey("SalesInvoicePaymentId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("SalesInvoiceId"); + + b.ToTable("sales_invoice_payments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturn", b => + { + b.Property("ReturnId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReasonCodeId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("ReturnId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("CustomerId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("ReasonCodeId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_returns", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturnLine", b => + { + b.Property("ReturnLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReturnId") + .HasColumnType("integer"); + + b.Property("SalesInvoiceLineId") + .HasColumnType("integer"); + + b.HasKey("ReturnLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("ReturnId"); + + b.HasIndex("SalesInvoiceLineId"); + + b.ToTable("sales_return_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlip", b => + { + b.Property("SalesSlipId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesSlipId")); + + b.Property("BalanceAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CashierUserId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("CustomerSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DayEndId") + .HasColumnType("integer"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SlipDate") + .HasColumnType("timestamp with time zone"); + + b.Property("SlipNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesSlipId"); + + b.HasIndex("CashierUserId"); + + b.HasIndex("CustomerId"); + + b.HasIndex("DayEndId"); + + b.HasIndex("SlipDate"); + + b.HasIndex("SlipNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_slips", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlipLine", b => + { + b.Property("SalesSlipLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesSlipLineId")); + + b.Property("BaseCost") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DiscountAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DiscountMode") + .HasColumnType("integer"); + + b.Property("DiscountPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("FreeQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("IsFreeIssue") + .HasColumnType("boolean"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("NetUnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ParentLineId") + .HasColumnType("integer"); + + b.Property("PriceSource") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SalesSlipId") + .HasColumnType("integer"); + + b.Property("TaxAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesSlipLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SalesSlipId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_slip_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Serial", b => + { + b.Property("SerialId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SerialId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("SerialNo") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("SerialId"); + + b.HasIndex("ItemId", "SerialNo") + .IsUnique(); + + b.ToTable("serials", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageEdge", b => + { + b.Property("EdgeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EdgeId")); + + b.Property("ChildStageId") + .HasColumnType("integer"); + + b.Property("ParentStageId") + .HasColumnType("integer"); + + b.Property("TemplateId") + .HasColumnType("integer"); + + b.HasKey("EdgeId"); + + b.HasIndex("ChildStageId"); + + b.HasIndex("TemplateId"); + + b.HasIndex("ParentStageId", "ChildStageId") + .IsUnique(); + + b.ToTable("stage_edges", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageInput", b => + { + b.Property("InputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("InputId")); + + b.Property("FromOutputId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyPerBatch") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyUnit") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Source") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("StageId") + .HasColumnType("integer"); + + b.HasKey("InputId"); + + b.HasIndex("FromOutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("StageId"); + + b.ToTable("stage_inputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageOutput", b => + { + b.Property("OutputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("OutputId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("QtyPerBatch") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("StageId") + .HasColumnType("integer"); + + b.Property("UomId") + .HasColumnType("integer"); + + b.HasKey("OutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("StageId"); + + b.HasIndex("UomId"); + + b.ToTable("stage_outputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustment", b => + { + b.Property("AdjustmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AdjustmentId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReasonCodeId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("AdjustmentId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("ReasonCodeId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("stock_adjustments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustmentLine", b => + { + b.Property("AdjLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AdjLineId")); + + b.Property("AdjustmentId") + .HasColumnType("integer"); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyDelta") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.HasKey("AdjLineId"); + + b.HasIndex("AdjustmentId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SerialId"); + + b.ToTable("stock_adjustment_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCount", b => + { + b.Property("CountId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CountId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CountType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("CountId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("stock_counts", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCountLine", b => + { + b.Property("CountLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CountLineId")); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("CountId") + .HasColumnType("integer"); + + b.Property("CountedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("SystemQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Variance") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("CountLineId"); + + b.HasIndex("BinId"); + + b.HasIndex("CountId"); + + b.HasIndex("ItemId"); + + b.ToTable("stock_count_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLayer", b => + { + b.Property("LayerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LayerId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("GrnLineId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyReceived") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyRemaining") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReceiptDate") + .HasColumnType("timestamp with time zone"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("LayerId"); + + b.HasIndex("BatchId"); + + b.HasIndex("GrnLineId"); + + b.HasIndex("SerialId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("ItemId", "WarehouseId", "ReceiptDate", "LayerId"); + + b.ToTable("stock_layers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLedger", b => + { + b.Property("LedgerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LedgerId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Direction") + .IsRequired() + .HasMaxLength(5) + .HasColumnType("character varying(5)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyBase") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RunningBalance") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("SourceDocId") + .HasColumnType("integer"); + + b.Property("SourceDocType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.Property("Value") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("LedgerId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("SerialId"); + + b.HasIndex("UserId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("SourceDocType", "SourceDocId"); + + b.HasIndex("ItemId", "WarehouseId", "CreatedAt"); + + b.HasIndex("ItemId", "WarehouseId", "LedgerId"); + + b.ToTable("stock_ledger", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransfer", b => + { + b.Property("TransferId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TransferId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DestWarehouseId") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SrcWarehouseId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("TransferId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DestWarehouseId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("SrcWarehouseId"); + + b.HasIndex("Status"); + + b.ToTable("stock_transfers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransferLine", b => + { + b.Property("TransferLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TransferLineId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("DestBinId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyReceived") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("SrcBinId") + .HasColumnType("integer"); + + b.Property("TransferId") + .HasColumnType("integer"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.HasKey("TransferLineId"); + + b.HasIndex("BatchId"); + + b.HasIndex("DestBinId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SerialId"); + + b.HasIndex("SrcBinId"); + + b.HasIndex("TransferId"); + + b.ToTable("stock_transfer_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubCategory", b => + { + b.Property("SubCategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SubCategoryId")); + + b.Property("CategoryId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("SubCategoryId"); + + b.HasIndex("Status"); + + b.HasIndex("CategoryId", "Name") + .IsUnique(); + + b.ToTable("subcategories", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubNavItem", b => + { + b.Property("SubNavItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SubNavItemId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Href") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Icon") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("NavItemId") + .HasColumnType("integer"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.HasKey("SubNavItemId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("NavItemId"); + + b.ToTable("sub_nav_items", (string)null); + + b.HasData( + new + { + SubNavItemId = 1, + Code = "products.item", + Href = "/dashboard/products", + Label = "Item", + NavItemId = 2, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 2, + Code = "products.category", + Href = "/dashboard/products/categories", + Label = "Category", + NavItemId = 2, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 3, + Code = "products.brand", + Href = "/dashboard/products/brands", + Label = "Brand", + NavItemId = 2, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 4, + Code = "products.item-type", + Href = "/dashboard/products/item-types", + Label = "Item Type", + NavItemId = 2, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 5, + Code = "products.uom", + Href = "/dashboard/products/uoms", + Label = "UOM", + NavItemId = 2, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 6, + Code = "products.configuration", + Href = "/dashboard/products/settings", + Label = "Configuration", + NavItemId = 2, + SortOrder = 6, + Status = "Active" + }, + new + { + SubNavItemId = 29, + Code = "settings.branches", + Href = "/dashboard/settings/branches", + Label = "Branches", + NavItemId = 9, + SortOrder = 0, + Status = "Active" + }, + new + { + SubNavItemId = 7, + Code = "settings.roles", + Href = "/dashboard/settings/roles", + Label = "Roles", + NavItemId = 9, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 8, + Code = "settings.users", + Href = "/dashboard/settings/users", + Label = "Users", + NavItemId = 9, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 24, + Code = "settings.notification-config", + Href = "/dashboard/settings/notification-config", + Label = "Notification Config", + NavItemId = 9, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 40, + Code = "sales.invoices", + Href = "/dashboard/sales/invoices", + Label = "Sales", + NavItemId = 13, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 23, + Code = "sales.bundle-templates", + Href = "/dashboard/sales/bundles/templates", + Label = "Bundle Templates", + NavItemId = 13, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 41, + Code = "sales.free-issues", + Href = "/dashboard/sales/free-issues", + Label = "Free Issues", + NavItemId = 13, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 42, + Code = "sales.day-end", + Href = "/dashboard/sales/day-end", + Label = "Day End", + NavItemId = 13, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 30, + Code = "procurement.vendors", + Href = "/dashboard/vendors", + Label = "Vendors", + NavItemId = 4, + SortOrder = 0, + Status = "Active" + }, + new + { + SubNavItemId = 17, + Code = "procurement.requisitions", + Href = "/dashboard/procurement/requisitions", + Label = "Requisitions", + NavItemId = 4, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 18, + Code = "procurement.rfqs", + Href = "/dashboard/procurement/rfqs", + Label = "RFQs", + NavItemId = 4, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 19, + Code = "procurement.purchase-orders", + Href = "/dashboard/procurement/purchase-orders", + Label = "Purchase Orders", + NavItemId = 4, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 20, + Code = "procurement.purchase-returns", + Href = "/dashboard/procurement/purchase-returns", + Label = "Purchase Returns", + NavItemId = 4, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 28, + Code = "procurement.purchase-invoices", + Href = "/dashboard/procurement/purchase-invoices", + Label = "Purchase Invoices", + NavItemId = 4, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 9, + Code = "ledgers.trial-balance", + Href = "/dashboard/ledgers/trial-balance", + Label = "Trial Balance", + NavItemId = 11, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 10, + Code = "ledgers.balance-sheet", + Href = "/dashboard/ledgers/balance-sheet", + Label = "Balance Sheet", + NavItemId = 11, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 11, + Code = "ledgers.general-ledger", + Href = "/dashboard/ledgers/general-ledger", + Label = "General Ledger", + NavItemId = 11, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 12, + Code = "ledgers.profit-and-loss", + Href = "/dashboard/ledgers/profit-and-loss", + Label = "Profit & Loss", + NavItemId = 11, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 13, + Code = "ledgers.cash-flow", + Href = "/dashboard/ledgers/cash-flow", + Label = "Cash Flow", + NavItemId = 11, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 14, + Code = "ledgers.budget-vs-actual", + Href = "/dashboard/ledgers/budget-vs-actual", + Label = "Budget vs Actual", + NavItemId = 11, + SortOrder = 6, + Status = "Active" + }, + new + { + SubNavItemId = 16, + Code = "ledgers.tax-report", + Href = "/dashboard/ledgers/tax-report", + Label = "Tax Report", + NavItemId = 11, + SortOrder = 7, + Status = "Active" + }, + new + { + SubNavItemId = 15, + Code = "accounts.bank-accounts", + Href = "/dashboard/accounts/bank-accounts", + Label = "Cash / Bank Accounts", + NavItemId = 12, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 21, + Code = "accounts.cheque-books", + Href = "/dashboard/accounts/cheque-books", + Label = "Cheque Books", + NavItemId = 12, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 22, + Code = "accounts.received-cheques", + Href = "/dashboard/accounts/received-cheques", + Label = "Received Cheques", + NavItemId = 12, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 27, + Code = "production.templates", + Href = "/dashboard/production/templates", + Label = "Templates", + NavItemId = 14, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 25, + Code = "production.runs", + Href = "/dashboard/production/runs", + Label = "Runs", + NavItemId = 14, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 26, + Code = "production.produced", + Href = "/dashboard/production/produced", + Label = "Produced", + NavItemId = 14, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 31, + Code = "stock.ledger", + Href = "/dashboard/stock/ledger", + Label = "Stock Ledger", + NavItemId = 6, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 32, + Code = "stock.enquiry", + Href = "/dashboard/stock/enquiry", + Label = "Stock Enquiry", + NavItemId = 6, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 33, + Code = "stock.valuation", + Href = "/dashboard/stock/valuation", + Label = "Valuation", + NavItemId = 6, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 34, + Code = "stock.transfers", + Href = "/dashboard/stock/transfers", + Label = "Transfers", + NavItemId = 6, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 35, + Code = "stock.adjustments", + Href = "/dashboard/stock/adjustments", + Label = "Adjustments", + NavItemId = 6, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 36, + Code = "stock.counts", + Href = "/dashboard/stock/counts", + Label = "Counts", + NavItemId = 6, + SortOrder = 6, + Status = "Active" + }, + new + { + SubNavItemId = 37, + Code = "stock.reorder-alerts", + Href = "/dashboard/stock/reorder-alerts", + Label = "Reorder Alerts", + NavItemId = 6, + SortOrder = 7, + Status = "Active" + }, + new + { + SubNavItemId = 38, + Code = "stock.wastage", + Href = "/dashboard/stock/wastage", + Label = "Wastage", + NavItemId = 6, + SortOrder = 8, + Status = "Active" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicket", b => + { + b.Property("TicketId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TicketId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Subject") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.HasKey("TicketId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("Status"); + + b.ToTable("support_tickets", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicketMessage", b => + { + b.Property("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("MessageId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsFromAdmin") + .HasColumnType("boolean"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("SenderUserId") + .HasColumnType("integer"); + + b.Property("TicketId") + .HasColumnType("integer"); + + b.HasKey("MessageId"); + + b.HasIndex("TicketId", "CreatedAt"); + + b.ToTable("support_ticket_messages", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TaxSlab", b => + { + b.Property("TaxSlabId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TaxSlabId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveTo") + .HasColumnType("timestamp with time zone"); + + b.Property("LowerBound") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("Rate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("UpperBound") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.HasKey("TaxSlabId"); + + b.HasIndex("EffectiveFrom"); + + b.ToTable("hr_tax_slabs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => + { + b.Property("StageId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("StageId")); + + b.Property("EstimatedMinutes") + .HasColumnType("integer"); + + b.Property("FieldDefs") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("PosX") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PosY") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RoleLabel") + .HasMaxLength(60) + .HasColumnType("character varying(60)"); + + b.Property("TemplateId") + .HasColumnType("integer"); + + b.HasKey("StageId"); + + b.HasIndex("TemplateId"); + + b.ToTable("template_stages", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Uom", b => + { + b.Property("UomId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("UomId")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("UomId"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("uoms", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.User", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("UserId")); + + b.Property("AuthUserId") + .HasColumnType("uuid") + .HasColumnName("auth_user_id"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Email") + .HasMaxLength(320) + .HasColumnType("character varying(320)"); + + b.Property("RoleId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("UserId"); + + b.HasIndex("AuthUserId") + .IsUnique(); + + b.HasIndex("Email") + .IsUnique(); + + b.HasIndex("RoleId"); + + b.HasIndex("Username") + .IsUnique(); + + b.ToTable("users", (string)null); + + b.HasData( + new + { + UserId = 1, + DisplayName = "System", + Status = "Active", + Username = "system" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Vendor", b => + { + b.Property("VendorId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("VendorId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Currency") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(3) + .HasColumnType("character varying(3)") + .HasDefaultValue("LKR"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TaxReg") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Terms") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("VendorId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("vendors", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => + { + b.Property("QuotationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("QuotationId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("RfqId") + .HasColumnType("integer"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.HasKey("QuotationId"); + + b.HasIndex("VendorId"); + + b.HasIndex("RfqId", "VendorId") + .IsUnique(); + + b.ToTable("vendor_quotations", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotationLine", b => + { + b.Property("QuotationLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("QuotationLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LeadDays") + .HasColumnType("integer"); + + b.Property("QuotationId") + .HasColumnType("integer"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("QuotationLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("QuotationId"); + + b.ToTable("vendor_quotation_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Warehouse", b => + { + b.Property("WarehouseId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("WarehouseId")); + + b.Property("Address") + .HasColumnType("text"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Phone") + .HasColumnType("text"); + + b.HasKey("WarehouseId"); + + b.HasIndex("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("warehouses", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.WorkShift", b => + { + b.Property("WorkShiftId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("WorkShiftId")); + + b.Property("BreakMinutes") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EndTime") + .HasColumnType("interval"); + + b.Property("GraceMinutes") + .HasColumnType("integer"); + + b.Property("IsOvernight") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("OtMultiplier") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("StandardWorkingMinutes") + .HasColumnType("integer"); + + b.Property("StartTime") + .HasColumnType("interval"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WorkingDaysMask") + .HasColumnType("integer"); + + b.HasKey("WorkShiftId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_work_shifts", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceRecord", b => + { + b.HasOne("ERPCore.Domain.Entities.AttendanceUploadBatch", "AttendanceUploadBatch") + .WithMany() + .HasForeignKey("AttendanceUploadBatchId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.WorkShift", "WorkShift") + .WithMany() + .HasForeignKey("WorkShiftId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("AttendanceUploadBatch"); + + b.Navigation("Employee"); + + b.Navigation("WorkShift"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AuditLog", b => + { + b.HasOne("ERPCore.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Batch", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Bin", b => + { + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany("Bins") + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BranchConfig", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSale", b => + { + b.HasOne("ERPCore.Domain.Entities.BundleSaleTemplate", "BundleSaleTemplate") + .WithMany() + .HasForeignKey("BundleSaleTemplateId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "CashierUser") + .WithMany() + .HasForeignKey("CashierUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesDayEnd", "DayEnd") + .WithMany("BundleSales") + .HasForeignKey("DayEndId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BundleSaleTemplate"); + + b.Navigation("CashierUser"); + + b.Navigation("Customer"); + + b.Navigation("DayEnd"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleLine", b => + { + b.HasOne("ERPCore.Domain.Entities.BundleSale", "BundleSale") + .WithMany("Lines") + .HasForeignKey("BundleSaleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BundleSale"); + + b.Navigation("Item"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplateLine", b => + { + b.HasOne("ERPCore.Domain.Entities.BundleSaleTemplate", "BundleSaleTemplate") + .WithMany("Lines") + .HasForeignKey("BundleSaleTemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BundleSaleTemplate"); + + b.Navigation("Item"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Customer", b => + { + b.HasOne("ERPCore.Domain.Entities.Warehouse", "DefaultWarehouse") + .WithMany() + .HasForeignKey("DefaultWarehouseId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("DefaultWarehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Department", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Employee", "HeadEmployee") + .WithMany() + .HasForeignKey("HeadEmployeeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Department", "ParentDepartment") + .WithMany() + .HasForeignKey("ParentDepartmentId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Branch"); + + b.Navigation("HeadEmployee"); + + b.Navigation("ParentDepartment"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Employee", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Department", "Department") + .WithMany() + .HasForeignKey("DepartmentId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Designation", "Designation") + .WithMany() + .HasForeignKey("DesignationId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.EmploymentType", "EmploymentType") + .WithMany() + .HasForeignKey("EmploymentTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Employee", "ReportingManager") + .WithMany() + .HasForeignKey("ReportingManagerId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithOne() + .HasForeignKey("ERPCore.Domain.Entities.Employee", "UserId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.WorkShift", "WorkShift") + .WithMany() + .HasForeignKey("WorkShiftId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Department"); + + b.Navigation("Designation"); + + b.Navigation("EmploymentType"); + + b.Navigation("ReportingManager"); + + b.Navigation("User"); + + b.Navigation("WorkShift"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeBankDetail", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeDocument", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.HrDocumentType", "HrDocumentType") + .WithMany() + .HasForeignKey("HrDocumentTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("HrDocumentType"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeLoan", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructure", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructureLine", b => + { + b.HasOne("ERPCore.Domain.Entities.EmployeeSalaryStructure", "EmployeeSalaryStructure") + .WithMany("Lines") + .HasForeignKey("EmployeeSalaryStructureId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalaryComponent", "SalaryComponent") + .WithMany() + .HasForeignKey("SalaryComponentId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("EmployeeSalaryStructure"); + + b.Navigation("SalaryComponent"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Grn", 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.HasOne("ERPCore.Domain.Entities.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("PoId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.PurchaseInvoice", "PurchaseInvoice") + .WithMany() + .HasForeignKey("PurchaseInvoiceId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("PurchaseInvoice"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Vendor"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", "Batch") + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", "Bin") + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Grn", "Grn") + .WithMany("Lines") + .HasForeignKey("GrnId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PoLine", "PoLine") + .WithMany() + .HasForeignKey("PoLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Batch"); + + b.Navigation("Bin"); + + b.Navigation("Grn"); + + b.Navigation("Item"); + + b.Navigation("PoLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLineWarrantyNumber", b => + { + b.HasOne("ERPCore.Domain.Entities.GrnLine", "GrnLine") + .WithMany("WarrantyNumbers") + .HasForeignKey("GrnLineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GrnLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Item", b => + { + b.HasOne("ERPCore.Domain.Entities.Uom", "BaseUom") + .WithMany() + .HasForeignKey("BaseUomId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Brand", "Brand") + .WithMany() + .HasForeignKey("BrandId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Category", "Category") + .WithMany() + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "DefaultVendor") + .WithMany() + .HasForeignKey("DefaultVendorId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.SubCategory", "SubCategory") + .WithMany() + .HasForeignKey("SubCategoryId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("BaseUom"); + + b.Navigation("Brand"); + + b.Navigation("Category"); + + b.Navigation("DefaultVendor"); + + b.Navigation("SubCategory"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ItemReorder", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany("ReorderSettings") + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveBalance", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.LeaveType", "LeaveType") + .WithMany() + .HasForeignKey("LeaveTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("LeaveType"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveRequest", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.LeaveType", "LeaveType") + .WithMany() + .HasForeignKey("LeaveTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("LeaveType"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoanInstallment", b => + { + b.HasOne("ERPCore.Domain.Entities.EmployeeLoan", "EmployeeLoan") + .WithMany("Installments") + .HasForeignKey("EmployeeLoanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PayrollRun", "PayrollRun") + .WithMany() + .HasForeignKey("PayrollRunId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("EmployeeLoan"); + + b.Navigation("PayrollRun"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoginActivity", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfigModule", b => + { + b.HasOne("ERPCore.Domain.Entities.NotificationConfig", "NotificationConfig") + .WithMany("Modules") + .HasForeignKey("NotificationConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("NotificationConfig"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationRecipient", b => + { + b.HasOne("ERPCore.Domain.Entities.Notification", "Notification") + .WithMany("Recipients") + .HasForeignKey("NotificationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Notification"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PayrollRun", "PayrollRun") + .WithMany("Lines") + .HasForeignKey("PayrollRunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("PayrollRun"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLineComponent", b => + { + b.HasOne("ERPCore.Domain.Entities.PayrollLine", "PayrollLine") + .WithMany("Components") + .HasForeignKey("PayrollLineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalaryComponent", "SalaryComponent") + .WithMany() + .HasForeignKey("SalaryComponentId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("PayrollLine"); + + b.Navigation("SalaryComponent"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollRun", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Branch"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Payslip", b => + { + b.HasOne("ERPCore.Domain.Entities.PayrollLine", "PayrollLine") + .WithOne() + .HasForeignKey("ERPCore.Domain.Entities.Payslip", "PayrollLineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PayrollLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Permission", b => + { + b.HasOne("ERPCore.Domain.Entities.NavItem", "NavItem") + .WithMany() + .HasForeignKey("NavItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ERPCore.Domain.Entities.SubNavItem", "SubNavItem") + .WithMany() + .HasForeignKey("SubNavItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("NavItem"); + + b.Navigation("SubNavItem"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PoLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseOrder", "PurchaseOrder") + .WithMany("Lines") + .HasForeignKey("PoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductConfig", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b => + { + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "CancelReason") + .WithMany() + .HasForeignKey("CancelReasonCodeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Bin", "OutputBin") + .WithMany() + .HasForeignKey("OutputBinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") + .WithMany("Runs") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CancelReason"); + + b.Navigation("Creator"); + + b.Navigation("OutputBin"); + + b.Navigation("Template"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionTemplate", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoiceLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Grn", "Grn") + .WithMany() + .HasForeignKey("GrnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseInvoice", "PurchaseInvoice") + .WithMany("Lines") + .HasForeignKey("PurchaseInvoiceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Grn"); + + b.Navigation("PurchaseInvoice"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoicePayment", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseInvoice", "PurchaseInvoice") + .WithMany("Payments") + .HasForeignKey("PurchaseInvoiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("PurchaseInvoice"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Approver") + .WithMany() + .HasForeignKey("ApproverUserId"); + + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") + .WithMany() + .HasForeignKey("RequisitionId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Approver"); + + b.Navigation("Creator"); + + b.Navigation("Requisition"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturn", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ReasonCode") + .WithMany() + .HasForeignKey("ReasonCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("ReasonCode"); + + b.Navigation("Vendor"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturnLine", b => + { + b.HasOne("ERPCore.Domain.Entities.GrnLine", "GrnLine") + .WithMany() + .HasForeignKey("GrnLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseReturn", "Return") + .WithMany("Lines") + .HasForeignKey("ReturnId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GrnLine"); + + b.Navigation("Item"); + + b.Navigation("Return"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Requester") + .WithMany() + .HasForeignKey("RequestedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Requester"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RequisitionLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") + .WithMany("Lines") + .HasForeignKey("RequisitionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Requisition"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => + { + b.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") + .WithMany() + .HasForeignKey("RequisitionId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Requisition"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RfqLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Rfq", "Rfq") + .WithMany("Lines") + .HasForeignKey("RfqId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Rfq"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RolePermission", b => + { + b.HasOne("ERPCore.Domain.Entities.Permission", "Permission") + .WithMany() + .HasForeignKey("PermissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Role", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Permission"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunEdge", b => + { + b.HasOne("ERPCore.Domain.Entities.RunStage", "ChildRunStage") + .WithMany() + .HasForeignKey("ChildRunStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "ParentRunStage") + .WithMany() + .HasForeignKey("ParentRunStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ProductionRun", "Run") + .WithMany("Edges") + .HasForeignKey("RunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildRunStage"); + + b.Navigation("ParentRunStage"); + + b.Navigation("Run"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStage", b => + { + b.HasOne("ERPCore.Domain.Entities.ProductionRun", "Run") + .WithMany("Stages") + .HasForeignKey("RunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "TemplateStage") + .WithMany() + .HasForeignKey("TemplateStageId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Run"); + + b.Navigation("TemplateStage"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageEvent", b => + { + b.HasOne("ERPCore.Domain.Entities.ProductionRun", "Run") + .WithMany("Events") + .HasForeignKey("RunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "RunStage") + .WithMany("Events") + .HasForeignKey("RunStageId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Run"); + + b.Navigation("RunStage"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageInput", b => + { + b.HasOne("ERPCore.Domain.Entities.RunStageOutput", "FromRunOutput") + .WithMany() + .HasForeignKey("FromRunOutputId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "RunStage") + .WithMany("Inputs") + .HasForeignKey("RunStageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromRunOutput"); + + b.Navigation("Item"); + + b.Navigation("RunStage"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageOutput", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "RunStage") + .WithMany("Outputs") + .HasForeignKey("RunStageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ScrapReason") + .WithMany() + .HasForeignKey("ScrapReasonCodeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Uom", "Uom") + .WithMany() + .HasForeignKey("UomId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Item"); + + b.Navigation("RunStage"); + + b.Navigation("ScrapReason"); + + b.Navigation("Uom"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesDayEnd", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "CashierUser") + .WithMany() + .HasForeignKey("CashierUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "ClosedByUser") + .WithMany() + .HasForeignKey("ClosedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CashierUser"); + + b.Navigation("ClosedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoice", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatorUserId"); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("Customer"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoiceLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesInvoice", "SalesInvoice") + .WithMany("Lines") + .HasForeignKey("SalesInvoiceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SalesInvoice"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoicePayment", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesInvoice", "SalesInvoice") + .WithMany("Payments") + .HasForeignKey("SalesInvoiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("SalesInvoice"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturn", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ReasonCode") + .WithMany() + .HasForeignKey("ReasonCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("Customer"); + + b.Navigation("ReasonCode"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturnLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesReturn", "Return") + .WithMany("Lines") + .HasForeignKey("ReturnId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesInvoiceLine", "SalesInvoiceLine") + .WithMany() + .HasForeignKey("SalesInvoiceLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Item"); + + b.Navigation("Return"); + + b.Navigation("SalesInvoiceLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlip", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "CashierUser") + .WithMany() + .HasForeignKey("CashierUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesDayEnd", "DayEnd") + .WithMany("Slips") + .HasForeignKey("DayEndId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CashierUser"); + + b.Navigation("Customer"); + + b.Navigation("DayEnd"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlipLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesSlip", "SalesSlip") + .WithMany("Lines") + .HasForeignKey("SalesSlipId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SalesSlip"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Serial", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageEdge", b => + { + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "ChildStage") + .WithMany() + .HasForeignKey("ChildStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "ParentStage") + .WithMany() + .HasForeignKey("ParentStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") + .WithMany("Edges") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildStage"); + + b.Navigation("ParentStage"); + + b.Navigation("Template"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageInput", b => + { + b.HasOne("ERPCore.Domain.Entities.StageOutput", "FromOutput") + .WithMany() + .HasForeignKey("FromOutputId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "Stage") + .WithMany("Inputs") + .HasForeignKey("StageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromOutput"); + + b.Navigation("Item"); + + b.Navigation("Stage"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageOutput", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "Stage") + .WithMany("Outputs") + .HasForeignKey("StageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Uom", "Uom") + .WithMany() + .HasForeignKey("UomId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Item"); + + b.Navigation("Stage"); + + b.Navigation("Uom"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustment", 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.HasOne("ERPCore.Domain.Entities.ReasonCode", "ReasonCode") + .WithMany() + .HasForeignKey("ReasonCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("ReasonCode"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustmentLine", b => + { + b.HasOne("ERPCore.Domain.Entities.StockAdjustment", "Adjustment") + .WithMany("Lines") + .HasForeignKey("AdjustmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Batch", null) + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", null) + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Adjustment"); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCount", 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.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCountLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.StockCount", "Count") + .WithMany("Lines") + .HasForeignKey("CountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Count"); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLayer", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", "Batch") + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.GrnLine", "GrnLine") + .WithMany() + .HasForeignKey("GrnLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", "Serial") + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Batch"); + + b.Navigation("GrnLine"); + + b.Navigation("Item"); + + b.Navigation("Serial"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLedger", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", null) + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", null) + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", null) + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", null) + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransfer", 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.HasOne("ERPCore.Domain.Entities.Warehouse", "DestWarehouse") + .WithMany() + .HasForeignKey("DestWarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "SrcWarehouse") + .WithMany() + .HasForeignKey("SrcWarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("DestWarehouse"); + + b.Navigation("SrcWarehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransferLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", null) + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("DestBinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", null) + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("SrcBinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.StockTransfer", "Transfer") + .WithMany("Lines") + .HasForeignKey("TransferId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Transfer"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubCategory", b => + { + b.HasOne("ERPCore.Domain.Entities.Category", "Category") + .WithMany("SubCategories") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubNavItem", b => + { + b.HasOne("ERPCore.Domain.Entities.NavItem", "NavItem") + .WithMany("Children") + .HasForeignKey("NavItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("NavItem"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicketMessage", b => + { + b.HasOne("ERPCore.Domain.Entities.SupportTicket", "Ticket") + .WithMany("Messages") + .HasForeignKey("TicketId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ticket"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => + { + b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") + .WithMany("Stages") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Template"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.User", b => + { + b.HasOne("ERPCore.Domain.Entities.Role", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => + { + b.HasOne("ERPCore.Domain.Entities.Rfq", "Rfq") + .WithMany("Quotations") + .HasForeignKey("RfqId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Rfq"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotationLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.VendorQuotation", "Quotation") + .WithMany("Lines") + .HasForeignKey("QuotationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Quotation"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Warehouse", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSale", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplate", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Category", b => + { + b.Navigation("SubCategories"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeLoan", b => + { + b.Navigation("Installments"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructure", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Grn", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLine", b => + { + b.Navigation("WarrantyNumbers"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Item", b => + { + b.Navigation("ReorderSettings"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NavItem", b => + { + b.Navigation("Children"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Notification", b => + { + b.Navigation("Recipients"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => + { + b.Navigation("Modules"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => + { + b.Navigation("Components"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollRun", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b => + { + b.Navigation("Edges"); + + b.Navigation("Events"); + + b.Navigation("Stages"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionTemplate", b => + { + b.Navigation("Edges"); + + b.Navigation("Runs"); + + b.Navigation("Stages"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", b => + { + b.Navigation("Lines"); + + b.Navigation("Payments"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturn", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => + { + b.Navigation("Lines"); + + b.Navigation("Quotations"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStage", b => + { + b.Navigation("Events"); + + b.Navigation("Inputs"); + + b.Navigation("Outputs"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesDayEnd", b => + { + b.Navigation("BundleSales"); + + b.Navigation("Slips"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoice", b => + { + b.Navigation("Lines"); + + b.Navigation("Payments"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturn", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlip", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustment", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCount", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransfer", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicket", b => + { + b.Navigation("Messages"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => + { + b.Navigation("Inputs"); + + b.Navigation("Outputs"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Warehouse", b => + { + b.Navigation("Bins"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Backend/ERPCore/Migrations/20260916051856_AddRolePermissionActions.cs b/Backend/ERPCore/Migrations/20260916051856_AddRolePermissionActions.cs new file mode 100644 index 0000000..061b4d0 --- /dev/null +++ b/Backend/ERPCore/Migrations/20260916051856_AddRolePermissionActions.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace ERPCore.Migrations +{ + /// + public partial class AddRolePermissionActions : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Actions", + table: "role_permissions", + type: "integer", + nullable: false, + defaultValue: 31); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Actions", + table: "role_permissions"); + } + } +} diff --git a/Backend/ERPCore/Migrations/20260916071017_AddSalesDayEndPaidBalance.Designer.cs b/Backend/ERPCore/Migrations/20260916071017_AddSalesDayEndPaidBalance.Designer.cs new file mode 100644 index 0000000..16a7aee --- /dev/null +++ b/Backend/ERPCore/Migrations/20260916071017_AddSalesDayEndPaidBalance.Designer.cs @@ -0,0 +1,8456 @@ +// +using System; +using ERPCore.Infra.Persistence; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace ERPCore.Migrations +{ + [DbContext(typeof(ErpDbContext))] + [Migration("20260916071017_AddSalesDayEndPaidBalance")] + partial class AddSalesDayEndPaidBalance + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.9") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceRecord", b => + { + b.Property("AttendanceRecordId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AttendanceRecordId")); + + b.Property("AttendanceDate") + .HasColumnType("timestamp with time zone"); + + b.Property("AttendanceStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("AttendanceUploadBatchId") + .HasColumnType("integer"); + + b.Property("CheckIn") + .HasColumnType("interval"); + + b.Property("CheckOut") + .HasColumnType("interval"); + + b.Property("DuplicateOfAttendanceRecordId") + .HasColumnType("integer"); + + b.Property("EarlyLeaveMinutes") + .HasColumnType("integer"); + + b.Property("EditedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EditedBy") + .HasColumnType("integer"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("IsManualOverride") + .HasColumnType("boolean"); + + b.Property("LateMinutes") + .HasColumnType("integer"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("OvertimeMinutes") + .HasColumnType("integer"); + + b.Property("RowValidationStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("WorkShiftId") + .HasColumnType("integer"); + + b.Property("WorkingMinutes") + .HasColumnType("integer"); + + b.HasKey("AttendanceRecordId"); + + b.HasIndex("AttendanceUploadBatchId"); + + b.HasIndex("WorkShiftId"); + + b.HasIndex("EmployeeId", "AttendanceDate"); + + b.ToTable("hr_attendance_records", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceUploadBatch", b => + { + b.Property("AttendanceUploadBatchId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AttendanceUploadBatchId")); + + b.Property("ConfirmedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ConfirmedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("OriginalFileName") + .HasMaxLength(260) + .HasColumnType("character varying(260)"); + + b.Property("PeriodEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("PeriodStart") + .HasColumnType("timestamp with time zone"); + + b.Property("RowCountDuplicate") + .HasColumnType("integer"); + + b.Property("RowCountError") + .HasColumnType("integer"); + + b.Property("RowCountTotal") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SourceType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UploadedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UploadedBy") + .HasColumnType("integer"); + + b.HasKey("AttendanceUploadBatchId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("PeriodStart", "PeriodEnd"); + + b.ToTable("hr_attendance_upload_batches", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AuditLog", b => + { + b.Property("AuditId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AuditId")); + + b.Property("Action") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("ChangeSet") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EntityId") + .HasColumnType("integer"); + + b.Property("EntityType") + .IsRequired() + .HasMaxLength(80) + .HasColumnType("character varying(80)"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("AuditId"); + + b.HasIndex("CreatedAt"); + + b.HasIndex("UserId"); + + b.HasIndex("EntityType", "EntityId"); + + b.ToTable("audit_logs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Batch", b => + { + b.Property("BatchId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BatchId")); + + b.Property("BatchNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ExpiryDate") + .HasColumnType("date"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.HasKey("BatchId"); + + b.HasIndex("ItemId", "BatchNo") + .IsUnique(); + + b.ToTable("batches", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Bin", b => + { + b.Property("BinId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BinId")); + + b.Property("BinType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BinId"); + + b.HasIndex("WarehouseId", "Code") + .IsUnique(); + + b.ToTable("bins", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Branch", b => + { + b.Property("BranchId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BranchId")); + + b.Property("Address") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("PhoneNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_branches", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BranchConfig", b => + { + b.Property("ConfigId") + .HasColumnType("integer"); + + b.Property("BranchingEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.Property("WarehouseBranchingEnabled") + .HasColumnType("boolean"); + + b.HasKey("ConfigId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("branch_config", null, t => + { + t.HasCheckConstraint("ck_branch_config_singleton", "\"ConfigId\" = 1"); + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Brand", b => + { + b.Property("BrandId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BrandId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("BrandId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("brands", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSale", b => + { + b.Property("BundleSaleId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleId")); + + b.Property("BundleCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BundleDate") + .HasColumnType("timestamp with time zone"); + + b.Property("BundleName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("BundleNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BundlePrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BundleSaleTemplateId") + .HasColumnType("integer"); + + b.Property("CashierUserId") + .HasColumnType("integer"); + + b.Property("ComponentSubtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("CustomerSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DayEndId") + .HasColumnType("integer"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("MarginAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BundleSaleId"); + + b.HasIndex("BundleNo") + .IsUnique(); + + b.HasIndex("BundleSaleTemplateId"); + + b.HasIndex("CashierUserId"); + + b.HasIndex("CustomerId"); + + b.HasIndex("DayEndId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("bundle_sales", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleLine", b => + { + b.Property("BundleSaleLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleLineId")); + + b.Property("BundleSaleId") + .HasColumnType("integer"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("IncludeInBundle") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("IsComponent") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ParentLineId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BundleSaleLineId"); + + b.HasIndex("BundleSaleId"); + + b.HasIndex("ItemId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("bundle_sale_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplate", b => + { + b.Property("BundleSaleTemplateId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleTemplateId")); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TemplateCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("TemplateName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("BundleSaleTemplateId"); + + b.HasIndex("TemplateCode") + .IsUnique(); + + b.ToTable("bundle_sale_templates", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplateLine", b => + { + b.Property("BundleSaleTemplateLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleTemplateLineId")); + + b.Property("BundleSaleTemplateId") + .HasColumnType("integer"); + + b.Property("IncludeInBundle") + .HasColumnType("boolean"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SortOrder") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BundleSaleTemplateLineId"); + + b.HasIndex("BundleSaleTemplateId"); + + b.HasIndex("ItemId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("bundle_sale_template_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Category", b => + { + b.Property("CategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CategoryId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("CategoryId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("categories", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Customer", b => + { + b.Property("CustomerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CustomerId")); + + b.Property("AddressLine1") + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("AddressLine2") + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("City") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Country") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreditDays") + .HasColumnType("integer"); + + b.Property("CreditLimit") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CustomerCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CustomerType") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("B2C"); + + b.Property("DefaultWarehouseId") + .HasColumnType("integer"); + + b.Property("DisplayName") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Email") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Phone") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TaxRegistrationNo") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("CustomerId"); + + b.HasIndex("CustomerCode") + .IsUnique(); + + b.HasIndex("CustomerType"); + + b.HasIndex("DefaultWarehouseId"); + + b.HasIndex("Status"); + + b.ToTable("customers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Department", b => + { + b.Property("DepartmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("DepartmentId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("HeadEmployeeId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("ParentDepartmentId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("DepartmentId"); + + b.HasIndex("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("HeadEmployeeId"); + + b.HasIndex("ParentDepartmentId"); + + b.HasIndex("Status"); + + b.ToTable("hr_departments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Designation", b => + { + b.Property("DesignationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("DesignationId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("DesignationId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_designations", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Employee", b => + { + b.Property("EmployeeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeId")); + + b.Property("AddressLine1") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("AddressLine2") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("City") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ConfirmationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Country") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DateOfBirth") + .HasColumnType("timestamp with time zone"); + + b.Property("DepartmentId") + .HasColumnType("integer"); + + b.Property("DesignationId") + .HasColumnType("integer"); + + b.Property("Email") + .HasMaxLength(320) + .HasColumnType("character varying(320)"); + + b.Property("EmergencyContactName") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("EmergencyContactPhone") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmergencyContactRelationship") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("EmployeeCode") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmploymentTypeId") + .HasColumnType("integer"); + + b.Property("EpfNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EtfNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Gender") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("HireDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LastWorkingDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Nationality") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Nic") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PersonalMobile") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PostalCode") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ProfilePhotoPath") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("ReportingManagerId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TaxIdentificationNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.Property("WorkShiftId") + .HasColumnType("integer"); + + b.HasKey("EmployeeId"); + + b.HasIndex("BranchId"); + + b.HasIndex("DepartmentId"); + + b.HasIndex("DesignationId"); + + b.HasIndex("Email"); + + b.HasIndex("EmployeeCode") + .IsUnique(); + + b.HasIndex("EmploymentTypeId"); + + b.HasIndex("ReportingManagerId"); + + b.HasIndex("Status"); + + b.HasIndex("UserId") + .IsUnique(); + + b.HasIndex("WorkShiftId"); + + b.ToTable("hr_employees", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeBankDetail", b => + { + b.Property("EmployeeBankDetailId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeBankDetailId")); + + b.Property("AccountHolderName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("AccountNumber") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BankName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("BranchName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("IsPrimary") + .HasColumnType("boolean"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("SwiftCode") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("EmployeeBankDetailId"); + + b.HasIndex("EmployeeId"); + + b.ToTable("hr_employee_bank_details", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeDocument", b => + { + b.Property("EmployeeDocumentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeDocumentId")); + + b.Property("ContentType") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("ExpiryDate") + .HasColumnType("timestamp with time zone"); + + b.Property("HrDocumentTypeId") + .HasColumnType("integer"); + + b.Property("IssueDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("OriginalFileName") + .IsRequired() + .HasMaxLength(260) + .HasColumnType("character varying(260)"); + + b.Property("RelativePath") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SizeBytes") + .HasColumnType("bigint"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("StoredFileName") + .IsRequired() + .HasMaxLength(260) + .HasColumnType("character varying(260)"); + + b.Property("UploadedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UploadedBy") + .HasColumnType("integer"); + + b.Property("VerifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VerifiedBy") + .HasColumnType("integer"); + + b.HasKey("EmployeeDocumentId"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("ExpiryDate"); + + b.HasIndex("HrDocumentTypeId"); + + b.ToTable("hr_employee_documents", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeLoan", b => + { + b.Property("EmployeeLoanId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeLoanId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("InstallmentAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("InterestRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("LoanKind") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("NumberOfInstallments") + .HasColumnType("integer"); + + b.Property("OutstandingBalance") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("PrincipalAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("StartMonth") + .HasColumnType("integer"); + + b.Property("StartYear") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("EmployeeLoanId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("EmployeeId"); + + b.HasIndex("Status"); + + b.ToTable("hr_employee_loans", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructure", b => + { + b.Property("EmployeeSalaryStructureId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeSalaryStructureId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("BasicSalary") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("Currency") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("character varying(3)"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveTo") + .HasColumnType("timestamp with time zone"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("EmployeeSalaryStructureId"); + + b.HasIndex("EmployeeId", "EffectiveTo"); + + b.ToTable("hr_employee_salary_structures", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructureLine", b => + { + b.Property("EmployeeSalaryStructureLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeSalaryStructureLineId")); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("EmployeeSalaryStructureId") + .HasColumnType("integer"); + + b.Property("SalaryComponentId") + .HasColumnType("integer"); + + b.HasKey("EmployeeSalaryStructureLineId"); + + b.HasIndex("EmployeeSalaryStructureId"); + + b.HasIndex("SalaryComponentId"); + + b.ToTable("hr_employee_salary_structure_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmploymentType", b => + { + b.Property("EmploymentTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmploymentTypeId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("EmploymentTypeId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_employment_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Grn", b => + { + b.Property("GrnId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("GrnId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PoId") + .HasColumnType("integer"); + + b.Property("PostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PurchaseInvoiceId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("GrnId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("PoId"); + + b.HasIndex("PurchaseInvoiceId"); + + b.HasIndex("Status"); + + b.HasIndex("VendorId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("grns", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLine", b => + { + b.Property("GrnLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("GrnLineId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("DiscountPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("GrnId") + .HasColumnType("integer"); + + b.Property("HoldStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("NetUnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("PoLineId") + .HasColumnType("integer"); + + b.Property("PoUnitPrice") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReceivedValue") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("VatAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("VatPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.HasKey("GrnLineId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("GrnId"); + + b.HasIndex("ItemId"); + + b.HasIndex("PoLineId"); + + b.ToTable("grn_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLineWarrantyNumber", b => + { + b.Property("GrnLineWarrantyNumberId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("GrnLineWarrantyNumberId")); + + b.Property("GrnLineId") + .HasColumnType("integer"); + + b.Property("WarrantyNo") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("WarrantyPeriodMonths") + .HasColumnType("integer"); + + b.HasKey("GrnLineWarrantyNumberId"); + + b.HasIndex("GrnLineId", "WarrantyNo") + .IsUnique(); + + b.ToTable("grn_line_warranty_numbers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.HrDocumentType", b => + { + b.Property("HrDocumentTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("HrDocumentTypeId")); + + b.Property("Category") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpiryTracked") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RequiredAtOnboarding") + .HasColumnType("boolean"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("HrDocumentTypeId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_document_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Item", b => + { + b.Property("ItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ItemId")); + + b.Property("BaseUomId") + .HasColumnType("integer"); + + b.Property("BrandId") + .HasColumnType("integer"); + + b.Property("CategoryId") + .HasColumnType("integer"); + + b.Property("ContentBaseQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ContentBaseUnit") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ContentQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ContentUnit") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DefaultVendorId") + .HasColumnType("integer"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SellingFlatPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SellingMaxPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SellingMinPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Sku") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("StockNature") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("SubCategoryId") + .HasColumnType("integer"); + + b.Property("TaxClass") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("TrackingMode") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Warranty") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("NonWarranty"); + + b.Property("WarrantyPeriodMonths") + .HasColumnType("integer"); + + b.HasKey("ItemId"); + + b.HasIndex("BaseUomId"); + + b.HasIndex("BrandId"); + + b.HasIndex("CategoryId"); + + b.HasIndex("DefaultVendorId"); + + b.HasIndex("Sku") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("SubCategoryId"); + + b.ToTable("items", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ItemReorder", b => + { + b.Property("ReorderId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReorderId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("ReorderPoint") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReorderQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("ReorderId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("ItemId", "WarehouseId") + .IsUnique(); + + b.ToTable("item_reorders", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ItemType", b => + { + b.Property("ItemTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ItemTypeId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsMeasurable") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("ItemTypeId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("item_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.JournalEntryStub", b => + { + b.Property("JournalId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("JournalId")); + + b.Property("Amount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CreditAccount") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("DebitAccount") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("SourceDocId") + .HasColumnType("integer"); + + b.Property("SourceDocType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.HasKey("JournalId"); + + b.HasIndex("SourceDocType", "SourceDocId"); + + b.ToTable("journal_entry_stubs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveBalance", b => + { + b.Property("LeaveBalanceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LeaveBalanceId")); + + b.Property("AdjustmentDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("CarriedForwardDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("EntitledDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("LeaveTypeId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("TakenDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Year") + .HasColumnType("integer"); + + b.HasKey("LeaveBalanceId"); + + b.HasIndex("LeaveTypeId"); + + b.HasIndex("EmployeeId", "LeaveTypeId", "Year") + .IsUnique(); + + b.ToTable("hr_leave_balances", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveRequest", b => + { + b.Property("LeaveRequestId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LeaveRequestId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DaysCount") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("EndDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LeaveTypeId") + .HasColumnType("integer"); + + b.Property("Reason") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("RejectionReason") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("StartDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("LeaveRequestId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("EmployeeId"); + + b.HasIndex("LeaveTypeId"); + + b.HasIndex("Status"); + + b.HasIndex("StartDate", "EndDate"); + + b.ToTable("hr_leave_requests", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveType", b => + { + b.Property("LeaveTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LeaveTypeId")); + + b.Property("AccrualPerYear") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("CarryForwardAllowed") + .HasColumnType("boolean"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CountsAsNoPay") + .HasColumnType("boolean"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsPaid") + .HasColumnType("boolean"); + + b.Property("MaxCarryForwardDays") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RequiresApproval") + .HasColumnType("boolean"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("LeaveTypeId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_leave_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoanInstallment", b => + { + b.Property("LoanInstallmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LoanInstallmentId")); + + b.Property("DueMonth") + .HasColumnType("integer"); + + b.Property("DueYear") + .HasColumnType("integer"); + + b.Property("EmployeeLoanId") + .HasColumnType("integer"); + + b.Property("InstallmentNumber") + .HasColumnType("integer"); + + b.Property("PaidAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("PayrollRunId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("ScheduledAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("LoanInstallmentId"); + + b.HasIndex("EmployeeLoanId"); + + b.HasIndex("PayrollRunId"); + + b.HasIndex("DueYear", "DueMonth"); + + b.ToTable("hr_loan_installments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoginActivity", b => + { + b.Property("LoginActivityId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LoginActivityId")); + + b.Property("DeviceLabel") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("IpAddress") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("LoginAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserAgent") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("LoginActivityId"); + + b.HasIndex("UserId", "LoginAt"); + + b.ToTable("login_activities", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NavItem", b => + { + b.Property("NavItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NavItemId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Href") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Icon") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.HasKey("NavItemId"); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("nav_items", (string)null); + + b.HasData( + new + { + NavItemId = 1, + Code = "dashboard", + Href = "/dashboard", + Label = "Dashboard", + SortOrder = 1, + Status = "Active" + }, + new + { + NavItemId = 2, + Code = "products", + Href = "/dashboard/products", + Label = "Products", + SortOrder = 2, + Status = "Active" + }, + new + { + NavItemId = 4, + Code = "procurement", + Href = "/dashboard/procurement", + Label = "Procurement", + SortOrder = 4, + Status = "Active" + }, + new + { + NavItemId = 5, + Code = "receiving", + Href = "/dashboard/receiving/grn", + Label = "Receiving", + SortOrder = 5, + Status = "Active" + }, + new + { + NavItemId = 6, + Code = "stock", + Href = "/dashboard/stock", + Label = "Stock", + SortOrder = 6, + Status = "Active" + }, + new + { + NavItemId = 7, + Code = "warehouses", + Href = "/dashboard/warehouse", + Label = "Warehouses", + SortOrder = 7, + Status = "Active" + }, + new + { + NavItemId = 8, + Code = "orders", + Href = "/dashboard/orders", + Label = "Orders", + SortOrder = 8, + Status = "Active" + }, + new + { + NavItemId = 9, + Code = "settings", + Href = "/dashboard/settings", + Label = "Settings", + SortOrder = 9, + Status = "Active" + }, + new + { + NavItemId = 10, + Code = "help", + Href = "/dashboard/help", + Label = "Help", + SortOrder = 10, + Status = "Active" + }, + new + { + NavItemId = 11, + Code = "ledgers", + Href = "/dashboard/ledgers", + Label = "Ledgers", + SortOrder = 11, + Status = "Active" + }, + new + { + NavItemId = 12, + Code = "accounts", + Href = "/dashboard/accounts", + Label = "Accounts", + SortOrder = 12, + Status = "Active" + }, + new + { + NavItemId = 13, + Code = "sales", + Href = "/dashboard/sales", + Label = "Sales", + SortOrder = 13, + Status = "Active" + }, + new + { + NavItemId = 14, + Code = "production", + Href = "/dashboard/production", + Label = "Production", + SortOrder = 14, + Status = "Active" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Notification", b => + { + b.Property("NotificationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NotificationId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("ModuleKey") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("RelatedEntityId") + .HasColumnType("integer"); + + b.Property("RelatedEntityType") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.HasKey("NotificationId"); + + b.HasIndex("CreatedAt"); + + b.ToTable("notifications", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => + { + b.Property("NotificationConfigId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.HasKey("NotificationConfigId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("notification_config", null, t => + { + t.HasCheckConstraint("ck_notification_config_singleton", "\"NotificationConfigId\" = 1"); + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfigModule", b => + { + b.Property("NotificationConfigModuleId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NotificationConfigModuleId")); + + b.Property("EmailEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("InAppEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("ModuleKey") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("NotificationConfigId") + .HasColumnType("integer"); + + b.Property("SmsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.HasKey("NotificationConfigModuleId"); + + b.HasIndex("ModuleKey") + .IsUnique(); + + b.HasIndex("NotificationConfigId"); + + b.ToTable("notification_config_modules", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationRecipient", b => + { + b.Property("NotificationRecipientId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NotificationRecipientId")); + + b.Property("IsRead") + .HasColumnType("boolean"); + + b.Property("NotificationId") + .HasColumnType("integer"); + + b.Property("ReadAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("NotificationRecipientId"); + + b.HasIndex("NotificationId"); + + b.HasIndex("UserId", "IsRead", "NotificationId"); + + b.ToTable("notification_recipients", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NumberSequence", b => + { + b.Property("SequenceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SequenceId")); + + b.Property("DocType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("doc_type"); + + b.Property("LastNumber") + .HasColumnType("integer") + .HasColumnName("last_number"); + + b.Property("Year") + .HasColumnType("integer") + .HasColumnName("year"); + + b.HasKey("SequenceId"); + + b.HasIndex("DocType", "Year") + .IsUnique(); + + b.ToTable("number_sequences", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => + { + b.Property("PayrollLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollLineId")); + + b.Property("AbsentDays") + .HasColumnType("integer"); + + b.Property("BasicSalary") + .HasColumnType("numeric(18,2)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("EpfEmployeeAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("EpfEmployerAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("EtfEmployerAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("GrossSalary") + .HasColumnType("numeric(18,2)"); + + b.Property("LateDeductionAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("LateMinutesTotal") + .HasColumnType("integer"); + + b.Property("LeaveDays") + .HasColumnType("integer"); + + b.Property("LoanDeductionAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("NetSalary") + .HasColumnType("numeric(18,2)"); + + b.Property("NoPayAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("OtMinutesTotal") + .HasColumnType("integer"); + + b.Property("OtherDeductionsAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("OvertimeAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("PayrollRunId") + .HasColumnType("integer"); + + b.Property("PresentDays") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("TaxAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("TotalAllowances") + .HasColumnType("numeric(18,2)"); + + b.Property("WorkingDays") + .HasColumnType("integer"); + + b.HasKey("PayrollLineId"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("PayrollRunId", "EmployeeId") + .IsUnique(); + + b.ToTable("hr_payroll_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLineComponent", b => + { + b.Property("PayrollLineComponentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollLineComponentId")); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("ComponentCategory") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("PayrollLineId") + .HasColumnType("integer"); + + b.Property("SalaryComponentId") + .HasColumnType("integer"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.HasKey("PayrollLineComponentId"); + + b.HasIndex("PayrollLineId"); + + b.HasIndex("SalaryComponentId"); + + b.ToTable("hr_payroll_line_components", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollRun", b => + { + b.Property("PayrollRunId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollRunId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GeneratedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GeneratedBy") + .HasColumnType("integer"); + + b.Property("LockedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("LockedBy") + .HasColumnType("integer"); + + b.Property("PeriodMonth") + .HasColumnType("integer"); + + b.Property("PeriodYear") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UnlockReason") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("UnlockedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UnlockedBy") + .HasColumnType("integer"); + + b.HasKey("PayrollRunId"); + + b.HasIndex("BranchId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("PeriodYear", "PeriodMonth", "BranchId"); + + b.ToTable("hr_payroll_runs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollStatutorySetting", b => + { + b.Property("PayrollStatutorySettingId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollStatutorySettingId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveTo") + .HasColumnType("timestamp with time zone"); + + b.Property("EpfEmployeeRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("EpfEmployerRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("EtfEmployerRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("OtMultiplierDefault") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.HasKey("PayrollStatutorySettingId"); + + b.HasIndex("EffectiveFrom"); + + b.ToTable("hr_payroll_statutory_settings", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Payslip", b => + { + b.Property("PayslipId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayslipId")); + + b.Property("GeneratedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PayrollLineId") + .HasColumnType("integer"); + + b.Property("ReleasedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReleasedBy") + .HasColumnType("integer"); + + b.HasKey("PayslipId"); + + b.HasIndex("PayrollLineId") + .IsUnique(); + + b.ToTable("hr_payslips", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Permission", b => + { + b.Property("PermissionId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PermissionId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(80) + .HasColumnType("character varying(80)"); + + b.Property("NavItemId") + .HasColumnType("integer"); + + b.Property("SubNavItemId") + .HasColumnType("integer"); + + b.HasKey("PermissionId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("NavItemId"); + + b.HasIndex("SubNavItemId"); + + b.ToTable("permissions", (string)null); + + b.HasData( + new + { + PermissionId = 1, + Code = "NAV:dashboard", + NavItemId = 1 + }, + new + { + PermissionId = 2, + Code = "NAV:products", + NavItemId = 2 + }, + new + { + PermissionId = 3, + Code = "NAV:procurement.vendors", + SubNavItemId = 30 + }, + new + { + PermissionId = 4, + Code = "NAV:procurement", + NavItemId = 4 + }, + new + { + PermissionId = 5, + Code = "NAV:receiving", + NavItemId = 5 + }, + new + { + PermissionId = 6, + Code = "NAV:stock", + NavItemId = 6 + }, + new + { + PermissionId = 7, + Code = "NAV:warehouses", + NavItemId = 7 + }, + new + { + PermissionId = 8, + Code = "NAV:orders", + NavItemId = 8 + }, + new + { + PermissionId = 9, + Code = "NAV:settings", + NavItemId = 9 + }, + new + { + PermissionId = 10, + Code = "NAV:help", + NavItemId = 10 + }, + new + { + PermissionId = 11, + Code = "NAV:products.item", + SubNavItemId = 1 + }, + new + { + PermissionId = 12, + Code = "NAV:products.category", + SubNavItemId = 2 + }, + new + { + PermissionId = 13, + Code = "NAV:products.brand", + SubNavItemId = 3 + }, + new + { + PermissionId = 14, + Code = "NAV:products.item-type", + SubNavItemId = 4 + }, + new + { + PermissionId = 15, + Code = "NAV:products.uom", + SubNavItemId = 5 + }, + new + { + PermissionId = 16, + Code = "NAV:products.configuration", + SubNavItemId = 6 + }, + new + { + PermissionId = 17, + Code = "NAV:settings.roles", + SubNavItemId = 7 + }, + new + { + PermissionId = 18, + Code = "NAV:settings.users", + SubNavItemId = 8 + }, + new + { + PermissionId = 28, + Code = "NAV:procurement.requisitions", + SubNavItemId = 17 + }, + new + { + PermissionId = 29, + Code = "NAV:procurement.rfqs", + SubNavItemId = 18 + }, + new + { + PermissionId = 30, + Code = "NAV:procurement.purchase-orders", + SubNavItemId = 19 + }, + new + { + PermissionId = 31, + Code = "NAV:procurement.purchase-returns", + SubNavItemId = 20 + }, + new + { + PermissionId = 19, + Code = "NAV:ledgers", + NavItemId = 11 + }, + new + { + PermissionId = 20, + Code = "NAV:ledgers.trial-balance", + SubNavItemId = 9 + }, + new + { + PermissionId = 21, + Code = "NAV:ledgers.balance-sheet", + SubNavItemId = 10 + }, + new + { + PermissionId = 22, + Code = "NAV:ledgers.general-ledger", + SubNavItemId = 11 + }, + new + { + PermissionId = 23, + Code = "NAV:ledgers.profit-and-loss", + SubNavItemId = 12 + }, + new + { + PermissionId = 24, + Code = "NAV:ledgers.cash-flow", + SubNavItemId = 13 + }, + new + { + PermissionId = 25, + Code = "NAV:ledgers.budget-vs-actual", + SubNavItemId = 14 + }, + new + { + PermissionId = 27, + Code = "NAV:ledgers.tax-report", + SubNavItemId = 16 + }, + new + { + PermissionId = 26, + Code = "NAV:accounts.bank-accounts", + SubNavItemId = 15 + }, + new + { + PermissionId = 32, + Code = "NAV:accounts", + NavItemId = 12 + }, + new + { + PermissionId = 33, + Code = "NAV:accounts.cheque-books", + SubNavItemId = 21 + }, + new + { + PermissionId = 34, + Code = "NAV:accounts.received-cheques", + SubNavItemId = 22 + }, + new + { + PermissionId = 35, + Code = "NAV:production", + NavItemId = 14 + }, + new + { + PermissionId = 36, + Code = "NAV:production.templates", + SubNavItemId = 27 + }, + new + { + PermissionId = 37, + Code = "NAV:production.runs", + SubNavItemId = 25 + }, + new + { + PermissionId = 38, + Code = "NAV:production.produced", + SubNavItemId = 26 + }, + new + { + PermissionId = 39, + Code = "NAV:procurement.purchase-invoices", + SubNavItemId = 28 + }, + new + { + PermissionId = 40, + Code = "NAV:settings.branches", + SubNavItemId = 29 + }, + new + { + PermissionId = 41, + Code = "NAV:stock.ledger", + SubNavItemId = 31 + }, + new + { + PermissionId = 42, + Code = "NAV:stock.enquiry", + SubNavItemId = 32 + }, + new + { + PermissionId = 43, + Code = "NAV:stock.valuation", + SubNavItemId = 33 + }, + new + { + PermissionId = 44, + Code = "NAV:stock.transfers", + SubNavItemId = 34 + }, + new + { + PermissionId = 45, + Code = "NAV:stock.adjustments", + SubNavItemId = 35 + }, + new + { + PermissionId = 46, + Code = "NAV:stock.counts", + SubNavItemId = 36 + }, + new + { + PermissionId = 47, + Code = "NAV:stock.reorder-alerts", + SubNavItemId = 37 + }, + new + { + PermissionId = 48, + Code = "NAV:stock.wastage", + SubNavItemId = 38 + }, + new + { + PermissionId = 49, + Code = "NAV:sales.bundle-templates", + SubNavItemId = 23 + }, + new + { + PermissionId = 50, + Code = "NAV:sales.invoices", + SubNavItemId = 40 + }, + new + { + PermissionId = 51, + Code = "NAV:sales.free-issues", + SubNavItemId = 41 + }, + new + { + PermissionId = 52, + Code = "NAV:sales.day-end", + SubNavItemId = 42 + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PoLine", b => + { + b.Property("PoLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PoLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("PoId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyReceived") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Tax") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("PoLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("PoId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("po_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductConfig", b => + { + b.Property("ConfigId") + .HasColumnType("integer"); + + b.Property("BatchListsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("BrandsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("ItemTypesEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SellingPricesEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("SerialNumbersEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("SubcategoriesEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.Property("WarrantyPeriodsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.HasKey("ConfigId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("product_config", null, t => + { + t.HasCheckConstraint("ck_product_config_singleton", "\"ConfigId\" = 1"); + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b => + { + b.Property("RunId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunId")); + + b.Property("CancelReasonCodeId") + .HasColumnType("integer"); + + b.Property("CompletedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("OutputBinId") + .HasColumnType("integer"); + + b.Property("ReworkCount") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("ScaleFactor") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("TargetQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TemplateId") + .HasColumnType("integer"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("RunId"); + + b.HasIndex("CancelReasonCodeId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("OutputBinId"); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("TemplateId", "Status"); + + b.ToTable("production_runs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionTemplate", b => + { + b.Property("TemplateId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TemplateId")); + + b.Property("Annotations") + .HasColumnType("jsonb"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("TemplateId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("CreatedBy"); + + b.HasIndex("Status"); + + b.ToTable("production_templates", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", b => + { + b.Property("PurchaseInvoiceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PurchaseInvoiceId")); + + b.Property("BalanceAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VatTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.Property("VendorInvoiceDate") + .HasColumnType("timestamp with time zone"); + + b.Property("VendorInvoiceNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("VendorSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("VendorSnapshotTaxNo") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("PurchaseInvoiceId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("VendorId"); + + b.HasIndex("VendorId", "VendorInvoiceNo"); + + b.ToTable("purchase_invoices", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoiceLine", b => + { + b.Property("PurchaseInvoiceLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PurchaseInvoiceLineId")); + + b.Property("GrnId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PurchaseInvoiceId") + .HasColumnType("integer"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("VatTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("PurchaseInvoiceLineId"); + + b.HasIndex("GrnId") + .IsUnique(); + + b.HasIndex("PurchaseInvoiceId"); + + b.ToTable("purchase_invoice_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoicePayment", b => + { + b.Property("PurchaseInvoicePaymentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PurchaseInvoicePaymentId")); + + b.Property("Amount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BankAccountName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("GlBankAccountId") + .HasColumnType("bigint"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PaymentDate") + .HasColumnType("timestamp with time zone"); + + b.Property("PurchaseInvoiceId") + .HasColumnType("integer"); + + b.Property("Reference") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("PurchaseInvoicePaymentId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("PurchaseInvoiceId"); + + b.ToTable("purchase_invoice_payments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => + { + b.Property("PoId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PoId")); + + b.Property("ApprovalRequired") + .HasColumnType("boolean"); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("ApproverUserId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RequisitionId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.HasKey("PoId"); + + b.HasIndex("ApproverUserId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("RequisitionId"); + + b.HasIndex("Status"); + + b.HasIndex("VendorId"); + + b.ToTable("purchase_orders", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturn", b => + { + b.Property("ReturnId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReasonCodeId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("ReturnId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("ReasonCodeId"); + + b.HasIndex("VendorId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("purchase_returns", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturnLine", b => + { + b.Property("ReturnLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnLineId")); + + b.Property("GrnLineId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReturnId") + .HasColumnType("integer"); + + b.HasKey("ReturnLineId"); + + b.HasIndex("GrnLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("ReturnId"); + + b.ToTable("purchase_return_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ReasonCode", b => + { + b.Property("ReasonCodeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReasonCodeId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Context") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.HasKey("ReasonCodeId"); + + b.HasIndex("Context", "Code") + .IsUnique(); + + b.ToTable("reason_codes", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => + { + b.Property("RequisitionId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RequisitionId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RequestedBy") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("RequisitionId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("RequestedBy"); + + b.HasIndex("Status"); + + b.ToTable("requisitions", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RequisitionLine", b => + { + b.Property("ReqLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReqLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RequiredBy") + .HasColumnType("date"); + + b.Property("RequisitionId") + .HasColumnType("integer"); + + b.HasKey("ReqLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RequisitionId"); + + b.ToTable("requisition_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => + { + b.Property("RfqId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RfqId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RequisitionId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("RfqId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("RequisitionId"); + + b.ToTable("rfqs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RfqLine", b => + { + b.Property("RfqLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RfqLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RfqId") + .HasColumnType("integer"); + + b.HasKey("RfqLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RfqId"); + + b.ToTable("rfq_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Role", b => + { + b.Property("RoleId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RoleId")); + + b.Property("AuthRoleId") + .HasColumnType("uuid") + .HasColumnName("auth_role_id"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsSystemRole") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("RoleId"); + + b.HasIndex("AuthRoleId") + .IsUnique(); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("roles", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RolePermission", b => + { + b.Property("RoleId") + .HasColumnType("integer"); + + b.Property("PermissionId") + .HasColumnType("integer"); + + b.Property("Actions") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(31); + + b.HasKey("RoleId", "PermissionId"); + + b.HasIndex("PermissionId"); + + b.ToTable("role_permissions", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunEdge", b => + { + b.Property("RunEdgeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunEdgeId")); + + b.Property("ChildRunStageId") + .HasColumnType("integer"); + + b.Property("ParentRunStageId") + .HasColumnType("integer"); + + b.Property("RunId") + .HasColumnType("integer"); + + b.HasKey("RunEdgeId"); + + b.HasIndex("ChildRunStageId"); + + b.HasIndex("RunId"); + + b.HasIndex("ParentRunStageId", "ChildRunStageId") + .IsUnique(); + + b.ToTable("run_edges", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStage", b => + { + b.Property("RunStageId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunStageId")); + + b.Property("ActualEndAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ActualStartAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EstimatedMinutes") + .HasColumnType("integer"); + + b.Property("FieldDefs") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("FieldValues") + .HasColumnType("jsonb"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("PosX") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PosY") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RoleLabel") + .HasMaxLength(60) + .HasColumnType("character varying(60)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("RunId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("TemplateStageId") + .HasColumnType("integer"); + + b.HasKey("RunStageId"); + + b.HasIndex("TemplateStageId"); + + b.HasIndex("RunId", "Status"); + + b.ToTable("run_stages", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageEvent", b => + { + b.Property("EventId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EventId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Note") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Payload") + .HasColumnType("jsonb"); + + b.Property("RunId") + .HasColumnType("integer"); + + b.Property("RunStageId") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("EventId"); + + b.HasIndex("RunStageId"); + + b.HasIndex("UserId"); + + b.HasIndex("RunId", "EventId"); + + b.ToTable("run_stage_events", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageInput", b => + { + b.Property("RunInputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunInputId")); + + b.Property("ConsumedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ConsumedValue") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DeliveredQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("FromRunOutputId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("PlannedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyUnit") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ReturnedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReturnedValue") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RunStageId") + .HasColumnType("integer"); + + b.Property("Source") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("RunInputId"); + + b.HasIndex("FromRunOutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RunStageId"); + + b.ToTable("run_stage_inputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageOutput", b => + { + b.Property("RunOutputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunOutputId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("PlannedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ProducedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RunStageId") + .HasColumnType("integer"); + + b.Property("ScrapReasonCodeId") + .HasColumnType("integer"); + + b.Property("ScrappedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TransferredQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UomId") + .HasColumnType("integer"); + + b.HasKey("RunOutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RunStageId"); + + b.HasIndex("ScrapReasonCodeId"); + + b.HasIndex("UomId"); + + b.ToTable("run_stage_outputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalaryComponent", b => + { + b.Property("SalaryComponentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalaryComponentId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ComponentType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsEpfEtfApplicable") + .HasColumnType("boolean"); + + b.Property("IsTaxable") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("SalaryComponentId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_salary_components", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesDayEnd", b => + { + b.Property("SalesDayEndId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesDayEndId")); + + b.Property("BalanceTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BundleCount") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("BusinessDate") + .HasColumnType("date"); + + b.Property("CashierUserId") + .HasColumnType("integer"); + + b.Property("ClosedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ClosedBy") + .HasColumnType("integer"); + + b.Property("CostOfGoodsSold") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SlipCount") + .HasColumnType("integer"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("SalesDayEndId"); + + b.HasIndex("ClosedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("CashierUserId", "BusinessDate") + .IsUnique(); + + b.ToTable("sales_day_ends", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoice", b => + { + b.Property("SalesInvoiceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesInvoiceId")); + + b.Property("BalanceAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("CreatorUserId") + .HasColumnType("integer"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("CustomerSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CustomerSnapshotTaxNo") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("InvoiceDate") + .HasColumnType("timestamp with time zone"); + + b.Property("InvoiceNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("InvoiceType") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("B2C"); + + b.Property("NetPayable") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RoundOff") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesInvoiceId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatorUserId"); + + b.HasIndex("CustomerId"); + + b.HasIndex("InvoiceDate"); + + b.HasIndex("InvoiceNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_invoices", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoiceLine", b => + { + b.Property("SalesInvoiceLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesInvoiceLineId")); + + b.Property("BaseCost") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DiscountAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DiscountMode") + .HasColumnType("integer"); + + b.Property("DiscountPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("FreeQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("IsFreeIssue") + .HasColumnType("boolean"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("NetUnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ParentLineId") + .HasColumnType("integer"); + + b.Property("PriceSource") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SalesInvoiceId") + .HasColumnType("integer"); + + b.Property("TaxAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesInvoiceLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SalesInvoiceId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_invoice_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoicePayment", b => + { + b.Property("SalesInvoicePaymentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesInvoicePaymentId")); + + b.Property("Amount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BankAccountName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("GlBankAccountId") + .HasColumnType("bigint"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PaymentDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Reference") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("SalesInvoiceId") + .HasColumnType("integer"); + + b.HasKey("SalesInvoicePaymentId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("SalesInvoiceId"); + + b.ToTable("sales_invoice_payments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturn", b => + { + b.Property("ReturnId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReasonCodeId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("ReturnId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("CustomerId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("ReasonCodeId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_returns", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturnLine", b => + { + b.Property("ReturnLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReturnId") + .HasColumnType("integer"); + + b.Property("SalesInvoiceLineId") + .HasColumnType("integer"); + + b.HasKey("ReturnLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("ReturnId"); + + b.HasIndex("SalesInvoiceLineId"); + + b.ToTable("sales_return_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlip", b => + { + b.Property("SalesSlipId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesSlipId")); + + b.Property("BalanceAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CashierUserId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("CustomerSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DayEndId") + .HasColumnType("integer"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SlipDate") + .HasColumnType("timestamp with time zone"); + + b.Property("SlipNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesSlipId"); + + b.HasIndex("CashierUserId"); + + b.HasIndex("CustomerId"); + + b.HasIndex("DayEndId"); + + b.HasIndex("SlipDate"); + + b.HasIndex("SlipNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_slips", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlipLine", b => + { + b.Property("SalesSlipLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesSlipLineId")); + + b.Property("BaseCost") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DiscountAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DiscountMode") + .HasColumnType("integer"); + + b.Property("DiscountPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("FreeQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("IsFreeIssue") + .HasColumnType("boolean"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("NetUnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ParentLineId") + .HasColumnType("integer"); + + b.Property("PriceSource") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SalesSlipId") + .HasColumnType("integer"); + + b.Property("TaxAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesSlipLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SalesSlipId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_slip_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Serial", b => + { + b.Property("SerialId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SerialId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("SerialNo") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("SerialId"); + + b.HasIndex("ItemId", "SerialNo") + .IsUnique(); + + b.ToTable("serials", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageEdge", b => + { + b.Property("EdgeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EdgeId")); + + b.Property("ChildStageId") + .HasColumnType("integer"); + + b.Property("ParentStageId") + .HasColumnType("integer"); + + b.Property("TemplateId") + .HasColumnType("integer"); + + b.HasKey("EdgeId"); + + b.HasIndex("ChildStageId"); + + b.HasIndex("TemplateId"); + + b.HasIndex("ParentStageId", "ChildStageId") + .IsUnique(); + + b.ToTable("stage_edges", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageInput", b => + { + b.Property("InputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("InputId")); + + b.Property("FromOutputId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyPerBatch") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyUnit") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Source") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("StageId") + .HasColumnType("integer"); + + b.HasKey("InputId"); + + b.HasIndex("FromOutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("StageId"); + + b.ToTable("stage_inputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageOutput", b => + { + b.Property("OutputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("OutputId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("QtyPerBatch") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("StageId") + .HasColumnType("integer"); + + b.Property("UomId") + .HasColumnType("integer"); + + b.HasKey("OutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("StageId"); + + b.HasIndex("UomId"); + + b.ToTable("stage_outputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustment", b => + { + b.Property("AdjustmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AdjustmentId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReasonCodeId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("AdjustmentId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("ReasonCodeId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("stock_adjustments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustmentLine", b => + { + b.Property("AdjLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AdjLineId")); + + b.Property("AdjustmentId") + .HasColumnType("integer"); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyDelta") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.HasKey("AdjLineId"); + + b.HasIndex("AdjustmentId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SerialId"); + + b.ToTable("stock_adjustment_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCount", b => + { + b.Property("CountId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CountId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CountType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("CountId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("stock_counts", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCountLine", b => + { + b.Property("CountLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CountLineId")); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("CountId") + .HasColumnType("integer"); + + b.Property("CountedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("SystemQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Variance") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("CountLineId"); + + b.HasIndex("BinId"); + + b.HasIndex("CountId"); + + b.HasIndex("ItemId"); + + b.ToTable("stock_count_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLayer", b => + { + b.Property("LayerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LayerId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("GrnLineId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyReceived") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyRemaining") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReceiptDate") + .HasColumnType("timestamp with time zone"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("LayerId"); + + b.HasIndex("BatchId"); + + b.HasIndex("GrnLineId"); + + b.HasIndex("SerialId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("ItemId", "WarehouseId", "ReceiptDate", "LayerId"); + + b.ToTable("stock_layers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLedger", b => + { + b.Property("LedgerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LedgerId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Direction") + .IsRequired() + .HasMaxLength(5) + .HasColumnType("character varying(5)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyBase") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RunningBalance") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("SourceDocId") + .HasColumnType("integer"); + + b.Property("SourceDocType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.Property("Value") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("LedgerId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("SerialId"); + + b.HasIndex("UserId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("SourceDocType", "SourceDocId"); + + b.HasIndex("ItemId", "WarehouseId", "CreatedAt"); + + b.HasIndex("ItemId", "WarehouseId", "LedgerId"); + + b.ToTable("stock_ledger", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransfer", b => + { + b.Property("TransferId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TransferId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DestWarehouseId") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SrcWarehouseId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("TransferId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DestWarehouseId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("SrcWarehouseId"); + + b.HasIndex("Status"); + + b.ToTable("stock_transfers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransferLine", b => + { + b.Property("TransferLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TransferLineId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("DestBinId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyReceived") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("SrcBinId") + .HasColumnType("integer"); + + b.Property("TransferId") + .HasColumnType("integer"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.HasKey("TransferLineId"); + + b.HasIndex("BatchId"); + + b.HasIndex("DestBinId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SerialId"); + + b.HasIndex("SrcBinId"); + + b.HasIndex("TransferId"); + + b.ToTable("stock_transfer_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubCategory", b => + { + b.Property("SubCategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SubCategoryId")); + + b.Property("CategoryId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("SubCategoryId"); + + b.HasIndex("Status"); + + b.HasIndex("CategoryId", "Name") + .IsUnique(); + + b.ToTable("subcategories", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubNavItem", b => + { + b.Property("SubNavItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SubNavItemId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Href") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Icon") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("NavItemId") + .HasColumnType("integer"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.HasKey("SubNavItemId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("NavItemId"); + + b.ToTable("sub_nav_items", (string)null); + + b.HasData( + new + { + SubNavItemId = 1, + Code = "products.item", + Href = "/dashboard/products", + Label = "Item", + NavItemId = 2, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 2, + Code = "products.category", + Href = "/dashboard/products/categories", + Label = "Category", + NavItemId = 2, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 3, + Code = "products.brand", + Href = "/dashboard/products/brands", + Label = "Brand", + NavItemId = 2, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 4, + Code = "products.item-type", + Href = "/dashboard/products/item-types", + Label = "Item Type", + NavItemId = 2, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 5, + Code = "products.uom", + Href = "/dashboard/products/uoms", + Label = "UOM", + NavItemId = 2, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 6, + Code = "products.configuration", + Href = "/dashboard/products/settings", + Label = "Configuration", + NavItemId = 2, + SortOrder = 6, + Status = "Active" + }, + new + { + SubNavItemId = 29, + Code = "settings.branches", + Href = "/dashboard/settings/branches", + Label = "Branches", + NavItemId = 9, + SortOrder = 0, + Status = "Active" + }, + new + { + SubNavItemId = 7, + Code = "settings.roles", + Href = "/dashboard/settings/roles", + Label = "Roles", + NavItemId = 9, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 8, + Code = "settings.users", + Href = "/dashboard/settings/users", + Label = "Users", + NavItemId = 9, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 24, + Code = "settings.notification-config", + Href = "/dashboard/settings/notification-config", + Label = "Notification Config", + NavItemId = 9, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 40, + Code = "sales.invoices", + Href = "/dashboard/sales/invoices", + Label = "Sales", + NavItemId = 13, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 23, + Code = "sales.bundle-templates", + Href = "/dashboard/sales/bundles/templates", + Label = "Bundle Templates", + NavItemId = 13, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 41, + Code = "sales.free-issues", + Href = "/dashboard/sales/free-issues", + Label = "Free Issues", + NavItemId = 13, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 42, + Code = "sales.day-end", + Href = "/dashboard/sales/day-end", + Label = "Day End", + NavItemId = 13, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 30, + Code = "procurement.vendors", + Href = "/dashboard/vendors", + Label = "Vendors", + NavItemId = 4, + SortOrder = 0, + Status = "Active" + }, + new + { + SubNavItemId = 17, + Code = "procurement.requisitions", + Href = "/dashboard/procurement/requisitions", + Label = "Requisitions", + NavItemId = 4, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 18, + Code = "procurement.rfqs", + Href = "/dashboard/procurement/rfqs", + Label = "RFQs", + NavItemId = 4, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 19, + Code = "procurement.purchase-orders", + Href = "/dashboard/procurement/purchase-orders", + Label = "Purchase Orders", + NavItemId = 4, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 20, + Code = "procurement.purchase-returns", + Href = "/dashboard/procurement/purchase-returns", + Label = "Purchase Returns", + NavItemId = 4, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 28, + Code = "procurement.purchase-invoices", + Href = "/dashboard/procurement/purchase-invoices", + Label = "Purchase Invoices", + NavItemId = 4, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 9, + Code = "ledgers.trial-balance", + Href = "/dashboard/ledgers/trial-balance", + Label = "Trial Balance", + NavItemId = 11, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 10, + Code = "ledgers.balance-sheet", + Href = "/dashboard/ledgers/balance-sheet", + Label = "Balance Sheet", + NavItemId = 11, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 11, + Code = "ledgers.general-ledger", + Href = "/dashboard/ledgers/general-ledger", + Label = "General Ledger", + NavItemId = 11, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 12, + Code = "ledgers.profit-and-loss", + Href = "/dashboard/ledgers/profit-and-loss", + Label = "Profit & Loss", + NavItemId = 11, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 13, + Code = "ledgers.cash-flow", + Href = "/dashboard/ledgers/cash-flow", + Label = "Cash Flow", + NavItemId = 11, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 14, + Code = "ledgers.budget-vs-actual", + Href = "/dashboard/ledgers/budget-vs-actual", + Label = "Budget vs Actual", + NavItemId = 11, + SortOrder = 6, + Status = "Active" + }, + new + { + SubNavItemId = 16, + Code = "ledgers.tax-report", + Href = "/dashboard/ledgers/tax-report", + Label = "Tax Report", + NavItemId = 11, + SortOrder = 7, + Status = "Active" + }, + new + { + SubNavItemId = 15, + Code = "accounts.bank-accounts", + Href = "/dashboard/accounts/bank-accounts", + Label = "Cash / Bank Accounts", + NavItemId = 12, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 21, + Code = "accounts.cheque-books", + Href = "/dashboard/accounts/cheque-books", + Label = "Cheque Books", + NavItemId = 12, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 22, + Code = "accounts.received-cheques", + Href = "/dashboard/accounts/received-cheques", + Label = "Received Cheques", + NavItemId = 12, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 27, + Code = "production.templates", + Href = "/dashboard/production/templates", + Label = "Templates", + NavItemId = 14, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 25, + Code = "production.runs", + Href = "/dashboard/production/runs", + Label = "Runs", + NavItemId = 14, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 26, + Code = "production.produced", + Href = "/dashboard/production/produced", + Label = "Produced", + NavItemId = 14, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 31, + Code = "stock.ledger", + Href = "/dashboard/stock/ledger", + Label = "Stock Ledger", + NavItemId = 6, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 32, + Code = "stock.enquiry", + Href = "/dashboard/stock/enquiry", + Label = "Stock Enquiry", + NavItemId = 6, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 33, + Code = "stock.valuation", + Href = "/dashboard/stock/valuation", + Label = "Valuation", + NavItemId = 6, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 34, + Code = "stock.transfers", + Href = "/dashboard/stock/transfers", + Label = "Transfers", + NavItemId = 6, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 35, + Code = "stock.adjustments", + Href = "/dashboard/stock/adjustments", + Label = "Adjustments", + NavItemId = 6, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 36, + Code = "stock.counts", + Href = "/dashboard/stock/counts", + Label = "Counts", + NavItemId = 6, + SortOrder = 6, + Status = "Active" + }, + new + { + SubNavItemId = 37, + Code = "stock.reorder-alerts", + Href = "/dashboard/stock/reorder-alerts", + Label = "Reorder Alerts", + NavItemId = 6, + SortOrder = 7, + Status = "Active" + }, + new + { + SubNavItemId = 38, + Code = "stock.wastage", + Href = "/dashboard/stock/wastage", + Label = "Wastage", + NavItemId = 6, + SortOrder = 8, + Status = "Active" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicket", b => + { + b.Property("TicketId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TicketId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Subject") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.HasKey("TicketId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("Status"); + + b.ToTable("support_tickets", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicketMessage", b => + { + b.Property("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("MessageId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsFromAdmin") + .HasColumnType("boolean"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("SenderUserId") + .HasColumnType("integer"); + + b.Property("TicketId") + .HasColumnType("integer"); + + b.HasKey("MessageId"); + + b.HasIndex("TicketId", "CreatedAt"); + + b.ToTable("support_ticket_messages", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TaxSlab", b => + { + b.Property("TaxSlabId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TaxSlabId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveTo") + .HasColumnType("timestamp with time zone"); + + b.Property("LowerBound") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("Rate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("UpperBound") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.HasKey("TaxSlabId"); + + b.HasIndex("EffectiveFrom"); + + b.ToTable("hr_tax_slabs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => + { + b.Property("StageId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("StageId")); + + b.Property("EstimatedMinutes") + .HasColumnType("integer"); + + b.Property("FieldDefs") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("PosX") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PosY") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RoleLabel") + .HasMaxLength(60) + .HasColumnType("character varying(60)"); + + b.Property("TemplateId") + .HasColumnType("integer"); + + b.HasKey("StageId"); + + b.HasIndex("TemplateId"); + + b.ToTable("template_stages", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Uom", b => + { + b.Property("UomId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("UomId")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("UomId"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("uoms", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.User", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("UserId")); + + b.Property("AuthUserId") + .HasColumnType("uuid") + .HasColumnName("auth_user_id"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Email") + .HasMaxLength(320) + .HasColumnType("character varying(320)"); + + b.Property("RoleId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("UserId"); + + b.HasIndex("AuthUserId") + .IsUnique(); + + b.HasIndex("Email") + .IsUnique(); + + b.HasIndex("RoleId"); + + b.HasIndex("Username") + .IsUnique(); + + b.ToTable("users", (string)null); + + b.HasData( + new + { + UserId = 1, + DisplayName = "System", + Status = "Active", + Username = "system" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Vendor", b => + { + b.Property("VendorId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("VendorId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Currency") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(3) + .HasColumnType("character varying(3)") + .HasDefaultValue("LKR"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TaxReg") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Terms") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("VendorId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("vendors", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => + { + b.Property("QuotationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("QuotationId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("RfqId") + .HasColumnType("integer"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.HasKey("QuotationId"); + + b.HasIndex("VendorId"); + + b.HasIndex("RfqId", "VendorId") + .IsUnique(); + + b.ToTable("vendor_quotations", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotationLine", b => + { + b.Property("QuotationLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("QuotationLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LeadDays") + .HasColumnType("integer"); + + b.Property("QuotationId") + .HasColumnType("integer"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("QuotationLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("QuotationId"); + + b.ToTable("vendor_quotation_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Warehouse", b => + { + b.Property("WarehouseId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("WarehouseId")); + + b.Property("Address") + .HasColumnType("text"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Phone") + .HasColumnType("text"); + + b.HasKey("WarehouseId"); + + b.HasIndex("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("warehouses", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.WorkShift", b => + { + b.Property("WorkShiftId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("WorkShiftId")); + + b.Property("BreakMinutes") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EndTime") + .HasColumnType("interval"); + + b.Property("GraceMinutes") + .HasColumnType("integer"); + + b.Property("IsOvernight") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("OtMultiplier") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("StandardWorkingMinutes") + .HasColumnType("integer"); + + b.Property("StartTime") + .HasColumnType("interval"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WorkingDaysMask") + .HasColumnType("integer"); + + b.HasKey("WorkShiftId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_work_shifts", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceRecord", b => + { + b.HasOne("ERPCore.Domain.Entities.AttendanceUploadBatch", "AttendanceUploadBatch") + .WithMany() + .HasForeignKey("AttendanceUploadBatchId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.WorkShift", "WorkShift") + .WithMany() + .HasForeignKey("WorkShiftId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("AttendanceUploadBatch"); + + b.Navigation("Employee"); + + b.Navigation("WorkShift"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AuditLog", b => + { + b.HasOne("ERPCore.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Batch", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Bin", b => + { + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany("Bins") + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BranchConfig", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSale", b => + { + b.HasOne("ERPCore.Domain.Entities.BundleSaleTemplate", "BundleSaleTemplate") + .WithMany() + .HasForeignKey("BundleSaleTemplateId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "CashierUser") + .WithMany() + .HasForeignKey("CashierUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesDayEnd", "DayEnd") + .WithMany("BundleSales") + .HasForeignKey("DayEndId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BundleSaleTemplate"); + + b.Navigation("CashierUser"); + + b.Navigation("Customer"); + + b.Navigation("DayEnd"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleLine", b => + { + b.HasOne("ERPCore.Domain.Entities.BundleSale", "BundleSale") + .WithMany("Lines") + .HasForeignKey("BundleSaleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BundleSale"); + + b.Navigation("Item"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplateLine", b => + { + b.HasOne("ERPCore.Domain.Entities.BundleSaleTemplate", "BundleSaleTemplate") + .WithMany("Lines") + .HasForeignKey("BundleSaleTemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BundleSaleTemplate"); + + b.Navigation("Item"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Customer", b => + { + b.HasOne("ERPCore.Domain.Entities.Warehouse", "DefaultWarehouse") + .WithMany() + .HasForeignKey("DefaultWarehouseId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("DefaultWarehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Department", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Employee", "HeadEmployee") + .WithMany() + .HasForeignKey("HeadEmployeeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Department", "ParentDepartment") + .WithMany() + .HasForeignKey("ParentDepartmentId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Branch"); + + b.Navigation("HeadEmployee"); + + b.Navigation("ParentDepartment"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Employee", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Department", "Department") + .WithMany() + .HasForeignKey("DepartmentId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Designation", "Designation") + .WithMany() + .HasForeignKey("DesignationId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.EmploymentType", "EmploymentType") + .WithMany() + .HasForeignKey("EmploymentTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Employee", "ReportingManager") + .WithMany() + .HasForeignKey("ReportingManagerId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithOne() + .HasForeignKey("ERPCore.Domain.Entities.Employee", "UserId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.WorkShift", "WorkShift") + .WithMany() + .HasForeignKey("WorkShiftId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Department"); + + b.Navigation("Designation"); + + b.Navigation("EmploymentType"); + + b.Navigation("ReportingManager"); + + b.Navigation("User"); + + b.Navigation("WorkShift"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeBankDetail", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeDocument", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.HrDocumentType", "HrDocumentType") + .WithMany() + .HasForeignKey("HrDocumentTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("HrDocumentType"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeLoan", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructure", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructureLine", b => + { + b.HasOne("ERPCore.Domain.Entities.EmployeeSalaryStructure", "EmployeeSalaryStructure") + .WithMany("Lines") + .HasForeignKey("EmployeeSalaryStructureId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalaryComponent", "SalaryComponent") + .WithMany() + .HasForeignKey("SalaryComponentId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("EmployeeSalaryStructure"); + + b.Navigation("SalaryComponent"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Grn", 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.HasOne("ERPCore.Domain.Entities.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("PoId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.PurchaseInvoice", "PurchaseInvoice") + .WithMany() + .HasForeignKey("PurchaseInvoiceId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("PurchaseInvoice"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Vendor"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", "Batch") + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", "Bin") + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Grn", "Grn") + .WithMany("Lines") + .HasForeignKey("GrnId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PoLine", "PoLine") + .WithMany() + .HasForeignKey("PoLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Batch"); + + b.Navigation("Bin"); + + b.Navigation("Grn"); + + b.Navigation("Item"); + + b.Navigation("PoLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLineWarrantyNumber", b => + { + b.HasOne("ERPCore.Domain.Entities.GrnLine", "GrnLine") + .WithMany("WarrantyNumbers") + .HasForeignKey("GrnLineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GrnLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Item", b => + { + b.HasOne("ERPCore.Domain.Entities.Uom", "BaseUom") + .WithMany() + .HasForeignKey("BaseUomId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Brand", "Brand") + .WithMany() + .HasForeignKey("BrandId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Category", "Category") + .WithMany() + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "DefaultVendor") + .WithMany() + .HasForeignKey("DefaultVendorId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.SubCategory", "SubCategory") + .WithMany() + .HasForeignKey("SubCategoryId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("BaseUom"); + + b.Navigation("Brand"); + + b.Navigation("Category"); + + b.Navigation("DefaultVendor"); + + b.Navigation("SubCategory"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ItemReorder", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany("ReorderSettings") + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveBalance", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.LeaveType", "LeaveType") + .WithMany() + .HasForeignKey("LeaveTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("LeaveType"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveRequest", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.LeaveType", "LeaveType") + .WithMany() + .HasForeignKey("LeaveTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("LeaveType"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoanInstallment", b => + { + b.HasOne("ERPCore.Domain.Entities.EmployeeLoan", "EmployeeLoan") + .WithMany("Installments") + .HasForeignKey("EmployeeLoanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PayrollRun", "PayrollRun") + .WithMany() + .HasForeignKey("PayrollRunId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("EmployeeLoan"); + + b.Navigation("PayrollRun"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoginActivity", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfigModule", b => + { + b.HasOne("ERPCore.Domain.Entities.NotificationConfig", "NotificationConfig") + .WithMany("Modules") + .HasForeignKey("NotificationConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("NotificationConfig"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationRecipient", b => + { + b.HasOne("ERPCore.Domain.Entities.Notification", "Notification") + .WithMany("Recipients") + .HasForeignKey("NotificationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Notification"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PayrollRun", "PayrollRun") + .WithMany("Lines") + .HasForeignKey("PayrollRunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("PayrollRun"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLineComponent", b => + { + b.HasOne("ERPCore.Domain.Entities.PayrollLine", "PayrollLine") + .WithMany("Components") + .HasForeignKey("PayrollLineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalaryComponent", "SalaryComponent") + .WithMany() + .HasForeignKey("SalaryComponentId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("PayrollLine"); + + b.Navigation("SalaryComponent"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollRun", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Branch"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Payslip", b => + { + b.HasOne("ERPCore.Domain.Entities.PayrollLine", "PayrollLine") + .WithOne() + .HasForeignKey("ERPCore.Domain.Entities.Payslip", "PayrollLineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PayrollLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Permission", b => + { + b.HasOne("ERPCore.Domain.Entities.NavItem", "NavItem") + .WithMany() + .HasForeignKey("NavItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ERPCore.Domain.Entities.SubNavItem", "SubNavItem") + .WithMany() + .HasForeignKey("SubNavItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("NavItem"); + + b.Navigation("SubNavItem"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PoLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseOrder", "PurchaseOrder") + .WithMany("Lines") + .HasForeignKey("PoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductConfig", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b => + { + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "CancelReason") + .WithMany() + .HasForeignKey("CancelReasonCodeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Bin", "OutputBin") + .WithMany() + .HasForeignKey("OutputBinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") + .WithMany("Runs") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CancelReason"); + + b.Navigation("Creator"); + + b.Navigation("OutputBin"); + + b.Navigation("Template"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionTemplate", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoiceLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Grn", "Grn") + .WithMany() + .HasForeignKey("GrnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseInvoice", "PurchaseInvoice") + .WithMany("Lines") + .HasForeignKey("PurchaseInvoiceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Grn"); + + b.Navigation("PurchaseInvoice"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoicePayment", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseInvoice", "PurchaseInvoice") + .WithMany("Payments") + .HasForeignKey("PurchaseInvoiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("PurchaseInvoice"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Approver") + .WithMany() + .HasForeignKey("ApproverUserId"); + + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") + .WithMany() + .HasForeignKey("RequisitionId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Approver"); + + b.Navigation("Creator"); + + b.Navigation("Requisition"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturn", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ReasonCode") + .WithMany() + .HasForeignKey("ReasonCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("ReasonCode"); + + b.Navigation("Vendor"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturnLine", b => + { + b.HasOne("ERPCore.Domain.Entities.GrnLine", "GrnLine") + .WithMany() + .HasForeignKey("GrnLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseReturn", "Return") + .WithMany("Lines") + .HasForeignKey("ReturnId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GrnLine"); + + b.Navigation("Item"); + + b.Navigation("Return"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Requester") + .WithMany() + .HasForeignKey("RequestedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Requester"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RequisitionLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") + .WithMany("Lines") + .HasForeignKey("RequisitionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Requisition"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => + { + b.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") + .WithMany() + .HasForeignKey("RequisitionId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Requisition"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RfqLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Rfq", "Rfq") + .WithMany("Lines") + .HasForeignKey("RfqId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Rfq"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RolePermission", b => + { + b.HasOne("ERPCore.Domain.Entities.Permission", "Permission") + .WithMany() + .HasForeignKey("PermissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Role", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Permission"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunEdge", b => + { + b.HasOne("ERPCore.Domain.Entities.RunStage", "ChildRunStage") + .WithMany() + .HasForeignKey("ChildRunStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "ParentRunStage") + .WithMany() + .HasForeignKey("ParentRunStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ProductionRun", "Run") + .WithMany("Edges") + .HasForeignKey("RunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildRunStage"); + + b.Navigation("ParentRunStage"); + + b.Navigation("Run"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStage", b => + { + b.HasOne("ERPCore.Domain.Entities.ProductionRun", "Run") + .WithMany("Stages") + .HasForeignKey("RunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "TemplateStage") + .WithMany() + .HasForeignKey("TemplateStageId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Run"); + + b.Navigation("TemplateStage"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageEvent", b => + { + b.HasOne("ERPCore.Domain.Entities.ProductionRun", "Run") + .WithMany("Events") + .HasForeignKey("RunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "RunStage") + .WithMany("Events") + .HasForeignKey("RunStageId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Run"); + + b.Navigation("RunStage"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageInput", b => + { + b.HasOne("ERPCore.Domain.Entities.RunStageOutput", "FromRunOutput") + .WithMany() + .HasForeignKey("FromRunOutputId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "RunStage") + .WithMany("Inputs") + .HasForeignKey("RunStageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromRunOutput"); + + b.Navigation("Item"); + + b.Navigation("RunStage"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageOutput", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "RunStage") + .WithMany("Outputs") + .HasForeignKey("RunStageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ScrapReason") + .WithMany() + .HasForeignKey("ScrapReasonCodeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Uom", "Uom") + .WithMany() + .HasForeignKey("UomId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Item"); + + b.Navigation("RunStage"); + + b.Navigation("ScrapReason"); + + b.Navigation("Uom"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesDayEnd", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "CashierUser") + .WithMany() + .HasForeignKey("CashierUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "ClosedByUser") + .WithMany() + .HasForeignKey("ClosedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CashierUser"); + + b.Navigation("ClosedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoice", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatorUserId"); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("Customer"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoiceLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesInvoice", "SalesInvoice") + .WithMany("Lines") + .HasForeignKey("SalesInvoiceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SalesInvoice"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoicePayment", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesInvoice", "SalesInvoice") + .WithMany("Payments") + .HasForeignKey("SalesInvoiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("SalesInvoice"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturn", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ReasonCode") + .WithMany() + .HasForeignKey("ReasonCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("Customer"); + + b.Navigation("ReasonCode"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturnLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesReturn", "Return") + .WithMany("Lines") + .HasForeignKey("ReturnId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesInvoiceLine", "SalesInvoiceLine") + .WithMany() + .HasForeignKey("SalesInvoiceLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Item"); + + b.Navigation("Return"); + + b.Navigation("SalesInvoiceLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlip", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "CashierUser") + .WithMany() + .HasForeignKey("CashierUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesDayEnd", "DayEnd") + .WithMany("Slips") + .HasForeignKey("DayEndId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CashierUser"); + + b.Navigation("Customer"); + + b.Navigation("DayEnd"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlipLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesSlip", "SalesSlip") + .WithMany("Lines") + .HasForeignKey("SalesSlipId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SalesSlip"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Serial", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageEdge", b => + { + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "ChildStage") + .WithMany() + .HasForeignKey("ChildStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "ParentStage") + .WithMany() + .HasForeignKey("ParentStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") + .WithMany("Edges") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildStage"); + + b.Navigation("ParentStage"); + + b.Navigation("Template"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageInput", b => + { + b.HasOne("ERPCore.Domain.Entities.StageOutput", "FromOutput") + .WithMany() + .HasForeignKey("FromOutputId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "Stage") + .WithMany("Inputs") + .HasForeignKey("StageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromOutput"); + + b.Navigation("Item"); + + b.Navigation("Stage"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageOutput", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "Stage") + .WithMany("Outputs") + .HasForeignKey("StageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Uom", "Uom") + .WithMany() + .HasForeignKey("UomId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Item"); + + b.Navigation("Stage"); + + b.Navigation("Uom"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustment", 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.HasOne("ERPCore.Domain.Entities.ReasonCode", "ReasonCode") + .WithMany() + .HasForeignKey("ReasonCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("ReasonCode"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustmentLine", b => + { + b.HasOne("ERPCore.Domain.Entities.StockAdjustment", "Adjustment") + .WithMany("Lines") + .HasForeignKey("AdjustmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Batch", null) + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", null) + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Adjustment"); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCount", 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.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCountLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.StockCount", "Count") + .WithMany("Lines") + .HasForeignKey("CountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Count"); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLayer", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", "Batch") + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.GrnLine", "GrnLine") + .WithMany() + .HasForeignKey("GrnLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", "Serial") + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Batch"); + + b.Navigation("GrnLine"); + + b.Navigation("Item"); + + b.Navigation("Serial"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLedger", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", null) + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", null) + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", null) + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", null) + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransfer", 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.HasOne("ERPCore.Domain.Entities.Warehouse", "DestWarehouse") + .WithMany() + .HasForeignKey("DestWarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "SrcWarehouse") + .WithMany() + .HasForeignKey("SrcWarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("DestWarehouse"); + + b.Navigation("SrcWarehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransferLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", null) + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("DestBinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", null) + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("SrcBinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.StockTransfer", "Transfer") + .WithMany("Lines") + .HasForeignKey("TransferId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Transfer"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubCategory", b => + { + b.HasOne("ERPCore.Domain.Entities.Category", "Category") + .WithMany("SubCategories") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubNavItem", b => + { + b.HasOne("ERPCore.Domain.Entities.NavItem", "NavItem") + .WithMany("Children") + .HasForeignKey("NavItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("NavItem"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicketMessage", b => + { + b.HasOne("ERPCore.Domain.Entities.SupportTicket", "Ticket") + .WithMany("Messages") + .HasForeignKey("TicketId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ticket"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => + { + b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") + .WithMany("Stages") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Template"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.User", b => + { + b.HasOne("ERPCore.Domain.Entities.Role", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => + { + b.HasOne("ERPCore.Domain.Entities.Rfq", "Rfq") + .WithMany("Quotations") + .HasForeignKey("RfqId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Rfq"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotationLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.VendorQuotation", "Quotation") + .WithMany("Lines") + .HasForeignKey("QuotationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Quotation"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Warehouse", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSale", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplate", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Category", b => + { + b.Navigation("SubCategories"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeLoan", b => + { + b.Navigation("Installments"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructure", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Grn", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLine", b => + { + b.Navigation("WarrantyNumbers"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Item", b => + { + b.Navigation("ReorderSettings"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NavItem", b => + { + b.Navigation("Children"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Notification", b => + { + b.Navigation("Recipients"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => + { + b.Navigation("Modules"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => + { + b.Navigation("Components"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollRun", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b => + { + b.Navigation("Edges"); + + b.Navigation("Events"); + + b.Navigation("Stages"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionTemplate", b => + { + b.Navigation("Edges"); + + b.Navigation("Runs"); + + b.Navigation("Stages"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", b => + { + b.Navigation("Lines"); + + b.Navigation("Payments"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturn", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => + { + b.Navigation("Lines"); + + b.Navigation("Quotations"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStage", b => + { + b.Navigation("Events"); + + b.Navigation("Inputs"); + + b.Navigation("Outputs"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesDayEnd", b => + { + b.Navigation("BundleSales"); + + b.Navigation("Slips"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoice", b => + { + b.Navigation("Lines"); + + b.Navigation("Payments"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturn", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlip", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustment", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCount", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransfer", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicket", b => + { + b.Navigation("Messages"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => + { + b.Navigation("Inputs"); + + b.Navigation("Outputs"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Warehouse", b => + { + b.Navigation("Bins"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Backend/ERPCore/Migrations/20260916071017_AddSalesDayEndPaidBalance.cs b/Backend/ERPCore/Migrations/20260916071017_AddSalesDayEndPaidBalance.cs new file mode 100644 index 0000000..d4bbfbc --- /dev/null +++ b/Backend/ERPCore/Migrations/20260916071017_AddSalesDayEndPaidBalance.cs @@ -0,0 +1,44 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace ERPCore.Migrations +{ + /// + public partial class AddSalesDayEndPaidBalance : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "BalanceTotal", + table: "sales_day_ends", + type: "numeric(18,4)", + precision: 18, + scale: 4, + nullable: false, + defaultValue: 0m); + + migrationBuilder.AddColumn( + name: "PaidTotal", + table: "sales_day_ends", + type: "numeric(18,4)", + precision: 18, + scale: 4, + nullable: false, + defaultValue: 0m); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "BalanceTotal", + table: "sales_day_ends"); + + migrationBuilder.DropColumn( + name: "PaidTotal", + table: "sales_day_ends"); + } + } +} diff --git a/Backend/ERPCore/Migrations/20260916082426_AddTaxRatesAndItemTaxRate.Designer.cs b/Backend/ERPCore/Migrations/20260916082426_AddTaxRatesAndItemTaxRate.Designer.cs new file mode 100644 index 0000000..efae913 --- /dev/null +++ b/Backend/ERPCore/Migrations/20260916082426_AddTaxRatesAndItemTaxRate.Designer.cs @@ -0,0 +1,8547 @@ +// +using System; +using ERPCore.Infra.Persistence; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace ERPCore.Migrations +{ + [DbContext(typeof(ErpDbContext))] + [Migration("20260916082426_AddTaxRatesAndItemTaxRate")] + partial class AddTaxRatesAndItemTaxRate + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.9") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceRecord", b => + { + b.Property("AttendanceRecordId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AttendanceRecordId")); + + b.Property("AttendanceDate") + .HasColumnType("timestamp with time zone"); + + b.Property("AttendanceStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("AttendanceUploadBatchId") + .HasColumnType("integer"); + + b.Property("CheckIn") + .HasColumnType("interval"); + + b.Property("CheckOut") + .HasColumnType("interval"); + + b.Property("DuplicateOfAttendanceRecordId") + .HasColumnType("integer"); + + b.Property("EarlyLeaveMinutes") + .HasColumnType("integer"); + + b.Property("EditedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EditedBy") + .HasColumnType("integer"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("IsManualOverride") + .HasColumnType("boolean"); + + b.Property("LateMinutes") + .HasColumnType("integer"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("OvertimeMinutes") + .HasColumnType("integer"); + + b.Property("RowValidationStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("WorkShiftId") + .HasColumnType("integer"); + + b.Property("WorkingMinutes") + .HasColumnType("integer"); + + b.HasKey("AttendanceRecordId"); + + b.HasIndex("AttendanceUploadBatchId"); + + b.HasIndex("WorkShiftId"); + + b.HasIndex("EmployeeId", "AttendanceDate"); + + b.ToTable("hr_attendance_records", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceUploadBatch", b => + { + b.Property("AttendanceUploadBatchId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AttendanceUploadBatchId")); + + b.Property("ConfirmedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ConfirmedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("OriginalFileName") + .HasMaxLength(260) + .HasColumnType("character varying(260)"); + + b.Property("PeriodEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("PeriodStart") + .HasColumnType("timestamp with time zone"); + + b.Property("RowCountDuplicate") + .HasColumnType("integer"); + + b.Property("RowCountError") + .HasColumnType("integer"); + + b.Property("RowCountTotal") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SourceType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UploadedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UploadedBy") + .HasColumnType("integer"); + + b.HasKey("AttendanceUploadBatchId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("PeriodStart", "PeriodEnd"); + + b.ToTable("hr_attendance_upload_batches", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AuditLog", b => + { + b.Property("AuditId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AuditId")); + + b.Property("Action") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("ChangeSet") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EntityId") + .HasColumnType("integer"); + + b.Property("EntityType") + .IsRequired() + .HasMaxLength(80) + .HasColumnType("character varying(80)"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("AuditId"); + + b.HasIndex("CreatedAt"); + + b.HasIndex("UserId"); + + b.HasIndex("EntityType", "EntityId"); + + b.ToTable("audit_logs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Batch", b => + { + b.Property("BatchId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BatchId")); + + b.Property("BatchNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ExpiryDate") + .HasColumnType("date"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.HasKey("BatchId"); + + b.HasIndex("ItemId", "BatchNo") + .IsUnique(); + + b.ToTable("batches", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Bin", b => + { + b.Property("BinId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BinId")); + + b.Property("BinType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BinId"); + + b.HasIndex("WarehouseId", "Code") + .IsUnique(); + + b.ToTable("bins", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Branch", b => + { + b.Property("BranchId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BranchId")); + + b.Property("Address") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("PhoneNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_branches", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BranchConfig", b => + { + b.Property("ConfigId") + .HasColumnType("integer"); + + b.Property("BranchingEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.Property("WarehouseBranchingEnabled") + .HasColumnType("boolean"); + + b.HasKey("ConfigId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("branch_config", null, t => + { + t.HasCheckConstraint("ck_branch_config_singleton", "\"ConfigId\" = 1"); + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Brand", b => + { + b.Property("BrandId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BrandId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("BrandId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("brands", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSale", b => + { + b.Property("BundleSaleId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleId")); + + b.Property("BundleCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BundleDate") + .HasColumnType("timestamp with time zone"); + + b.Property("BundleName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("BundleNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BundlePrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BundleSaleTemplateId") + .HasColumnType("integer"); + + b.Property("CashierUserId") + .HasColumnType("integer"); + + b.Property("ComponentSubtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("CustomerSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DayEndId") + .HasColumnType("integer"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("MarginAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BundleSaleId"); + + b.HasIndex("BundleNo") + .IsUnique(); + + b.HasIndex("BundleSaleTemplateId"); + + b.HasIndex("CashierUserId"); + + b.HasIndex("CustomerId"); + + b.HasIndex("DayEndId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("bundle_sales", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleLine", b => + { + b.Property("BundleSaleLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleLineId")); + + b.Property("BundleSaleId") + .HasColumnType("integer"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("IncludeInBundle") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("IsComponent") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ParentLineId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BundleSaleLineId"); + + b.HasIndex("BundleSaleId"); + + b.HasIndex("ItemId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("bundle_sale_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplate", b => + { + b.Property("BundleSaleTemplateId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleTemplateId")); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TemplateCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("TemplateName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("BundleSaleTemplateId"); + + b.HasIndex("TemplateCode") + .IsUnique(); + + b.ToTable("bundle_sale_templates", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplateLine", b => + { + b.Property("BundleSaleTemplateLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleTemplateLineId")); + + b.Property("BundleSaleTemplateId") + .HasColumnType("integer"); + + b.Property("IncludeInBundle") + .HasColumnType("boolean"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SortOrder") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BundleSaleTemplateLineId"); + + b.HasIndex("BundleSaleTemplateId"); + + b.HasIndex("ItemId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("bundle_sale_template_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Category", b => + { + b.Property("CategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CategoryId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("CategoryId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("categories", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Customer", b => + { + b.Property("CustomerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CustomerId")); + + b.Property("AddressLine1") + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("AddressLine2") + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("City") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Country") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreditDays") + .HasColumnType("integer"); + + b.Property("CreditLimit") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CustomerCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CustomerType") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("B2C"); + + b.Property("DefaultWarehouseId") + .HasColumnType("integer"); + + b.Property("DisplayName") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Email") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Phone") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TaxRegistrationNo") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("CustomerId"); + + b.HasIndex("CustomerCode") + .IsUnique(); + + b.HasIndex("CustomerType"); + + b.HasIndex("DefaultWarehouseId"); + + b.HasIndex("Status"); + + b.ToTable("customers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Department", b => + { + b.Property("DepartmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("DepartmentId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("HeadEmployeeId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("ParentDepartmentId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("DepartmentId"); + + b.HasIndex("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("HeadEmployeeId"); + + b.HasIndex("ParentDepartmentId"); + + b.HasIndex("Status"); + + b.ToTable("hr_departments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Designation", b => + { + b.Property("DesignationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("DesignationId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("DesignationId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_designations", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Employee", b => + { + b.Property("EmployeeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeId")); + + b.Property("AddressLine1") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("AddressLine2") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("City") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ConfirmationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Country") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DateOfBirth") + .HasColumnType("timestamp with time zone"); + + b.Property("DepartmentId") + .HasColumnType("integer"); + + b.Property("DesignationId") + .HasColumnType("integer"); + + b.Property("Email") + .HasMaxLength(320) + .HasColumnType("character varying(320)"); + + b.Property("EmergencyContactName") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("EmergencyContactPhone") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmergencyContactRelationship") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("EmployeeCode") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmploymentTypeId") + .HasColumnType("integer"); + + b.Property("EpfNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EtfNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Gender") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("HireDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LastWorkingDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Nationality") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Nic") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PersonalMobile") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PostalCode") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ProfilePhotoPath") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("ReportingManagerId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TaxIdentificationNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.Property("WorkShiftId") + .HasColumnType("integer"); + + b.HasKey("EmployeeId"); + + b.HasIndex("BranchId"); + + b.HasIndex("DepartmentId"); + + b.HasIndex("DesignationId"); + + b.HasIndex("Email"); + + b.HasIndex("EmployeeCode") + .IsUnique(); + + b.HasIndex("EmploymentTypeId"); + + b.HasIndex("ReportingManagerId"); + + b.HasIndex("Status"); + + b.HasIndex("UserId") + .IsUnique(); + + b.HasIndex("WorkShiftId"); + + b.ToTable("hr_employees", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeBankDetail", b => + { + b.Property("EmployeeBankDetailId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeBankDetailId")); + + b.Property("AccountHolderName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("AccountNumber") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BankName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("BranchName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("IsPrimary") + .HasColumnType("boolean"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("SwiftCode") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("EmployeeBankDetailId"); + + b.HasIndex("EmployeeId"); + + b.ToTable("hr_employee_bank_details", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeDocument", b => + { + b.Property("EmployeeDocumentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeDocumentId")); + + b.Property("ContentType") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("ExpiryDate") + .HasColumnType("timestamp with time zone"); + + b.Property("HrDocumentTypeId") + .HasColumnType("integer"); + + b.Property("IssueDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("OriginalFileName") + .IsRequired() + .HasMaxLength(260) + .HasColumnType("character varying(260)"); + + b.Property("RelativePath") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SizeBytes") + .HasColumnType("bigint"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("StoredFileName") + .IsRequired() + .HasMaxLength(260) + .HasColumnType("character varying(260)"); + + b.Property("UploadedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UploadedBy") + .HasColumnType("integer"); + + b.Property("VerifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VerifiedBy") + .HasColumnType("integer"); + + b.HasKey("EmployeeDocumentId"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("ExpiryDate"); + + b.HasIndex("HrDocumentTypeId"); + + b.ToTable("hr_employee_documents", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeLoan", b => + { + b.Property("EmployeeLoanId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeLoanId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("InstallmentAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("InterestRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("LoanKind") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("NumberOfInstallments") + .HasColumnType("integer"); + + b.Property("OutstandingBalance") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("PrincipalAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("StartMonth") + .HasColumnType("integer"); + + b.Property("StartYear") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("EmployeeLoanId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("EmployeeId"); + + b.HasIndex("Status"); + + b.ToTable("hr_employee_loans", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructure", b => + { + b.Property("EmployeeSalaryStructureId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeSalaryStructureId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("BasicSalary") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("Currency") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("character varying(3)"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveTo") + .HasColumnType("timestamp with time zone"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("EmployeeSalaryStructureId"); + + b.HasIndex("EmployeeId", "EffectiveTo"); + + b.ToTable("hr_employee_salary_structures", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructureLine", b => + { + b.Property("EmployeeSalaryStructureLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeSalaryStructureLineId")); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("EmployeeSalaryStructureId") + .HasColumnType("integer"); + + b.Property("SalaryComponentId") + .HasColumnType("integer"); + + b.HasKey("EmployeeSalaryStructureLineId"); + + b.HasIndex("EmployeeSalaryStructureId"); + + b.HasIndex("SalaryComponentId"); + + b.ToTable("hr_employee_salary_structure_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmploymentType", b => + { + b.Property("EmploymentTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmploymentTypeId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("EmploymentTypeId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_employment_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Grn", b => + { + b.Property("GrnId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("GrnId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PoId") + .HasColumnType("integer"); + + b.Property("PostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PurchaseInvoiceId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("GrnId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("PoId"); + + b.HasIndex("PurchaseInvoiceId"); + + b.HasIndex("Status"); + + b.HasIndex("VendorId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("grns", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLine", b => + { + b.Property("GrnLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("GrnLineId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("DiscountPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("GrnId") + .HasColumnType("integer"); + + b.Property("HoldStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("NetUnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("PoLineId") + .HasColumnType("integer"); + + b.Property("PoUnitPrice") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReceivedValue") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("VatAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("VatPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.HasKey("GrnLineId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("GrnId"); + + b.HasIndex("ItemId"); + + b.HasIndex("PoLineId"); + + b.ToTable("grn_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLineWarrantyNumber", b => + { + b.Property("GrnLineWarrantyNumberId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("GrnLineWarrantyNumberId")); + + b.Property("GrnLineId") + .HasColumnType("integer"); + + b.Property("WarrantyNo") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("WarrantyPeriodMonths") + .HasColumnType("integer"); + + b.HasKey("GrnLineWarrantyNumberId"); + + b.HasIndex("GrnLineId", "WarrantyNo") + .IsUnique(); + + b.ToTable("grn_line_warranty_numbers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.HrDocumentType", b => + { + b.Property("HrDocumentTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("HrDocumentTypeId")); + + b.Property("Category") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpiryTracked") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RequiredAtOnboarding") + .HasColumnType("boolean"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("HrDocumentTypeId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_document_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Item", b => + { + b.Property("ItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ItemId")); + + b.Property("BaseUomId") + .HasColumnType("integer"); + + b.Property("BrandId") + .HasColumnType("integer"); + + b.Property("CategoryId") + .HasColumnType("integer"); + + b.Property("ContentBaseQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ContentBaseUnit") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ContentQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ContentUnit") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DefaultVendorId") + .HasColumnType("integer"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SellingFlatPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SellingMaxPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SellingMinPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Sku") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("StockNature") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("SubCategoryId") + .HasColumnType("integer"); + + b.Property("TaxRateId") + .HasColumnType("integer"); + + b.Property("TrackingMode") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Warranty") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("NonWarranty"); + + b.Property("WarrantyPeriodMonths") + .HasColumnType("integer"); + + b.HasKey("ItemId"); + + b.HasIndex("BaseUomId"); + + b.HasIndex("BrandId"); + + b.HasIndex("CategoryId"); + + b.HasIndex("DefaultVendorId"); + + b.HasIndex("Sku") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("SubCategoryId"); + + b.HasIndex("TaxRateId"); + + b.ToTable("items", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ItemReorder", b => + { + b.Property("ReorderId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReorderId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("ReorderPoint") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReorderQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("ReorderId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("ItemId", "WarehouseId") + .IsUnique(); + + b.ToTable("item_reorders", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ItemType", b => + { + b.Property("ItemTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ItemTypeId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsMeasurable") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("ItemTypeId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("item_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.JournalEntryStub", b => + { + b.Property("JournalId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("JournalId")); + + b.Property("Amount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CreditAccount") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("DebitAccount") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("SourceDocId") + .HasColumnType("integer"); + + b.Property("SourceDocType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.HasKey("JournalId"); + + b.HasIndex("SourceDocType", "SourceDocId"); + + b.ToTable("journal_entry_stubs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveBalance", b => + { + b.Property("LeaveBalanceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LeaveBalanceId")); + + b.Property("AdjustmentDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("CarriedForwardDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("EntitledDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("LeaveTypeId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("TakenDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Year") + .HasColumnType("integer"); + + b.HasKey("LeaveBalanceId"); + + b.HasIndex("LeaveTypeId"); + + b.HasIndex("EmployeeId", "LeaveTypeId", "Year") + .IsUnique(); + + b.ToTable("hr_leave_balances", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveRequest", b => + { + b.Property("LeaveRequestId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LeaveRequestId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DaysCount") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("EndDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LeaveTypeId") + .HasColumnType("integer"); + + b.Property("Reason") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("RejectionReason") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("StartDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("LeaveRequestId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("EmployeeId"); + + b.HasIndex("LeaveTypeId"); + + b.HasIndex("Status"); + + b.HasIndex("StartDate", "EndDate"); + + b.ToTable("hr_leave_requests", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveType", b => + { + b.Property("LeaveTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LeaveTypeId")); + + b.Property("AccrualPerYear") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("CarryForwardAllowed") + .HasColumnType("boolean"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CountsAsNoPay") + .HasColumnType("boolean"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsPaid") + .HasColumnType("boolean"); + + b.Property("MaxCarryForwardDays") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RequiresApproval") + .HasColumnType("boolean"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("LeaveTypeId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_leave_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoanInstallment", b => + { + b.Property("LoanInstallmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LoanInstallmentId")); + + b.Property("DueMonth") + .HasColumnType("integer"); + + b.Property("DueYear") + .HasColumnType("integer"); + + b.Property("EmployeeLoanId") + .HasColumnType("integer"); + + b.Property("InstallmentNumber") + .HasColumnType("integer"); + + b.Property("PaidAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("PayrollRunId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("ScheduledAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("LoanInstallmentId"); + + b.HasIndex("EmployeeLoanId"); + + b.HasIndex("PayrollRunId"); + + b.HasIndex("DueYear", "DueMonth"); + + b.ToTable("hr_loan_installments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoginActivity", b => + { + b.Property("LoginActivityId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LoginActivityId")); + + b.Property("DeviceLabel") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("IpAddress") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("LoginAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserAgent") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("LoginActivityId"); + + b.HasIndex("UserId", "LoginAt"); + + b.ToTable("login_activities", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NavItem", b => + { + b.Property("NavItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NavItemId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Href") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Icon") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.HasKey("NavItemId"); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("nav_items", (string)null); + + b.HasData( + new + { + NavItemId = 1, + Code = "dashboard", + Href = "/dashboard", + Label = "Dashboard", + SortOrder = 1, + Status = "Active" + }, + new + { + NavItemId = 2, + Code = "products", + Href = "/dashboard/products", + Label = "Products", + SortOrder = 2, + Status = "Active" + }, + new + { + NavItemId = 4, + Code = "procurement", + Href = "/dashboard/procurement", + Label = "Procurement", + SortOrder = 4, + Status = "Active" + }, + new + { + NavItemId = 5, + Code = "receiving", + Href = "/dashboard/receiving/grn", + Label = "Receiving", + SortOrder = 5, + Status = "Active" + }, + new + { + NavItemId = 6, + Code = "stock", + Href = "/dashboard/stock", + Label = "Stock", + SortOrder = 6, + Status = "Active" + }, + new + { + NavItemId = 7, + Code = "warehouses", + Href = "/dashboard/warehouse", + Label = "Warehouses", + SortOrder = 7, + Status = "Active" + }, + new + { + NavItemId = 8, + Code = "orders", + Href = "/dashboard/orders", + Label = "Orders", + SortOrder = 8, + Status = "Active" + }, + new + { + NavItemId = 9, + Code = "settings", + Href = "/dashboard/settings", + Label = "Settings", + SortOrder = 9, + Status = "Active" + }, + new + { + NavItemId = 10, + Code = "help", + Href = "/dashboard/help", + Label = "Help", + SortOrder = 10, + Status = "Active" + }, + new + { + NavItemId = 11, + Code = "ledgers", + Href = "/dashboard/ledgers", + Label = "Ledgers", + SortOrder = 11, + Status = "Active" + }, + new + { + NavItemId = 12, + Code = "accounts", + Href = "/dashboard/accounts", + Label = "Accounts", + SortOrder = 12, + Status = "Active" + }, + new + { + NavItemId = 13, + Code = "sales", + Href = "/dashboard/sales", + Label = "Sales", + SortOrder = 13, + Status = "Active" + }, + new + { + NavItemId = 14, + Code = "production", + Href = "/dashboard/production", + Label = "Production", + SortOrder = 14, + Status = "Active" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Notification", b => + { + b.Property("NotificationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NotificationId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("ModuleKey") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("RelatedEntityId") + .HasColumnType("integer"); + + b.Property("RelatedEntityType") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.HasKey("NotificationId"); + + b.HasIndex("CreatedAt"); + + b.ToTable("notifications", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => + { + b.Property("NotificationConfigId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.HasKey("NotificationConfigId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("notification_config", null, t => + { + t.HasCheckConstraint("ck_notification_config_singleton", "\"NotificationConfigId\" = 1"); + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfigModule", b => + { + b.Property("NotificationConfigModuleId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NotificationConfigModuleId")); + + b.Property("EmailEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("InAppEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("ModuleKey") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("NotificationConfigId") + .HasColumnType("integer"); + + b.Property("SmsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.HasKey("NotificationConfigModuleId"); + + b.HasIndex("ModuleKey") + .IsUnique(); + + b.HasIndex("NotificationConfigId"); + + b.ToTable("notification_config_modules", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationRecipient", b => + { + b.Property("NotificationRecipientId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NotificationRecipientId")); + + b.Property("IsRead") + .HasColumnType("boolean"); + + b.Property("NotificationId") + .HasColumnType("integer"); + + b.Property("ReadAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("NotificationRecipientId"); + + b.HasIndex("NotificationId"); + + b.HasIndex("UserId", "IsRead", "NotificationId"); + + b.ToTable("notification_recipients", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NumberSequence", b => + { + b.Property("SequenceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SequenceId")); + + b.Property("DocType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("doc_type"); + + b.Property("LastNumber") + .HasColumnType("integer") + .HasColumnName("last_number"); + + b.Property("Year") + .HasColumnType("integer") + .HasColumnName("year"); + + b.HasKey("SequenceId"); + + b.HasIndex("DocType", "Year") + .IsUnique(); + + b.ToTable("number_sequences", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => + { + b.Property("PayrollLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollLineId")); + + b.Property("AbsentDays") + .HasColumnType("integer"); + + b.Property("BasicSalary") + .HasColumnType("numeric(18,2)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("EpfEmployeeAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("EpfEmployerAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("EtfEmployerAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("GrossSalary") + .HasColumnType("numeric(18,2)"); + + b.Property("LateDeductionAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("LateMinutesTotal") + .HasColumnType("integer"); + + b.Property("LeaveDays") + .HasColumnType("integer"); + + b.Property("LoanDeductionAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("NetSalary") + .HasColumnType("numeric(18,2)"); + + b.Property("NoPayAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("OtMinutesTotal") + .HasColumnType("integer"); + + b.Property("OtherDeductionsAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("OvertimeAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("PayrollRunId") + .HasColumnType("integer"); + + b.Property("PresentDays") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("TaxAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("TotalAllowances") + .HasColumnType("numeric(18,2)"); + + b.Property("WorkingDays") + .HasColumnType("integer"); + + b.HasKey("PayrollLineId"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("PayrollRunId", "EmployeeId") + .IsUnique(); + + b.ToTable("hr_payroll_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLineComponent", b => + { + b.Property("PayrollLineComponentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollLineComponentId")); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("ComponentCategory") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("PayrollLineId") + .HasColumnType("integer"); + + b.Property("SalaryComponentId") + .HasColumnType("integer"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.HasKey("PayrollLineComponentId"); + + b.HasIndex("PayrollLineId"); + + b.HasIndex("SalaryComponentId"); + + b.ToTable("hr_payroll_line_components", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollRun", b => + { + b.Property("PayrollRunId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollRunId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GeneratedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GeneratedBy") + .HasColumnType("integer"); + + b.Property("LockedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("LockedBy") + .HasColumnType("integer"); + + b.Property("PeriodMonth") + .HasColumnType("integer"); + + b.Property("PeriodYear") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UnlockReason") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("UnlockedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UnlockedBy") + .HasColumnType("integer"); + + b.HasKey("PayrollRunId"); + + b.HasIndex("BranchId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("PeriodYear", "PeriodMonth", "BranchId"); + + b.ToTable("hr_payroll_runs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollStatutorySetting", b => + { + b.Property("PayrollStatutorySettingId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollStatutorySettingId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveTo") + .HasColumnType("timestamp with time zone"); + + b.Property("EpfEmployeeRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("EpfEmployerRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("EtfEmployerRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("OtMultiplierDefault") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.HasKey("PayrollStatutorySettingId"); + + b.HasIndex("EffectiveFrom"); + + b.ToTable("hr_payroll_statutory_settings", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Payslip", b => + { + b.Property("PayslipId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayslipId")); + + b.Property("GeneratedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PayrollLineId") + .HasColumnType("integer"); + + b.Property("ReleasedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReleasedBy") + .HasColumnType("integer"); + + b.HasKey("PayslipId"); + + b.HasIndex("PayrollLineId") + .IsUnique(); + + b.ToTable("hr_payslips", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Permission", b => + { + b.Property("PermissionId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PermissionId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(80) + .HasColumnType("character varying(80)"); + + b.Property("NavItemId") + .HasColumnType("integer"); + + b.Property("SubNavItemId") + .HasColumnType("integer"); + + b.HasKey("PermissionId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("NavItemId"); + + b.HasIndex("SubNavItemId"); + + b.ToTable("permissions", (string)null); + + b.HasData( + new + { + PermissionId = 1, + Code = "NAV:dashboard", + NavItemId = 1 + }, + new + { + PermissionId = 2, + Code = "NAV:products", + NavItemId = 2 + }, + new + { + PermissionId = 3, + Code = "NAV:procurement.vendors", + SubNavItemId = 30 + }, + new + { + PermissionId = 4, + Code = "NAV:procurement", + NavItemId = 4 + }, + new + { + PermissionId = 5, + Code = "NAV:receiving", + NavItemId = 5 + }, + new + { + PermissionId = 6, + Code = "NAV:stock", + NavItemId = 6 + }, + new + { + PermissionId = 7, + Code = "NAV:warehouses", + NavItemId = 7 + }, + new + { + PermissionId = 8, + Code = "NAV:orders", + NavItemId = 8 + }, + new + { + PermissionId = 9, + Code = "NAV:settings", + NavItemId = 9 + }, + new + { + PermissionId = 10, + Code = "NAV:help", + NavItemId = 10 + }, + new + { + PermissionId = 11, + Code = "NAV:products.item", + SubNavItemId = 1 + }, + new + { + PermissionId = 12, + Code = "NAV:products.category", + SubNavItemId = 2 + }, + new + { + PermissionId = 13, + Code = "NAV:products.brand", + SubNavItemId = 3 + }, + new + { + PermissionId = 14, + Code = "NAV:products.item-type", + SubNavItemId = 4 + }, + new + { + PermissionId = 15, + Code = "NAV:products.uom", + SubNavItemId = 5 + }, + new + { + PermissionId = 16, + Code = "NAV:products.configuration", + SubNavItemId = 6 + }, + new + { + PermissionId = 17, + Code = "NAV:settings.roles", + SubNavItemId = 7 + }, + new + { + PermissionId = 18, + Code = "NAV:settings.users", + SubNavItemId = 8 + }, + new + { + PermissionId = 28, + Code = "NAV:procurement.requisitions", + SubNavItemId = 17 + }, + new + { + PermissionId = 29, + Code = "NAV:procurement.rfqs", + SubNavItemId = 18 + }, + new + { + PermissionId = 30, + Code = "NAV:procurement.purchase-orders", + SubNavItemId = 19 + }, + new + { + PermissionId = 31, + Code = "NAV:procurement.purchase-returns", + SubNavItemId = 20 + }, + new + { + PermissionId = 19, + Code = "NAV:ledgers", + NavItemId = 11 + }, + new + { + PermissionId = 20, + Code = "NAV:ledgers.trial-balance", + SubNavItemId = 9 + }, + new + { + PermissionId = 21, + Code = "NAV:ledgers.balance-sheet", + SubNavItemId = 10 + }, + new + { + PermissionId = 22, + Code = "NAV:ledgers.general-ledger", + SubNavItemId = 11 + }, + new + { + PermissionId = 23, + Code = "NAV:ledgers.profit-and-loss", + SubNavItemId = 12 + }, + new + { + PermissionId = 24, + Code = "NAV:ledgers.cash-flow", + SubNavItemId = 13 + }, + new + { + PermissionId = 25, + Code = "NAV:ledgers.budget-vs-actual", + SubNavItemId = 14 + }, + new + { + PermissionId = 27, + Code = "NAV:ledgers.tax-report", + SubNavItemId = 16 + }, + new + { + PermissionId = 26, + Code = "NAV:accounts.bank-accounts", + SubNavItemId = 15 + }, + new + { + PermissionId = 32, + Code = "NAV:accounts", + NavItemId = 12 + }, + new + { + PermissionId = 33, + Code = "NAV:accounts.cheque-books", + SubNavItemId = 21 + }, + new + { + PermissionId = 34, + Code = "NAV:accounts.received-cheques", + SubNavItemId = 22 + }, + new + { + PermissionId = 35, + Code = "NAV:production", + NavItemId = 14 + }, + new + { + PermissionId = 36, + Code = "NAV:production.templates", + SubNavItemId = 27 + }, + new + { + PermissionId = 37, + Code = "NAV:production.runs", + SubNavItemId = 25 + }, + new + { + PermissionId = 38, + Code = "NAV:production.produced", + SubNavItemId = 26 + }, + new + { + PermissionId = 39, + Code = "NAV:procurement.purchase-invoices", + SubNavItemId = 28 + }, + new + { + PermissionId = 40, + Code = "NAV:settings.branches", + SubNavItemId = 29 + }, + new + { + PermissionId = 41, + Code = "NAV:stock.ledger", + SubNavItemId = 31 + }, + new + { + PermissionId = 42, + Code = "NAV:stock.enquiry", + SubNavItemId = 32 + }, + new + { + PermissionId = 43, + Code = "NAV:stock.valuation", + SubNavItemId = 33 + }, + new + { + PermissionId = 44, + Code = "NAV:stock.transfers", + SubNavItemId = 34 + }, + new + { + PermissionId = 45, + Code = "NAV:stock.adjustments", + SubNavItemId = 35 + }, + new + { + PermissionId = 46, + Code = "NAV:stock.counts", + SubNavItemId = 36 + }, + new + { + PermissionId = 47, + Code = "NAV:stock.reorder-alerts", + SubNavItemId = 37 + }, + new + { + PermissionId = 48, + Code = "NAV:stock.wastage", + SubNavItemId = 38 + }, + new + { + PermissionId = 49, + Code = "NAV:sales.bundle-templates", + SubNavItemId = 23 + }, + new + { + PermissionId = 50, + Code = "NAV:sales.invoices", + SubNavItemId = 40 + }, + new + { + PermissionId = 51, + Code = "NAV:sales.free-issues", + SubNavItemId = 41 + }, + new + { + PermissionId = 52, + Code = "NAV:sales.day-end", + SubNavItemId = 42 + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PoLine", b => + { + b.Property("PoLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PoLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("PoId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyReceived") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Tax") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("PoLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("PoId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("po_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductConfig", b => + { + b.Property("ConfigId") + .HasColumnType("integer"); + + b.Property("BatchListsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("BrandsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("ItemTypesEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SellingPricesEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("SerialNumbersEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("SubcategoriesEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.Property("WarrantyPeriodsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.HasKey("ConfigId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("product_config", null, t => + { + t.HasCheckConstraint("ck_product_config_singleton", "\"ConfigId\" = 1"); + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b => + { + b.Property("RunId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunId")); + + b.Property("CancelReasonCodeId") + .HasColumnType("integer"); + + b.Property("CompletedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("OutputBinId") + .HasColumnType("integer"); + + b.Property("ReworkCount") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("ScaleFactor") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("TargetQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TemplateId") + .HasColumnType("integer"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("RunId"); + + b.HasIndex("CancelReasonCodeId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("OutputBinId"); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("TemplateId", "Status"); + + b.ToTable("production_runs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionTemplate", b => + { + b.Property("TemplateId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TemplateId")); + + b.Property("Annotations") + .HasColumnType("jsonb"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("TemplateId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("CreatedBy"); + + b.HasIndex("Status"); + + b.ToTable("production_templates", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", b => + { + b.Property("PurchaseInvoiceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PurchaseInvoiceId")); + + b.Property("BalanceAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VatTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.Property("VendorInvoiceDate") + .HasColumnType("timestamp with time zone"); + + b.Property("VendorInvoiceNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("VendorSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("VendorSnapshotTaxNo") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("PurchaseInvoiceId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("VendorId"); + + b.HasIndex("VendorId", "VendorInvoiceNo"); + + b.ToTable("purchase_invoices", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoiceLine", b => + { + b.Property("PurchaseInvoiceLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PurchaseInvoiceLineId")); + + b.Property("GrnId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PurchaseInvoiceId") + .HasColumnType("integer"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("VatTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("PurchaseInvoiceLineId"); + + b.HasIndex("GrnId") + .IsUnique(); + + b.HasIndex("PurchaseInvoiceId"); + + b.ToTable("purchase_invoice_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoicePayment", b => + { + b.Property("PurchaseInvoicePaymentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PurchaseInvoicePaymentId")); + + b.Property("Amount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BankAccountName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("GlBankAccountId") + .HasColumnType("bigint"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PaymentDate") + .HasColumnType("timestamp with time zone"); + + b.Property("PurchaseInvoiceId") + .HasColumnType("integer"); + + b.Property("Reference") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("PurchaseInvoicePaymentId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("PurchaseInvoiceId"); + + b.ToTable("purchase_invoice_payments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => + { + b.Property("PoId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PoId")); + + b.Property("ApprovalRequired") + .HasColumnType("boolean"); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("ApproverUserId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RequisitionId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.HasKey("PoId"); + + b.HasIndex("ApproverUserId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("RequisitionId"); + + b.HasIndex("Status"); + + b.HasIndex("VendorId"); + + b.ToTable("purchase_orders", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturn", b => + { + b.Property("ReturnId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReasonCodeId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("ReturnId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("ReasonCodeId"); + + b.HasIndex("VendorId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("purchase_returns", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturnLine", b => + { + b.Property("ReturnLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnLineId")); + + b.Property("GrnLineId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReturnId") + .HasColumnType("integer"); + + b.HasKey("ReturnLineId"); + + b.HasIndex("GrnLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("ReturnId"); + + b.ToTable("purchase_return_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ReasonCode", b => + { + b.Property("ReasonCodeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReasonCodeId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Context") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.HasKey("ReasonCodeId"); + + b.HasIndex("Context", "Code") + .IsUnique(); + + b.ToTable("reason_codes", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => + { + b.Property("RequisitionId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RequisitionId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RequestedBy") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("RequisitionId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("RequestedBy"); + + b.HasIndex("Status"); + + b.ToTable("requisitions", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RequisitionLine", b => + { + b.Property("ReqLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReqLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RequiredBy") + .HasColumnType("date"); + + b.Property("RequisitionId") + .HasColumnType("integer"); + + b.HasKey("ReqLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RequisitionId"); + + b.ToTable("requisition_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => + { + b.Property("RfqId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RfqId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RequisitionId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("RfqId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("RequisitionId"); + + b.ToTable("rfqs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RfqLine", b => + { + b.Property("RfqLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RfqLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RfqId") + .HasColumnType("integer"); + + b.HasKey("RfqLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RfqId"); + + b.ToTable("rfq_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Role", b => + { + b.Property("RoleId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RoleId")); + + b.Property("AuthRoleId") + .HasColumnType("uuid") + .HasColumnName("auth_role_id"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsSystemRole") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("RoleId"); + + b.HasIndex("AuthRoleId") + .IsUnique(); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("roles", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RolePermission", b => + { + b.Property("RoleId") + .HasColumnType("integer"); + + b.Property("PermissionId") + .HasColumnType("integer"); + + b.Property("Actions") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(31); + + b.HasKey("RoleId", "PermissionId"); + + b.HasIndex("PermissionId"); + + b.ToTable("role_permissions", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunEdge", b => + { + b.Property("RunEdgeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunEdgeId")); + + b.Property("ChildRunStageId") + .HasColumnType("integer"); + + b.Property("ParentRunStageId") + .HasColumnType("integer"); + + b.Property("RunId") + .HasColumnType("integer"); + + b.HasKey("RunEdgeId"); + + b.HasIndex("ChildRunStageId"); + + b.HasIndex("RunId"); + + b.HasIndex("ParentRunStageId", "ChildRunStageId") + .IsUnique(); + + b.ToTable("run_edges", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStage", b => + { + b.Property("RunStageId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunStageId")); + + b.Property("ActualEndAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ActualStartAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EstimatedMinutes") + .HasColumnType("integer"); + + b.Property("FieldDefs") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("FieldValues") + .HasColumnType("jsonb"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("PosX") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PosY") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RoleLabel") + .HasMaxLength(60) + .HasColumnType("character varying(60)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("RunId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("TemplateStageId") + .HasColumnType("integer"); + + b.HasKey("RunStageId"); + + b.HasIndex("TemplateStageId"); + + b.HasIndex("RunId", "Status"); + + b.ToTable("run_stages", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageEvent", b => + { + b.Property("EventId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EventId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Note") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Payload") + .HasColumnType("jsonb"); + + b.Property("RunId") + .HasColumnType("integer"); + + b.Property("RunStageId") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("EventId"); + + b.HasIndex("RunStageId"); + + b.HasIndex("UserId"); + + b.HasIndex("RunId", "EventId"); + + b.ToTable("run_stage_events", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageInput", b => + { + b.Property("RunInputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunInputId")); + + b.Property("ConsumedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ConsumedValue") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DeliveredQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("FromRunOutputId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("PlannedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyUnit") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ReturnedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReturnedValue") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RunStageId") + .HasColumnType("integer"); + + b.Property("Source") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("RunInputId"); + + b.HasIndex("FromRunOutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RunStageId"); + + b.ToTable("run_stage_inputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageOutput", b => + { + b.Property("RunOutputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunOutputId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("PlannedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ProducedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RunStageId") + .HasColumnType("integer"); + + b.Property("ScrapReasonCodeId") + .HasColumnType("integer"); + + b.Property("ScrappedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TransferredQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UomId") + .HasColumnType("integer"); + + b.HasKey("RunOutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RunStageId"); + + b.HasIndex("ScrapReasonCodeId"); + + b.HasIndex("UomId"); + + b.ToTable("run_stage_outputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalaryComponent", b => + { + b.Property("SalaryComponentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalaryComponentId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ComponentType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsEpfEtfApplicable") + .HasColumnType("boolean"); + + b.Property("IsTaxable") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("SalaryComponentId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_salary_components", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesDayEnd", b => + { + b.Property("SalesDayEndId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesDayEndId")); + + b.Property("BalanceTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BundleCount") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("BusinessDate") + .HasColumnType("date"); + + b.Property("CashierUserId") + .HasColumnType("integer"); + + b.Property("ClosedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ClosedBy") + .HasColumnType("integer"); + + b.Property("CostOfGoodsSold") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SlipCount") + .HasColumnType("integer"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("SalesDayEndId"); + + b.HasIndex("ClosedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("CashierUserId", "BusinessDate") + .IsUnique(); + + b.ToTable("sales_day_ends", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoice", b => + { + b.Property("SalesInvoiceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesInvoiceId")); + + b.Property("BalanceAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("CreatorUserId") + .HasColumnType("integer"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("CustomerSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CustomerSnapshotTaxNo") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("InvoiceDate") + .HasColumnType("timestamp with time zone"); + + b.Property("InvoiceNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("InvoiceType") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("B2C"); + + b.Property("NetPayable") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RoundOff") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesInvoiceId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatorUserId"); + + b.HasIndex("CustomerId"); + + b.HasIndex("InvoiceDate"); + + b.HasIndex("InvoiceNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_invoices", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoiceLine", b => + { + b.Property("SalesInvoiceLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesInvoiceLineId")); + + b.Property("BaseCost") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DiscountAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DiscountMode") + .HasColumnType("integer"); + + b.Property("DiscountPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("FreeQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("IsFreeIssue") + .HasColumnType("boolean"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("NetUnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ParentLineId") + .HasColumnType("integer"); + + b.Property("PriceSource") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SalesInvoiceId") + .HasColumnType("integer"); + + b.Property("TaxAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesInvoiceLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SalesInvoiceId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_invoice_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoicePayment", b => + { + b.Property("SalesInvoicePaymentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesInvoicePaymentId")); + + b.Property("Amount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BankAccountName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("GlBankAccountId") + .HasColumnType("bigint"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PaymentDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Reference") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("SalesInvoiceId") + .HasColumnType("integer"); + + b.HasKey("SalesInvoicePaymentId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("SalesInvoiceId"); + + b.ToTable("sales_invoice_payments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturn", b => + { + b.Property("ReturnId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReasonCodeId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("ReturnId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("CustomerId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("ReasonCodeId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_returns", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturnLine", b => + { + b.Property("ReturnLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReturnId") + .HasColumnType("integer"); + + b.Property("SalesInvoiceLineId") + .HasColumnType("integer"); + + b.HasKey("ReturnLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("ReturnId"); + + b.HasIndex("SalesInvoiceLineId"); + + b.ToTable("sales_return_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlip", b => + { + b.Property("SalesSlipId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesSlipId")); + + b.Property("BalanceAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CashierUserId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("CustomerSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DayEndId") + .HasColumnType("integer"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SlipDate") + .HasColumnType("timestamp with time zone"); + + b.Property("SlipNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesSlipId"); + + b.HasIndex("CashierUserId"); + + b.HasIndex("CustomerId"); + + b.HasIndex("DayEndId"); + + b.HasIndex("SlipDate"); + + b.HasIndex("SlipNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_slips", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlipLine", b => + { + b.Property("SalesSlipLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesSlipLineId")); + + b.Property("BaseCost") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DiscountAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DiscountMode") + .HasColumnType("integer"); + + b.Property("DiscountPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("FreeQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("IsFreeIssue") + .HasColumnType("boolean"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("NetUnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ParentLineId") + .HasColumnType("integer"); + + b.Property("PriceSource") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SalesSlipId") + .HasColumnType("integer"); + + b.Property("TaxAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesSlipLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SalesSlipId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_slip_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Serial", b => + { + b.Property("SerialId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SerialId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("SerialNo") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("SerialId"); + + b.HasIndex("ItemId", "SerialNo") + .IsUnique(); + + b.ToTable("serials", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageEdge", b => + { + b.Property("EdgeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EdgeId")); + + b.Property("ChildStageId") + .HasColumnType("integer"); + + b.Property("ParentStageId") + .HasColumnType("integer"); + + b.Property("TemplateId") + .HasColumnType("integer"); + + b.HasKey("EdgeId"); + + b.HasIndex("ChildStageId"); + + b.HasIndex("TemplateId"); + + b.HasIndex("ParentStageId", "ChildStageId") + .IsUnique(); + + b.ToTable("stage_edges", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageInput", b => + { + b.Property("InputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("InputId")); + + b.Property("FromOutputId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyPerBatch") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyUnit") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Source") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("StageId") + .HasColumnType("integer"); + + b.HasKey("InputId"); + + b.HasIndex("FromOutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("StageId"); + + b.ToTable("stage_inputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageOutput", b => + { + b.Property("OutputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("OutputId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("QtyPerBatch") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("StageId") + .HasColumnType("integer"); + + b.Property("UomId") + .HasColumnType("integer"); + + b.HasKey("OutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("StageId"); + + b.HasIndex("UomId"); + + b.ToTable("stage_outputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustment", b => + { + b.Property("AdjustmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AdjustmentId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReasonCodeId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("AdjustmentId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("ReasonCodeId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("stock_adjustments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustmentLine", b => + { + b.Property("AdjLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AdjLineId")); + + b.Property("AdjustmentId") + .HasColumnType("integer"); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyDelta") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.HasKey("AdjLineId"); + + b.HasIndex("AdjustmentId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SerialId"); + + b.ToTable("stock_adjustment_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCount", b => + { + b.Property("CountId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CountId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CountType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("CountId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("stock_counts", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCountLine", b => + { + b.Property("CountLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CountLineId")); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("CountId") + .HasColumnType("integer"); + + b.Property("CountedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("SystemQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Variance") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("CountLineId"); + + b.HasIndex("BinId"); + + b.HasIndex("CountId"); + + b.HasIndex("ItemId"); + + b.ToTable("stock_count_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLayer", b => + { + b.Property("LayerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LayerId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("GrnLineId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyReceived") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyRemaining") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReceiptDate") + .HasColumnType("timestamp with time zone"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("LayerId"); + + b.HasIndex("BatchId"); + + b.HasIndex("GrnLineId"); + + b.HasIndex("SerialId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("ItemId", "WarehouseId", "ReceiptDate", "LayerId"); + + b.ToTable("stock_layers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLedger", b => + { + b.Property("LedgerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LedgerId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Direction") + .IsRequired() + .HasMaxLength(5) + .HasColumnType("character varying(5)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyBase") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RunningBalance") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("SourceDocId") + .HasColumnType("integer"); + + b.Property("SourceDocType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.Property("Value") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("LedgerId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("SerialId"); + + b.HasIndex("UserId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("SourceDocType", "SourceDocId"); + + b.HasIndex("ItemId", "WarehouseId", "CreatedAt"); + + b.HasIndex("ItemId", "WarehouseId", "LedgerId"); + + b.ToTable("stock_ledger", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransfer", b => + { + b.Property("TransferId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TransferId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DestWarehouseId") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SrcWarehouseId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("TransferId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DestWarehouseId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("SrcWarehouseId"); + + b.HasIndex("Status"); + + b.ToTable("stock_transfers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransferLine", b => + { + b.Property("TransferLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TransferLineId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("DestBinId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyReceived") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("SrcBinId") + .HasColumnType("integer"); + + b.Property("TransferId") + .HasColumnType("integer"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.HasKey("TransferLineId"); + + b.HasIndex("BatchId"); + + b.HasIndex("DestBinId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SerialId"); + + b.HasIndex("SrcBinId"); + + b.HasIndex("TransferId"); + + b.ToTable("stock_transfer_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubCategory", b => + { + b.Property("SubCategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SubCategoryId")); + + b.Property("CategoryId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("SubCategoryId"); + + b.HasIndex("Status"); + + b.HasIndex("CategoryId", "Name") + .IsUnique(); + + b.ToTable("subcategories", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubNavItem", b => + { + b.Property("SubNavItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SubNavItemId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Href") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Icon") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("NavItemId") + .HasColumnType("integer"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.HasKey("SubNavItemId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("NavItemId"); + + b.ToTable("sub_nav_items", (string)null); + + b.HasData( + new + { + SubNavItemId = 1, + Code = "products.item", + Href = "/dashboard/products", + Label = "Item", + NavItemId = 2, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 2, + Code = "products.category", + Href = "/dashboard/products/categories", + Label = "Category", + NavItemId = 2, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 3, + Code = "products.brand", + Href = "/dashboard/products/brands", + Label = "Brand", + NavItemId = 2, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 4, + Code = "products.item-type", + Href = "/dashboard/products/item-types", + Label = "Item Type", + NavItemId = 2, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 5, + Code = "products.uom", + Href = "/dashboard/products/uoms", + Label = "UOM", + NavItemId = 2, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 6, + Code = "products.configuration", + Href = "/dashboard/products/settings", + Label = "Configuration", + NavItemId = 2, + SortOrder = 6, + Status = "Active" + }, + new + { + SubNavItemId = 29, + Code = "settings.branches", + Href = "/dashboard/settings/branches", + Label = "Branches", + NavItemId = 9, + SortOrder = 0, + Status = "Active" + }, + new + { + SubNavItemId = 7, + Code = "settings.roles", + Href = "/dashboard/settings/roles", + Label = "Roles", + NavItemId = 9, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 8, + Code = "settings.users", + Href = "/dashboard/settings/users", + Label = "Users", + NavItemId = 9, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 24, + Code = "settings.notification-config", + Href = "/dashboard/settings/notification-config", + Label = "Notification Config", + NavItemId = 9, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 40, + Code = "sales.invoices", + Href = "/dashboard/sales/invoices", + Label = "Sales", + NavItemId = 13, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 23, + Code = "sales.bundle-templates", + Href = "/dashboard/sales/bundles/templates", + Label = "Bundle Templates", + NavItemId = 13, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 41, + Code = "sales.free-issues", + Href = "/dashboard/sales/free-issues", + Label = "Free Issues", + NavItemId = 13, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 42, + Code = "sales.day-end", + Href = "/dashboard/sales/day-end", + Label = "Day End", + NavItemId = 13, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 30, + Code = "procurement.vendors", + Href = "/dashboard/vendors", + Label = "Vendors", + NavItemId = 4, + SortOrder = 0, + Status = "Active" + }, + new + { + SubNavItemId = 17, + Code = "procurement.requisitions", + Href = "/dashboard/procurement/requisitions", + Label = "Requisitions", + NavItemId = 4, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 18, + Code = "procurement.rfqs", + Href = "/dashboard/procurement/rfqs", + Label = "RFQs", + NavItemId = 4, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 19, + Code = "procurement.purchase-orders", + Href = "/dashboard/procurement/purchase-orders", + Label = "Purchase Orders", + NavItemId = 4, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 20, + Code = "procurement.purchase-returns", + Href = "/dashboard/procurement/purchase-returns", + Label = "Purchase Returns", + NavItemId = 4, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 28, + Code = "procurement.purchase-invoices", + Href = "/dashboard/procurement/purchase-invoices", + Label = "Purchase Invoices", + NavItemId = 4, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 9, + Code = "ledgers.trial-balance", + Href = "/dashboard/ledgers/trial-balance", + Label = "Trial Balance", + NavItemId = 11, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 10, + Code = "ledgers.balance-sheet", + Href = "/dashboard/ledgers/balance-sheet", + Label = "Balance Sheet", + NavItemId = 11, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 11, + Code = "ledgers.general-ledger", + Href = "/dashboard/ledgers/general-ledger", + Label = "General Ledger", + NavItemId = 11, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 12, + Code = "ledgers.profit-and-loss", + Href = "/dashboard/ledgers/profit-and-loss", + Label = "Profit & Loss", + NavItemId = 11, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 13, + Code = "ledgers.cash-flow", + Href = "/dashboard/ledgers/cash-flow", + Label = "Cash Flow", + NavItemId = 11, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 14, + Code = "ledgers.budget-vs-actual", + Href = "/dashboard/ledgers/budget-vs-actual", + Label = "Budget vs Actual", + NavItemId = 11, + SortOrder = 6, + Status = "Active" + }, + new + { + SubNavItemId = 16, + Code = "ledgers.tax-report", + Href = "/dashboard/ledgers/tax-report", + Label = "Tax Report", + NavItemId = 11, + SortOrder = 7, + Status = "Active" + }, + new + { + SubNavItemId = 15, + Code = "accounts.bank-accounts", + Href = "/dashboard/accounts/bank-accounts", + Label = "Cash / Bank Accounts", + NavItemId = 12, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 21, + Code = "accounts.cheque-books", + Href = "/dashboard/accounts/cheque-books", + Label = "Cheque Books", + NavItemId = 12, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 22, + Code = "accounts.received-cheques", + Href = "/dashboard/accounts/received-cheques", + Label = "Received Cheques", + NavItemId = 12, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 27, + Code = "production.templates", + Href = "/dashboard/production/templates", + Label = "Templates", + NavItemId = 14, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 25, + Code = "production.runs", + Href = "/dashboard/production/runs", + Label = "Runs", + NavItemId = 14, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 26, + Code = "production.produced", + Href = "/dashboard/production/produced", + Label = "Produced", + NavItemId = 14, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 31, + Code = "stock.ledger", + Href = "/dashboard/stock/ledger", + Label = "Stock Ledger", + NavItemId = 6, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 32, + Code = "stock.enquiry", + Href = "/dashboard/stock/enquiry", + Label = "Stock Enquiry", + NavItemId = 6, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 33, + Code = "stock.valuation", + Href = "/dashboard/stock/valuation", + Label = "Valuation", + NavItemId = 6, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 34, + Code = "stock.transfers", + Href = "/dashboard/stock/transfers", + Label = "Transfers", + NavItemId = 6, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 35, + Code = "stock.adjustments", + Href = "/dashboard/stock/adjustments", + Label = "Adjustments", + NavItemId = 6, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 36, + Code = "stock.counts", + Href = "/dashboard/stock/counts", + Label = "Counts", + NavItemId = 6, + SortOrder = 6, + Status = "Active" + }, + new + { + SubNavItemId = 37, + Code = "stock.reorder-alerts", + Href = "/dashboard/stock/reorder-alerts", + Label = "Reorder Alerts", + NavItemId = 6, + SortOrder = 7, + Status = "Active" + }, + new + { + SubNavItemId = 38, + Code = "stock.wastage", + Href = "/dashboard/stock/wastage", + Label = "Wastage", + NavItemId = 6, + SortOrder = 8, + Status = "Active" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicket", b => + { + b.Property("TicketId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TicketId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Subject") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.HasKey("TicketId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("Status"); + + b.ToTable("support_tickets", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicketMessage", b => + { + b.Property("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("MessageId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsFromAdmin") + .HasColumnType("boolean"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("SenderUserId") + .HasColumnType("integer"); + + b.Property("TicketId") + .HasColumnType("integer"); + + b.HasKey("MessageId"); + + b.HasIndex("TicketId", "CreatedAt"); + + b.ToTable("support_ticket_messages", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TaxRate", b => + { + b.Property("TaxRateId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TaxRateId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Percentage") + .HasPrecision(5, 2) + .HasColumnType("numeric(5,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("TaxRateId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("tax_rates", (string)null); + + b.HasData( + new + { + TaxRateId = 1, + Code = "STANDARD", + CreatedAt = new DateTime(2026, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc), + Name = "Standard", + Percentage = 15m, + RowVersion = 0u, + Status = "Active" + }, + new + { + TaxRateId = 2, + Code = "ZERO", + CreatedAt = new DateTime(2026, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc), + Name = "Zero-Rated", + Percentage = 0m, + RowVersion = 0u, + Status = "Active" + }, + new + { + TaxRateId = 3, + Code = "EXEMPT", + CreatedAt = new DateTime(2026, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc), + Name = "Exempt", + Percentage = 0m, + RowVersion = 0u, + Status = "Active" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TaxSlab", b => + { + b.Property("TaxSlabId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TaxSlabId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveTo") + .HasColumnType("timestamp with time zone"); + + b.Property("LowerBound") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("Rate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("UpperBound") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.HasKey("TaxSlabId"); + + b.HasIndex("EffectiveFrom"); + + b.ToTable("hr_tax_slabs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => + { + b.Property("StageId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("StageId")); + + b.Property("EstimatedMinutes") + .HasColumnType("integer"); + + b.Property("FieldDefs") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("PosX") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PosY") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RoleLabel") + .HasMaxLength(60) + .HasColumnType("character varying(60)"); + + b.Property("TemplateId") + .HasColumnType("integer"); + + b.HasKey("StageId"); + + b.HasIndex("TemplateId"); + + b.ToTable("template_stages", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Uom", b => + { + b.Property("UomId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("UomId")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("UomId"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("uoms", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.User", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("UserId")); + + b.Property("AuthUserId") + .HasColumnType("uuid") + .HasColumnName("auth_user_id"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Email") + .HasMaxLength(320) + .HasColumnType("character varying(320)"); + + b.Property("RoleId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("UserId"); + + b.HasIndex("AuthUserId") + .IsUnique(); + + b.HasIndex("Email") + .IsUnique(); + + b.HasIndex("RoleId"); + + b.HasIndex("Username") + .IsUnique(); + + b.ToTable("users", (string)null); + + b.HasData( + new + { + UserId = 1, + DisplayName = "System", + Status = "Active", + Username = "system" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Vendor", b => + { + b.Property("VendorId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("VendorId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Currency") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(3) + .HasColumnType("character varying(3)") + .HasDefaultValue("LKR"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TaxReg") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Terms") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("VendorId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("vendors", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => + { + b.Property("QuotationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("QuotationId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("RfqId") + .HasColumnType("integer"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.HasKey("QuotationId"); + + b.HasIndex("VendorId"); + + b.HasIndex("RfqId", "VendorId") + .IsUnique(); + + b.ToTable("vendor_quotations", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotationLine", b => + { + b.Property("QuotationLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("QuotationLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LeadDays") + .HasColumnType("integer"); + + b.Property("QuotationId") + .HasColumnType("integer"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("QuotationLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("QuotationId"); + + b.ToTable("vendor_quotation_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Warehouse", b => + { + b.Property("WarehouseId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("WarehouseId")); + + b.Property("Address") + .HasColumnType("text"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Phone") + .HasColumnType("text"); + + b.HasKey("WarehouseId"); + + b.HasIndex("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("warehouses", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.WorkShift", b => + { + b.Property("WorkShiftId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("WorkShiftId")); + + b.Property("BreakMinutes") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EndTime") + .HasColumnType("interval"); + + b.Property("GraceMinutes") + .HasColumnType("integer"); + + b.Property("IsOvernight") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("OtMultiplier") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("StandardWorkingMinutes") + .HasColumnType("integer"); + + b.Property("StartTime") + .HasColumnType("interval"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WorkingDaysMask") + .HasColumnType("integer"); + + b.HasKey("WorkShiftId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_work_shifts", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceRecord", b => + { + b.HasOne("ERPCore.Domain.Entities.AttendanceUploadBatch", "AttendanceUploadBatch") + .WithMany() + .HasForeignKey("AttendanceUploadBatchId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.WorkShift", "WorkShift") + .WithMany() + .HasForeignKey("WorkShiftId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("AttendanceUploadBatch"); + + b.Navigation("Employee"); + + b.Navigation("WorkShift"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AuditLog", b => + { + b.HasOne("ERPCore.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Batch", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Bin", b => + { + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany("Bins") + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BranchConfig", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSale", b => + { + b.HasOne("ERPCore.Domain.Entities.BundleSaleTemplate", "BundleSaleTemplate") + .WithMany() + .HasForeignKey("BundleSaleTemplateId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "CashierUser") + .WithMany() + .HasForeignKey("CashierUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesDayEnd", "DayEnd") + .WithMany("BundleSales") + .HasForeignKey("DayEndId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BundleSaleTemplate"); + + b.Navigation("CashierUser"); + + b.Navigation("Customer"); + + b.Navigation("DayEnd"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleLine", b => + { + b.HasOne("ERPCore.Domain.Entities.BundleSale", "BundleSale") + .WithMany("Lines") + .HasForeignKey("BundleSaleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BundleSale"); + + b.Navigation("Item"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplateLine", b => + { + b.HasOne("ERPCore.Domain.Entities.BundleSaleTemplate", "BundleSaleTemplate") + .WithMany("Lines") + .HasForeignKey("BundleSaleTemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BundleSaleTemplate"); + + b.Navigation("Item"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Customer", b => + { + b.HasOne("ERPCore.Domain.Entities.Warehouse", "DefaultWarehouse") + .WithMany() + .HasForeignKey("DefaultWarehouseId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("DefaultWarehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Department", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Employee", "HeadEmployee") + .WithMany() + .HasForeignKey("HeadEmployeeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Department", "ParentDepartment") + .WithMany() + .HasForeignKey("ParentDepartmentId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Branch"); + + b.Navigation("HeadEmployee"); + + b.Navigation("ParentDepartment"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Employee", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Department", "Department") + .WithMany() + .HasForeignKey("DepartmentId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Designation", "Designation") + .WithMany() + .HasForeignKey("DesignationId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.EmploymentType", "EmploymentType") + .WithMany() + .HasForeignKey("EmploymentTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Employee", "ReportingManager") + .WithMany() + .HasForeignKey("ReportingManagerId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithOne() + .HasForeignKey("ERPCore.Domain.Entities.Employee", "UserId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.WorkShift", "WorkShift") + .WithMany() + .HasForeignKey("WorkShiftId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Department"); + + b.Navigation("Designation"); + + b.Navigation("EmploymentType"); + + b.Navigation("ReportingManager"); + + b.Navigation("User"); + + b.Navigation("WorkShift"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeBankDetail", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeDocument", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.HrDocumentType", "HrDocumentType") + .WithMany() + .HasForeignKey("HrDocumentTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("HrDocumentType"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeLoan", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructure", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructureLine", b => + { + b.HasOne("ERPCore.Domain.Entities.EmployeeSalaryStructure", "EmployeeSalaryStructure") + .WithMany("Lines") + .HasForeignKey("EmployeeSalaryStructureId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalaryComponent", "SalaryComponent") + .WithMany() + .HasForeignKey("SalaryComponentId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("EmployeeSalaryStructure"); + + b.Navigation("SalaryComponent"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Grn", 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.HasOne("ERPCore.Domain.Entities.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("PoId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.PurchaseInvoice", "PurchaseInvoice") + .WithMany() + .HasForeignKey("PurchaseInvoiceId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("PurchaseInvoice"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Vendor"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", "Batch") + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", "Bin") + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Grn", "Grn") + .WithMany("Lines") + .HasForeignKey("GrnId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PoLine", "PoLine") + .WithMany() + .HasForeignKey("PoLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Batch"); + + b.Navigation("Bin"); + + b.Navigation("Grn"); + + b.Navigation("Item"); + + b.Navigation("PoLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLineWarrantyNumber", b => + { + b.HasOne("ERPCore.Domain.Entities.GrnLine", "GrnLine") + .WithMany("WarrantyNumbers") + .HasForeignKey("GrnLineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GrnLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Item", b => + { + b.HasOne("ERPCore.Domain.Entities.Uom", "BaseUom") + .WithMany() + .HasForeignKey("BaseUomId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Brand", "Brand") + .WithMany() + .HasForeignKey("BrandId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Category", "Category") + .WithMany() + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "DefaultVendor") + .WithMany() + .HasForeignKey("DefaultVendorId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.SubCategory", "SubCategory") + .WithMany() + .HasForeignKey("SubCategoryId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.TaxRate", "TaxRate") + .WithMany() + .HasForeignKey("TaxRateId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("BaseUom"); + + b.Navigation("Brand"); + + b.Navigation("Category"); + + b.Navigation("DefaultVendor"); + + b.Navigation("SubCategory"); + + b.Navigation("TaxRate"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ItemReorder", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany("ReorderSettings") + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveBalance", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.LeaveType", "LeaveType") + .WithMany() + .HasForeignKey("LeaveTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("LeaveType"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveRequest", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.LeaveType", "LeaveType") + .WithMany() + .HasForeignKey("LeaveTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("LeaveType"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoanInstallment", b => + { + b.HasOne("ERPCore.Domain.Entities.EmployeeLoan", "EmployeeLoan") + .WithMany("Installments") + .HasForeignKey("EmployeeLoanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PayrollRun", "PayrollRun") + .WithMany() + .HasForeignKey("PayrollRunId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("EmployeeLoan"); + + b.Navigation("PayrollRun"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoginActivity", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfigModule", b => + { + b.HasOne("ERPCore.Domain.Entities.NotificationConfig", "NotificationConfig") + .WithMany("Modules") + .HasForeignKey("NotificationConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("NotificationConfig"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationRecipient", b => + { + b.HasOne("ERPCore.Domain.Entities.Notification", "Notification") + .WithMany("Recipients") + .HasForeignKey("NotificationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Notification"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PayrollRun", "PayrollRun") + .WithMany("Lines") + .HasForeignKey("PayrollRunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("PayrollRun"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLineComponent", b => + { + b.HasOne("ERPCore.Domain.Entities.PayrollLine", "PayrollLine") + .WithMany("Components") + .HasForeignKey("PayrollLineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalaryComponent", "SalaryComponent") + .WithMany() + .HasForeignKey("SalaryComponentId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("PayrollLine"); + + b.Navigation("SalaryComponent"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollRun", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Branch"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Payslip", b => + { + b.HasOne("ERPCore.Domain.Entities.PayrollLine", "PayrollLine") + .WithOne() + .HasForeignKey("ERPCore.Domain.Entities.Payslip", "PayrollLineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PayrollLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Permission", b => + { + b.HasOne("ERPCore.Domain.Entities.NavItem", "NavItem") + .WithMany() + .HasForeignKey("NavItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ERPCore.Domain.Entities.SubNavItem", "SubNavItem") + .WithMany() + .HasForeignKey("SubNavItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("NavItem"); + + b.Navigation("SubNavItem"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PoLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseOrder", "PurchaseOrder") + .WithMany("Lines") + .HasForeignKey("PoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductConfig", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b => + { + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "CancelReason") + .WithMany() + .HasForeignKey("CancelReasonCodeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Bin", "OutputBin") + .WithMany() + .HasForeignKey("OutputBinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") + .WithMany("Runs") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CancelReason"); + + b.Navigation("Creator"); + + b.Navigation("OutputBin"); + + b.Navigation("Template"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionTemplate", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoiceLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Grn", "Grn") + .WithMany() + .HasForeignKey("GrnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseInvoice", "PurchaseInvoice") + .WithMany("Lines") + .HasForeignKey("PurchaseInvoiceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Grn"); + + b.Navigation("PurchaseInvoice"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoicePayment", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseInvoice", "PurchaseInvoice") + .WithMany("Payments") + .HasForeignKey("PurchaseInvoiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("PurchaseInvoice"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Approver") + .WithMany() + .HasForeignKey("ApproverUserId"); + + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") + .WithMany() + .HasForeignKey("RequisitionId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Approver"); + + b.Navigation("Creator"); + + b.Navigation("Requisition"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturn", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ReasonCode") + .WithMany() + .HasForeignKey("ReasonCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("ReasonCode"); + + b.Navigation("Vendor"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturnLine", b => + { + b.HasOne("ERPCore.Domain.Entities.GrnLine", "GrnLine") + .WithMany() + .HasForeignKey("GrnLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseReturn", "Return") + .WithMany("Lines") + .HasForeignKey("ReturnId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GrnLine"); + + b.Navigation("Item"); + + b.Navigation("Return"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Requester") + .WithMany() + .HasForeignKey("RequestedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Requester"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RequisitionLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") + .WithMany("Lines") + .HasForeignKey("RequisitionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Requisition"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => + { + b.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") + .WithMany() + .HasForeignKey("RequisitionId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Requisition"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RfqLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Rfq", "Rfq") + .WithMany("Lines") + .HasForeignKey("RfqId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Rfq"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RolePermission", b => + { + b.HasOne("ERPCore.Domain.Entities.Permission", "Permission") + .WithMany() + .HasForeignKey("PermissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Role", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Permission"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunEdge", b => + { + b.HasOne("ERPCore.Domain.Entities.RunStage", "ChildRunStage") + .WithMany() + .HasForeignKey("ChildRunStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "ParentRunStage") + .WithMany() + .HasForeignKey("ParentRunStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ProductionRun", "Run") + .WithMany("Edges") + .HasForeignKey("RunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildRunStage"); + + b.Navigation("ParentRunStage"); + + b.Navigation("Run"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStage", b => + { + b.HasOne("ERPCore.Domain.Entities.ProductionRun", "Run") + .WithMany("Stages") + .HasForeignKey("RunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "TemplateStage") + .WithMany() + .HasForeignKey("TemplateStageId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Run"); + + b.Navigation("TemplateStage"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageEvent", b => + { + b.HasOne("ERPCore.Domain.Entities.ProductionRun", "Run") + .WithMany("Events") + .HasForeignKey("RunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "RunStage") + .WithMany("Events") + .HasForeignKey("RunStageId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Run"); + + b.Navigation("RunStage"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageInput", b => + { + b.HasOne("ERPCore.Domain.Entities.RunStageOutput", "FromRunOutput") + .WithMany() + .HasForeignKey("FromRunOutputId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "RunStage") + .WithMany("Inputs") + .HasForeignKey("RunStageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromRunOutput"); + + b.Navigation("Item"); + + b.Navigation("RunStage"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageOutput", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "RunStage") + .WithMany("Outputs") + .HasForeignKey("RunStageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ScrapReason") + .WithMany() + .HasForeignKey("ScrapReasonCodeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Uom", "Uom") + .WithMany() + .HasForeignKey("UomId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Item"); + + b.Navigation("RunStage"); + + b.Navigation("ScrapReason"); + + b.Navigation("Uom"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesDayEnd", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "CashierUser") + .WithMany() + .HasForeignKey("CashierUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "ClosedByUser") + .WithMany() + .HasForeignKey("ClosedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CashierUser"); + + b.Navigation("ClosedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoice", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatorUserId"); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("Customer"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoiceLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesInvoice", "SalesInvoice") + .WithMany("Lines") + .HasForeignKey("SalesInvoiceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SalesInvoice"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoicePayment", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesInvoice", "SalesInvoice") + .WithMany("Payments") + .HasForeignKey("SalesInvoiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("SalesInvoice"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturn", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ReasonCode") + .WithMany() + .HasForeignKey("ReasonCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("Customer"); + + b.Navigation("ReasonCode"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturnLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesReturn", "Return") + .WithMany("Lines") + .HasForeignKey("ReturnId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesInvoiceLine", "SalesInvoiceLine") + .WithMany() + .HasForeignKey("SalesInvoiceLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Item"); + + b.Navigation("Return"); + + b.Navigation("SalesInvoiceLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlip", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "CashierUser") + .WithMany() + .HasForeignKey("CashierUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesDayEnd", "DayEnd") + .WithMany("Slips") + .HasForeignKey("DayEndId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CashierUser"); + + b.Navigation("Customer"); + + b.Navigation("DayEnd"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlipLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesSlip", "SalesSlip") + .WithMany("Lines") + .HasForeignKey("SalesSlipId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SalesSlip"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Serial", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageEdge", b => + { + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "ChildStage") + .WithMany() + .HasForeignKey("ChildStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "ParentStage") + .WithMany() + .HasForeignKey("ParentStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") + .WithMany("Edges") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildStage"); + + b.Navigation("ParentStage"); + + b.Navigation("Template"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageInput", b => + { + b.HasOne("ERPCore.Domain.Entities.StageOutput", "FromOutput") + .WithMany() + .HasForeignKey("FromOutputId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "Stage") + .WithMany("Inputs") + .HasForeignKey("StageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromOutput"); + + b.Navigation("Item"); + + b.Navigation("Stage"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageOutput", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "Stage") + .WithMany("Outputs") + .HasForeignKey("StageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Uom", "Uom") + .WithMany() + .HasForeignKey("UomId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Item"); + + b.Navigation("Stage"); + + b.Navigation("Uom"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustment", 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.HasOne("ERPCore.Domain.Entities.ReasonCode", "ReasonCode") + .WithMany() + .HasForeignKey("ReasonCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("ReasonCode"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustmentLine", b => + { + b.HasOne("ERPCore.Domain.Entities.StockAdjustment", "Adjustment") + .WithMany("Lines") + .HasForeignKey("AdjustmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Batch", null) + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", null) + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Adjustment"); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCount", 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.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCountLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.StockCount", "Count") + .WithMany("Lines") + .HasForeignKey("CountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Count"); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLayer", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", "Batch") + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.GrnLine", "GrnLine") + .WithMany() + .HasForeignKey("GrnLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", "Serial") + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Batch"); + + b.Navigation("GrnLine"); + + b.Navigation("Item"); + + b.Navigation("Serial"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLedger", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", null) + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", null) + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", null) + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", null) + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransfer", 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.HasOne("ERPCore.Domain.Entities.Warehouse", "DestWarehouse") + .WithMany() + .HasForeignKey("DestWarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "SrcWarehouse") + .WithMany() + .HasForeignKey("SrcWarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("DestWarehouse"); + + b.Navigation("SrcWarehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransferLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", null) + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("DestBinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", null) + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("SrcBinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.StockTransfer", "Transfer") + .WithMany("Lines") + .HasForeignKey("TransferId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Transfer"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubCategory", b => + { + b.HasOne("ERPCore.Domain.Entities.Category", "Category") + .WithMany("SubCategories") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubNavItem", b => + { + b.HasOne("ERPCore.Domain.Entities.NavItem", "NavItem") + .WithMany("Children") + .HasForeignKey("NavItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("NavItem"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicketMessage", b => + { + b.HasOne("ERPCore.Domain.Entities.SupportTicket", "Ticket") + .WithMany("Messages") + .HasForeignKey("TicketId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ticket"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => + { + b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") + .WithMany("Stages") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Template"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.User", b => + { + b.HasOne("ERPCore.Domain.Entities.Role", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => + { + b.HasOne("ERPCore.Domain.Entities.Rfq", "Rfq") + .WithMany("Quotations") + .HasForeignKey("RfqId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Rfq"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotationLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.VendorQuotation", "Quotation") + .WithMany("Lines") + .HasForeignKey("QuotationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Quotation"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Warehouse", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSale", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplate", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Category", b => + { + b.Navigation("SubCategories"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeLoan", b => + { + b.Navigation("Installments"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructure", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Grn", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLine", b => + { + b.Navigation("WarrantyNumbers"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Item", b => + { + b.Navigation("ReorderSettings"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NavItem", b => + { + b.Navigation("Children"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Notification", b => + { + b.Navigation("Recipients"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => + { + b.Navigation("Modules"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => + { + b.Navigation("Components"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollRun", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b => + { + b.Navigation("Edges"); + + b.Navigation("Events"); + + b.Navigation("Stages"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionTemplate", b => + { + b.Navigation("Edges"); + + b.Navigation("Runs"); + + b.Navigation("Stages"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", b => + { + b.Navigation("Lines"); + + b.Navigation("Payments"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturn", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => + { + b.Navigation("Lines"); + + b.Navigation("Quotations"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStage", b => + { + b.Navigation("Events"); + + b.Navigation("Inputs"); + + b.Navigation("Outputs"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesDayEnd", b => + { + b.Navigation("BundleSales"); + + b.Navigation("Slips"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoice", b => + { + b.Navigation("Lines"); + + b.Navigation("Payments"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturn", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlip", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustment", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCount", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransfer", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicket", b => + { + b.Navigation("Messages"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => + { + b.Navigation("Inputs"); + + b.Navigation("Outputs"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Warehouse", b => + { + b.Navigation("Bins"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Backend/ERPCore/Migrations/20260916082426_AddTaxRatesAndItemTaxRate.cs b/Backend/ERPCore/Migrations/20260916082426_AddTaxRatesAndItemTaxRate.cs new file mode 100644 index 0000000..67e6afe --- /dev/null +++ b/Backend/ERPCore/Migrations/20260916082426_AddTaxRatesAndItemTaxRate.cs @@ -0,0 +1,107 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional + +namespace ERPCore.Migrations +{ + /// + public partial class AddTaxRatesAndItemTaxRate : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "TaxClass", + table: "items"); + + migrationBuilder.AddColumn( + name: "TaxRateId", + table: "items", + type: "integer", + nullable: true); + + migrationBuilder.CreateTable( + name: "tax_rates", + columns: table => new + { + TaxRateId = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + Code = table.Column(type: "character varying(20)", maxLength: 20, nullable: false), + Name = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + Percentage = table.Column(type: "numeric(5,2)", precision: 5, scale: 2, nullable: false), + Status = table.Column(type: "character varying(20)", maxLength: 20, nullable: false, defaultValue: "Active"), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true), + xmin = table.Column(type: "xid", rowVersion: true, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_tax_rates", x => x.TaxRateId); + }); + + migrationBuilder.InsertData( + table: "tax_rates", + columns: new[] { "TaxRateId", "Code", "CreatedAt", "Name", "Percentage", "UpdatedAt" }, + values: new object[,] + { + { 1, "STANDARD", new DateTime(2026, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc), "Standard", 15m, null }, + { 2, "ZERO", new DateTime(2026, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc), "Zero-Rated", 0m, null }, + { 3, "EXEMPT", new DateTime(2026, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc), "Exempt", 0m, null } + }); + + migrationBuilder.CreateIndex( + name: "IX_items_TaxRateId", + table: "items", + column: "TaxRateId"); + + migrationBuilder.CreateIndex( + name: "IX_tax_rates_Code", + table: "tax_rates", + column: "Code", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_tax_rates_Status", + table: "tax_rates", + column: "Status"); + + migrationBuilder.AddForeignKey( + name: "FK_items_tax_rates_TaxRateId", + table: "items", + column: "TaxRateId", + principalTable: "tax_rates", + principalColumn: "TaxRateId", + onDelete: ReferentialAction.Restrict); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_items_tax_rates_TaxRateId", + table: "items"); + + migrationBuilder.DropTable( + name: "tax_rates"); + + migrationBuilder.DropIndex( + name: "IX_items_TaxRateId", + table: "items"); + + migrationBuilder.DropColumn( + name: "TaxRateId", + table: "items"); + + migrationBuilder.AddColumn( + name: "TaxClass", + table: "items", + type: "character varying(20)", + maxLength: 20, + nullable: true); + } + } +} diff --git a/Backend/ERPCore/Migrations/20260916102635_BranchIsolationPhase1.Designer.cs b/Backend/ERPCore/Migrations/20260916102635_BranchIsolationPhase1.Designer.cs new file mode 100644 index 0000000..7436d4d --- /dev/null +++ b/Backend/ERPCore/Migrations/20260916102635_BranchIsolationPhase1.Designer.cs @@ -0,0 +1,8661 @@ +// +using System; +using ERPCore.Infra.Persistence; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace ERPCore.Migrations +{ + [DbContext(typeof(ErpDbContext))] + [Migration("20260916102635_BranchIsolationPhase1")] + partial class BranchIsolationPhase1 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.9") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceRecord", b => + { + b.Property("AttendanceRecordId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AttendanceRecordId")); + + b.Property("AttendanceDate") + .HasColumnType("timestamp with time zone"); + + b.Property("AttendanceStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("AttendanceUploadBatchId") + .HasColumnType("integer"); + + b.Property("CheckIn") + .HasColumnType("interval"); + + b.Property("CheckOut") + .HasColumnType("interval"); + + b.Property("DuplicateOfAttendanceRecordId") + .HasColumnType("integer"); + + b.Property("EarlyLeaveMinutes") + .HasColumnType("integer"); + + b.Property("EditedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EditedBy") + .HasColumnType("integer"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("IsManualOverride") + .HasColumnType("boolean"); + + b.Property("LateMinutes") + .HasColumnType("integer"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("OvertimeMinutes") + .HasColumnType("integer"); + + b.Property("RowValidationStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("WorkShiftId") + .HasColumnType("integer"); + + b.Property("WorkingMinutes") + .HasColumnType("integer"); + + b.HasKey("AttendanceRecordId"); + + b.HasIndex("AttendanceUploadBatchId"); + + b.HasIndex("WorkShiftId"); + + b.HasIndex("EmployeeId", "AttendanceDate"); + + b.ToTable("hr_attendance_records", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceUploadBatch", b => + { + b.Property("AttendanceUploadBatchId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AttendanceUploadBatchId")); + + b.Property("ConfirmedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ConfirmedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("OriginalFileName") + .HasMaxLength(260) + .HasColumnType("character varying(260)"); + + b.Property("PeriodEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("PeriodStart") + .HasColumnType("timestamp with time zone"); + + b.Property("RowCountDuplicate") + .HasColumnType("integer"); + + b.Property("RowCountError") + .HasColumnType("integer"); + + b.Property("RowCountTotal") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SourceType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UploadedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UploadedBy") + .HasColumnType("integer"); + + b.HasKey("AttendanceUploadBatchId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("PeriodStart", "PeriodEnd"); + + b.ToTable("hr_attendance_upload_batches", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AuditLog", b => + { + b.Property("AuditId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AuditId")); + + b.Property("Action") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("ChangeSet") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EntityId") + .HasColumnType("integer"); + + b.Property("EntityType") + .IsRequired() + .HasMaxLength(80) + .HasColumnType("character varying(80)"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("AuditId"); + + b.HasIndex("CreatedAt"); + + b.HasIndex("UserId"); + + b.HasIndex("EntityType", "EntityId"); + + b.ToTable("audit_logs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Batch", b => + { + b.Property("BatchId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BatchId")); + + b.Property("BatchNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ExpiryDate") + .HasColumnType("date"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.HasKey("BatchId"); + + b.HasIndex("ItemId", "BatchNo") + .IsUnique(); + + b.ToTable("batches", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Bin", b => + { + b.Property("BinId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BinId")); + + b.Property("BinType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BinId"); + + b.HasIndex("WarehouseId", "Code") + .IsUnique(); + + b.ToTable("bins", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Branch", b => + { + b.Property("BranchId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BranchId")); + + b.Property("Address") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("PhoneNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_branches", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BranchConfig", b => + { + b.Property("ConfigId") + .HasColumnType("integer"); + + b.Property("BranchingEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.Property("WarehouseBranchingEnabled") + .HasColumnType("boolean"); + + b.HasKey("ConfigId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("branch_config", null, t => + { + t.HasCheckConstraint("ck_branch_config_singleton", "\"ConfigId\" = 1"); + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Brand", b => + { + b.Property("BrandId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BrandId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("BrandId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("brands", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSale", b => + { + b.Property("BundleSaleId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleId")); + + b.Property("BundleCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BundleDate") + .HasColumnType("timestamp with time zone"); + + b.Property("BundleName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("BundleNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BundlePrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BundleSaleTemplateId") + .HasColumnType("integer"); + + b.Property("CashierUserId") + .HasColumnType("integer"); + + b.Property("ComponentSubtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("CustomerSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DayEndId") + .HasColumnType("integer"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("MarginAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BundleSaleId"); + + b.HasIndex("BundleNo") + .IsUnique(); + + b.HasIndex("BundleSaleTemplateId"); + + b.HasIndex("CashierUserId"); + + b.HasIndex("CustomerId"); + + b.HasIndex("DayEndId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("bundle_sales", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleLine", b => + { + b.Property("BundleSaleLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleLineId")); + + b.Property("BundleSaleId") + .HasColumnType("integer"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("IncludeInBundle") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("IsComponent") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ParentLineId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BundleSaleLineId"); + + b.HasIndex("BundleSaleId"); + + b.HasIndex("ItemId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("bundle_sale_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplate", b => + { + b.Property("BundleSaleTemplateId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleTemplateId")); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TemplateCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("TemplateName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("BundleSaleTemplateId"); + + b.HasIndex("TemplateCode") + .IsUnique(); + + b.ToTable("bundle_sale_templates", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplateLine", b => + { + b.Property("BundleSaleTemplateLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleTemplateLineId")); + + b.Property("BundleSaleTemplateId") + .HasColumnType("integer"); + + b.Property("IncludeInBundle") + .HasColumnType("boolean"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SortOrder") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BundleSaleTemplateLineId"); + + b.HasIndex("BundleSaleTemplateId"); + + b.HasIndex("ItemId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("bundle_sale_template_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Category", b => + { + b.Property("CategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CategoryId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("CategoryId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("categories", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Customer", b => + { + b.Property("CustomerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CustomerId")); + + b.Property("AddressLine1") + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("AddressLine2") + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("City") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Country") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreditDays") + .HasColumnType("integer"); + + b.Property("CreditLimit") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CustomerCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CustomerType") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("B2C"); + + b.Property("DefaultWarehouseId") + .HasColumnType("integer"); + + b.Property("DisplayName") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Email") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Phone") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TaxRegistrationNo") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("CustomerId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CustomerCode") + .IsUnique(); + + b.HasIndex("CustomerType"); + + b.HasIndex("DefaultWarehouseId"); + + b.HasIndex("Status"); + + b.ToTable("customers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Department", b => + { + b.Property("DepartmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("DepartmentId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("HeadEmployeeId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("ParentDepartmentId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("DepartmentId"); + + b.HasIndex("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("HeadEmployeeId"); + + b.HasIndex("ParentDepartmentId"); + + b.HasIndex("Status"); + + b.ToTable("hr_departments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Designation", b => + { + b.Property("DesignationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("DesignationId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("DesignationId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_designations", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Employee", b => + { + b.Property("EmployeeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeId")); + + b.Property("AddressLine1") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("AddressLine2") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("City") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ConfirmationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Country") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DateOfBirth") + .HasColumnType("timestamp with time zone"); + + b.Property("DepartmentId") + .HasColumnType("integer"); + + b.Property("DesignationId") + .HasColumnType("integer"); + + b.Property("Email") + .HasMaxLength(320) + .HasColumnType("character varying(320)"); + + b.Property("EmergencyContactName") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("EmergencyContactPhone") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmergencyContactRelationship") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("EmployeeCode") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmploymentTypeId") + .HasColumnType("integer"); + + b.Property("EpfNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EtfNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Gender") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("HireDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LastWorkingDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Nationality") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Nic") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PersonalMobile") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PostalCode") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ProfilePhotoPath") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("ReportingManagerId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TaxIdentificationNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.Property("WorkShiftId") + .HasColumnType("integer"); + + b.HasKey("EmployeeId"); + + b.HasIndex("BranchId"); + + b.HasIndex("DepartmentId"); + + b.HasIndex("DesignationId"); + + b.HasIndex("Email"); + + b.HasIndex("EmployeeCode") + .IsUnique(); + + b.HasIndex("EmploymentTypeId"); + + b.HasIndex("ReportingManagerId"); + + b.HasIndex("Status"); + + b.HasIndex("UserId") + .IsUnique(); + + b.HasIndex("WorkShiftId"); + + b.ToTable("hr_employees", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeBankDetail", b => + { + b.Property("EmployeeBankDetailId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeBankDetailId")); + + b.Property("AccountHolderName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("AccountNumber") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BankName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("BranchName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("IsPrimary") + .HasColumnType("boolean"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("SwiftCode") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("EmployeeBankDetailId"); + + b.HasIndex("EmployeeId"); + + b.ToTable("hr_employee_bank_details", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeDocument", b => + { + b.Property("EmployeeDocumentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeDocumentId")); + + b.Property("ContentType") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("ExpiryDate") + .HasColumnType("timestamp with time zone"); + + b.Property("HrDocumentTypeId") + .HasColumnType("integer"); + + b.Property("IssueDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("OriginalFileName") + .IsRequired() + .HasMaxLength(260) + .HasColumnType("character varying(260)"); + + b.Property("RelativePath") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SizeBytes") + .HasColumnType("bigint"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("StoredFileName") + .IsRequired() + .HasMaxLength(260) + .HasColumnType("character varying(260)"); + + b.Property("UploadedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UploadedBy") + .HasColumnType("integer"); + + b.Property("VerifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VerifiedBy") + .HasColumnType("integer"); + + b.HasKey("EmployeeDocumentId"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("ExpiryDate"); + + b.HasIndex("HrDocumentTypeId"); + + b.ToTable("hr_employee_documents", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeLoan", b => + { + b.Property("EmployeeLoanId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeLoanId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("InstallmentAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("InterestRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("LoanKind") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("NumberOfInstallments") + .HasColumnType("integer"); + + b.Property("OutstandingBalance") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("PrincipalAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("StartMonth") + .HasColumnType("integer"); + + b.Property("StartYear") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("EmployeeLoanId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("EmployeeId"); + + b.HasIndex("Status"); + + b.ToTable("hr_employee_loans", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructure", b => + { + b.Property("EmployeeSalaryStructureId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeSalaryStructureId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("BasicSalary") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("Currency") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("character varying(3)"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveTo") + .HasColumnType("timestamp with time zone"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("EmployeeSalaryStructureId"); + + b.HasIndex("EmployeeId", "EffectiveTo"); + + b.ToTable("hr_employee_salary_structures", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructureLine", b => + { + b.Property("EmployeeSalaryStructureLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeSalaryStructureLineId")); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("EmployeeSalaryStructureId") + .HasColumnType("integer"); + + b.Property("SalaryComponentId") + .HasColumnType("integer"); + + b.HasKey("EmployeeSalaryStructureLineId"); + + b.HasIndex("EmployeeSalaryStructureId"); + + b.HasIndex("SalaryComponentId"); + + b.ToTable("hr_employee_salary_structure_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmploymentType", b => + { + b.Property("EmploymentTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmploymentTypeId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("EmploymentTypeId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_employment_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Grn", b => + { + b.Property("GrnId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("GrnId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PoId") + .HasColumnType("integer"); + + b.Property("PostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PurchaseInvoiceId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("GrnId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("PoId"); + + b.HasIndex("PurchaseInvoiceId"); + + b.HasIndex("Status"); + + b.HasIndex("VendorId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("grns", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLine", b => + { + b.Property("GrnLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("GrnLineId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("DiscountPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("GrnId") + .HasColumnType("integer"); + + b.Property("HoldStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("NetUnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("PoLineId") + .HasColumnType("integer"); + + b.Property("PoUnitPrice") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReceivedValue") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("VatAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("VatPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.HasKey("GrnLineId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("GrnId"); + + b.HasIndex("ItemId"); + + b.HasIndex("PoLineId"); + + b.ToTable("grn_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLineWarrantyNumber", b => + { + b.Property("GrnLineWarrantyNumberId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("GrnLineWarrantyNumberId")); + + b.Property("GrnLineId") + .HasColumnType("integer"); + + b.Property("WarrantyNo") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("WarrantyPeriodMonths") + .HasColumnType("integer"); + + b.HasKey("GrnLineWarrantyNumberId"); + + b.HasIndex("GrnLineId", "WarrantyNo") + .IsUnique(); + + b.ToTable("grn_line_warranty_numbers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.HrDocumentType", b => + { + b.Property("HrDocumentTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("HrDocumentTypeId")); + + b.Property("Category") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpiryTracked") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RequiredAtOnboarding") + .HasColumnType("boolean"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("HrDocumentTypeId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_document_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Item", b => + { + b.Property("ItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ItemId")); + + b.Property("BaseUomId") + .HasColumnType("integer"); + + b.Property("BrandId") + .HasColumnType("integer"); + + b.Property("CategoryId") + .HasColumnType("integer"); + + b.Property("ContentBaseQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ContentBaseUnit") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ContentQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ContentUnit") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DefaultVendorId") + .HasColumnType("integer"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SellingFlatPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SellingMaxPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SellingMinPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Sku") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("StockNature") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("SubCategoryId") + .HasColumnType("integer"); + + b.Property("TaxRateId") + .HasColumnType("integer"); + + b.Property("TrackingMode") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Warranty") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("NonWarranty"); + + b.Property("WarrantyPeriodMonths") + .HasColumnType("integer"); + + b.HasKey("ItemId"); + + b.HasIndex("BaseUomId"); + + b.HasIndex("BrandId"); + + b.HasIndex("CategoryId"); + + b.HasIndex("DefaultVendorId"); + + b.HasIndex("Sku") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("SubCategoryId"); + + b.HasIndex("TaxRateId"); + + b.ToTable("items", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ItemReorder", b => + { + b.Property("ReorderId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReorderId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("ReorderPoint") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReorderQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("ReorderId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("ItemId", "WarehouseId") + .IsUnique(); + + b.ToTable("item_reorders", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ItemType", b => + { + b.Property("ItemTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ItemTypeId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsMeasurable") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("ItemTypeId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("item_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.JournalEntryStub", b => + { + b.Property("JournalId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("JournalId")); + + b.Property("Amount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CreditAccount") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("DebitAccount") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("SourceDocId") + .HasColumnType("integer"); + + b.Property("SourceDocType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.HasKey("JournalId"); + + b.HasIndex("SourceDocType", "SourceDocId"); + + b.ToTable("journal_entry_stubs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveBalance", b => + { + b.Property("LeaveBalanceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LeaveBalanceId")); + + b.Property("AdjustmentDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("CarriedForwardDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("EntitledDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("LeaveTypeId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("TakenDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Year") + .HasColumnType("integer"); + + b.HasKey("LeaveBalanceId"); + + b.HasIndex("LeaveTypeId"); + + b.HasIndex("EmployeeId", "LeaveTypeId", "Year") + .IsUnique(); + + b.ToTable("hr_leave_balances", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveRequest", b => + { + b.Property("LeaveRequestId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LeaveRequestId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DaysCount") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("EndDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LeaveTypeId") + .HasColumnType("integer"); + + b.Property("Reason") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("RejectionReason") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("StartDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("LeaveRequestId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("EmployeeId"); + + b.HasIndex("LeaveTypeId"); + + b.HasIndex("Status"); + + b.HasIndex("StartDate", "EndDate"); + + b.ToTable("hr_leave_requests", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveType", b => + { + b.Property("LeaveTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LeaveTypeId")); + + b.Property("AccrualPerYear") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("CarryForwardAllowed") + .HasColumnType("boolean"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CountsAsNoPay") + .HasColumnType("boolean"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsPaid") + .HasColumnType("boolean"); + + b.Property("MaxCarryForwardDays") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RequiresApproval") + .HasColumnType("boolean"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("LeaveTypeId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_leave_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoanInstallment", b => + { + b.Property("LoanInstallmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LoanInstallmentId")); + + b.Property("DueMonth") + .HasColumnType("integer"); + + b.Property("DueYear") + .HasColumnType("integer"); + + b.Property("EmployeeLoanId") + .HasColumnType("integer"); + + b.Property("InstallmentNumber") + .HasColumnType("integer"); + + b.Property("PaidAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("PayrollRunId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("ScheduledAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("LoanInstallmentId"); + + b.HasIndex("EmployeeLoanId"); + + b.HasIndex("PayrollRunId"); + + b.HasIndex("DueYear", "DueMonth"); + + b.ToTable("hr_loan_installments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoginActivity", b => + { + b.Property("LoginActivityId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LoginActivityId")); + + b.Property("DeviceLabel") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("IpAddress") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("LoginAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserAgent") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("LoginActivityId"); + + b.HasIndex("UserId", "LoginAt"); + + b.ToTable("login_activities", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NavItem", b => + { + b.Property("NavItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NavItemId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Href") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Icon") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.HasKey("NavItemId"); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("nav_items", (string)null); + + b.HasData( + new + { + NavItemId = 1, + Code = "dashboard", + Href = "/dashboard", + Label = "Dashboard", + SortOrder = 1, + Status = "Active" + }, + new + { + NavItemId = 2, + Code = "products", + Href = "/dashboard/products", + Label = "Products", + SortOrder = 2, + Status = "Active" + }, + new + { + NavItemId = 4, + Code = "procurement", + Href = "/dashboard/procurement", + Label = "Procurement", + SortOrder = 4, + Status = "Active" + }, + new + { + NavItemId = 5, + Code = "receiving", + Href = "/dashboard/receiving/grn", + Label = "Receiving", + SortOrder = 5, + Status = "Active" + }, + new + { + NavItemId = 6, + Code = "stock", + Href = "/dashboard/stock", + Label = "Stock", + SortOrder = 6, + Status = "Active" + }, + new + { + NavItemId = 7, + Code = "warehouses", + Href = "/dashboard/warehouse", + Label = "Warehouses", + SortOrder = 7, + Status = "Active" + }, + new + { + NavItemId = 8, + Code = "orders", + Href = "/dashboard/orders", + Label = "Orders", + SortOrder = 8, + Status = "Active" + }, + new + { + NavItemId = 9, + Code = "settings", + Href = "/dashboard/settings", + Label = "Settings", + SortOrder = 9, + Status = "Active" + }, + new + { + NavItemId = 10, + Code = "help", + Href = "/dashboard/help", + Label = "Help", + SortOrder = 10, + Status = "Active" + }, + new + { + NavItemId = 11, + Code = "ledgers", + Href = "/dashboard/ledgers", + Label = "Ledgers", + SortOrder = 11, + Status = "Active" + }, + new + { + NavItemId = 12, + Code = "accounts", + Href = "/dashboard/accounts", + Label = "Accounts", + SortOrder = 12, + Status = "Active" + }, + new + { + NavItemId = 13, + Code = "sales", + Href = "/dashboard/sales", + Label = "Sales", + SortOrder = 13, + Status = "Active" + }, + new + { + NavItemId = 14, + Code = "production", + Href = "/dashboard/production", + Label = "Production", + SortOrder = 14, + Status = "Active" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Notification", b => + { + b.Property("NotificationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NotificationId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("ModuleKey") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("RelatedEntityId") + .HasColumnType("integer"); + + b.Property("RelatedEntityType") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.HasKey("NotificationId"); + + b.HasIndex("CreatedAt"); + + b.ToTable("notifications", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => + { + b.Property("NotificationConfigId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.HasKey("NotificationConfigId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("notification_config", null, t => + { + t.HasCheckConstraint("ck_notification_config_singleton", "\"NotificationConfigId\" = 1"); + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfigModule", b => + { + b.Property("NotificationConfigModuleId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NotificationConfigModuleId")); + + b.Property("EmailEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("InAppEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("ModuleKey") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("NotificationConfigId") + .HasColumnType("integer"); + + b.Property("SmsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.HasKey("NotificationConfigModuleId"); + + b.HasIndex("ModuleKey") + .IsUnique(); + + b.HasIndex("NotificationConfigId"); + + b.ToTable("notification_config_modules", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationRecipient", b => + { + b.Property("NotificationRecipientId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NotificationRecipientId")); + + b.Property("IsRead") + .HasColumnType("boolean"); + + b.Property("NotificationId") + .HasColumnType("integer"); + + b.Property("ReadAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("NotificationRecipientId"); + + b.HasIndex("NotificationId"); + + b.HasIndex("UserId", "IsRead", "NotificationId"); + + b.ToTable("notification_recipients", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NumberSequence", b => + { + b.Property("SequenceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SequenceId")); + + b.Property("BranchId") + .HasColumnType("integer") + .HasColumnName("branch_id"); + + b.Property("DocType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("doc_type"); + + b.Property("LastNumber") + .HasColumnType("integer") + .HasColumnName("last_number"); + + b.Property("Year") + .HasColumnType("integer") + .HasColumnName("year"); + + b.HasKey("SequenceId"); + + b.HasIndex("BranchId"); + + b.HasIndex("DocType", "BranchId", "Year") + .IsUnique(); + + b.ToTable("number_sequences", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => + { + b.Property("PayrollLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollLineId")); + + b.Property("AbsentDays") + .HasColumnType("integer"); + + b.Property("BasicSalary") + .HasColumnType("numeric(18,2)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("EpfEmployeeAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("EpfEmployerAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("EtfEmployerAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("GrossSalary") + .HasColumnType("numeric(18,2)"); + + b.Property("LateDeductionAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("LateMinutesTotal") + .HasColumnType("integer"); + + b.Property("LeaveDays") + .HasColumnType("integer"); + + b.Property("LoanDeductionAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("NetSalary") + .HasColumnType("numeric(18,2)"); + + b.Property("NoPayAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("OtMinutesTotal") + .HasColumnType("integer"); + + b.Property("OtherDeductionsAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("OvertimeAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("PayrollRunId") + .HasColumnType("integer"); + + b.Property("PresentDays") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("TaxAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("TotalAllowances") + .HasColumnType("numeric(18,2)"); + + b.Property("WorkingDays") + .HasColumnType("integer"); + + b.HasKey("PayrollLineId"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("PayrollRunId", "EmployeeId") + .IsUnique(); + + b.ToTable("hr_payroll_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLineComponent", b => + { + b.Property("PayrollLineComponentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollLineComponentId")); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("ComponentCategory") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("PayrollLineId") + .HasColumnType("integer"); + + b.Property("SalaryComponentId") + .HasColumnType("integer"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.HasKey("PayrollLineComponentId"); + + b.HasIndex("PayrollLineId"); + + b.HasIndex("SalaryComponentId"); + + b.ToTable("hr_payroll_line_components", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollRun", b => + { + b.Property("PayrollRunId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollRunId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GeneratedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GeneratedBy") + .HasColumnType("integer"); + + b.Property("LockedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("LockedBy") + .HasColumnType("integer"); + + b.Property("PeriodMonth") + .HasColumnType("integer"); + + b.Property("PeriodYear") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UnlockReason") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("UnlockedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UnlockedBy") + .HasColumnType("integer"); + + b.HasKey("PayrollRunId"); + + b.HasIndex("BranchId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("PeriodYear", "PeriodMonth", "BranchId"); + + b.ToTable("hr_payroll_runs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollStatutorySetting", b => + { + b.Property("PayrollStatutorySettingId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollStatutorySettingId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveTo") + .HasColumnType("timestamp with time zone"); + + b.Property("EpfEmployeeRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("EpfEmployerRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("EtfEmployerRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("OtMultiplierDefault") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.HasKey("PayrollStatutorySettingId"); + + b.HasIndex("EffectiveFrom"); + + b.ToTable("hr_payroll_statutory_settings", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Payslip", b => + { + b.Property("PayslipId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayslipId")); + + b.Property("GeneratedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PayrollLineId") + .HasColumnType("integer"); + + b.Property("ReleasedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReleasedBy") + .HasColumnType("integer"); + + b.HasKey("PayslipId"); + + b.HasIndex("PayrollLineId") + .IsUnique(); + + b.ToTable("hr_payslips", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Permission", b => + { + b.Property("PermissionId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PermissionId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(80) + .HasColumnType("character varying(80)"); + + b.Property("NavItemId") + .HasColumnType("integer"); + + b.Property("SubNavItemId") + .HasColumnType("integer"); + + b.HasKey("PermissionId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("NavItemId"); + + b.HasIndex("SubNavItemId"); + + b.ToTable("permissions", (string)null); + + b.HasData( + new + { + PermissionId = 1, + Code = "NAV:dashboard", + NavItemId = 1 + }, + new + { + PermissionId = 2, + Code = "NAV:products", + NavItemId = 2 + }, + new + { + PermissionId = 3, + Code = "NAV:procurement.vendors", + SubNavItemId = 30 + }, + new + { + PermissionId = 4, + Code = "NAV:procurement", + NavItemId = 4 + }, + new + { + PermissionId = 5, + Code = "NAV:receiving", + NavItemId = 5 + }, + new + { + PermissionId = 6, + Code = "NAV:stock", + NavItemId = 6 + }, + new + { + PermissionId = 7, + Code = "NAV:warehouses", + NavItemId = 7 + }, + new + { + PermissionId = 8, + Code = "NAV:orders", + NavItemId = 8 + }, + new + { + PermissionId = 9, + Code = "NAV:settings", + NavItemId = 9 + }, + new + { + PermissionId = 10, + Code = "NAV:help", + NavItemId = 10 + }, + new + { + PermissionId = 11, + Code = "NAV:products.item", + SubNavItemId = 1 + }, + new + { + PermissionId = 12, + Code = "NAV:products.category", + SubNavItemId = 2 + }, + new + { + PermissionId = 13, + Code = "NAV:products.brand", + SubNavItemId = 3 + }, + new + { + PermissionId = 14, + Code = "NAV:products.item-type", + SubNavItemId = 4 + }, + new + { + PermissionId = 15, + Code = "NAV:products.uom", + SubNavItemId = 5 + }, + new + { + PermissionId = 16, + Code = "NAV:products.configuration", + SubNavItemId = 6 + }, + new + { + PermissionId = 17, + Code = "NAV:settings.roles", + SubNavItemId = 7 + }, + new + { + PermissionId = 18, + Code = "NAV:settings.users", + SubNavItemId = 8 + }, + new + { + PermissionId = 28, + Code = "NAV:procurement.requisitions", + SubNavItemId = 17 + }, + new + { + PermissionId = 29, + Code = "NAV:procurement.rfqs", + SubNavItemId = 18 + }, + new + { + PermissionId = 30, + Code = "NAV:procurement.purchase-orders", + SubNavItemId = 19 + }, + new + { + PermissionId = 31, + Code = "NAV:procurement.purchase-returns", + SubNavItemId = 20 + }, + new + { + PermissionId = 19, + Code = "NAV:ledgers", + NavItemId = 11 + }, + new + { + PermissionId = 20, + Code = "NAV:ledgers.trial-balance", + SubNavItemId = 9 + }, + new + { + PermissionId = 21, + Code = "NAV:ledgers.balance-sheet", + SubNavItemId = 10 + }, + new + { + PermissionId = 22, + Code = "NAV:ledgers.general-ledger", + SubNavItemId = 11 + }, + new + { + PermissionId = 23, + Code = "NAV:ledgers.profit-and-loss", + SubNavItemId = 12 + }, + new + { + PermissionId = 24, + Code = "NAV:ledgers.cash-flow", + SubNavItemId = 13 + }, + new + { + PermissionId = 25, + Code = "NAV:ledgers.budget-vs-actual", + SubNavItemId = 14 + }, + new + { + PermissionId = 27, + Code = "NAV:ledgers.tax-report", + SubNavItemId = 16 + }, + new + { + PermissionId = 26, + Code = "NAV:accounts.bank-accounts", + SubNavItemId = 15 + }, + new + { + PermissionId = 32, + Code = "NAV:accounts", + NavItemId = 12 + }, + new + { + PermissionId = 33, + Code = "NAV:accounts.cheque-books", + SubNavItemId = 21 + }, + new + { + PermissionId = 34, + Code = "NAV:accounts.received-cheques", + SubNavItemId = 22 + }, + new + { + PermissionId = 35, + Code = "NAV:production", + NavItemId = 14 + }, + new + { + PermissionId = 36, + Code = "NAV:production.templates", + SubNavItemId = 27 + }, + new + { + PermissionId = 37, + Code = "NAV:production.runs", + SubNavItemId = 25 + }, + new + { + PermissionId = 38, + Code = "NAV:production.produced", + SubNavItemId = 26 + }, + new + { + PermissionId = 39, + Code = "NAV:procurement.purchase-invoices", + SubNavItemId = 28 + }, + new + { + PermissionId = 40, + Code = "NAV:settings.branches", + SubNavItemId = 29 + }, + new + { + PermissionId = 41, + Code = "NAV:stock.ledger", + SubNavItemId = 31 + }, + new + { + PermissionId = 42, + Code = "NAV:stock.enquiry", + SubNavItemId = 32 + }, + new + { + PermissionId = 43, + Code = "NAV:stock.valuation", + SubNavItemId = 33 + }, + new + { + PermissionId = 44, + Code = "NAV:stock.transfers", + SubNavItemId = 34 + }, + new + { + PermissionId = 45, + Code = "NAV:stock.adjustments", + SubNavItemId = 35 + }, + new + { + PermissionId = 46, + Code = "NAV:stock.counts", + SubNavItemId = 36 + }, + new + { + PermissionId = 47, + Code = "NAV:stock.reorder-alerts", + SubNavItemId = 37 + }, + new + { + PermissionId = 48, + Code = "NAV:stock.wastage", + SubNavItemId = 38 + }, + new + { + PermissionId = 49, + Code = "NAV:sales.bundle-templates", + SubNavItemId = 23 + }, + new + { + PermissionId = 50, + Code = "NAV:sales.invoices", + SubNavItemId = 40 + }, + new + { + PermissionId = 51, + Code = "NAV:sales.free-issues", + SubNavItemId = 41 + }, + new + { + PermissionId = 52, + Code = "NAV:sales.day-end", + SubNavItemId = 42 + }, + new + { + PermissionId = 53, + Code = "NAV:products.tax-rates", + SubNavItemId = 43 + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PoLine", b => + { + b.Property("PoLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PoLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("PoId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyReceived") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Tax") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("PoLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("PoId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("po_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductConfig", b => + { + b.Property("ConfigId") + .HasColumnType("integer"); + + b.Property("BatchListsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("BrandsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("ItemTypesEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SellingPricesEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("SerialNumbersEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("SubcategoriesEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.Property("WarrantyPeriodsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.HasKey("ConfigId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("product_config", null, t => + { + t.HasCheckConstraint("ck_product_config_singleton", "\"ConfigId\" = 1"); + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b => + { + b.Property("RunId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunId")); + + b.Property("CancelReasonCodeId") + .HasColumnType("integer"); + + b.Property("CompletedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("OutputBinId") + .HasColumnType("integer"); + + b.Property("ReworkCount") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("ScaleFactor") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("TargetQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TemplateId") + .HasColumnType("integer"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("RunId"); + + b.HasIndex("CancelReasonCodeId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("OutputBinId"); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("TemplateId", "Status"); + + b.ToTable("production_runs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionTemplate", b => + { + b.Property("TemplateId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TemplateId")); + + b.Property("Annotations") + .HasColumnType("jsonb"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("TemplateId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("CreatedBy"); + + b.HasIndex("Status"); + + b.ToTable("production_templates", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", b => + { + b.Property("PurchaseInvoiceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PurchaseInvoiceId")); + + b.Property("BalanceAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VatTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.Property("VendorInvoiceDate") + .HasColumnType("timestamp with time zone"); + + b.Property("VendorInvoiceNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("VendorSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("VendorSnapshotTaxNo") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("PurchaseInvoiceId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("VendorId"); + + b.HasIndex("VendorId", "VendorInvoiceNo"); + + b.ToTable("purchase_invoices", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoiceLine", b => + { + b.Property("PurchaseInvoiceLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PurchaseInvoiceLineId")); + + b.Property("GrnId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PurchaseInvoiceId") + .HasColumnType("integer"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("VatTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("PurchaseInvoiceLineId"); + + b.HasIndex("GrnId") + .IsUnique(); + + b.HasIndex("PurchaseInvoiceId"); + + b.ToTable("purchase_invoice_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoicePayment", b => + { + b.Property("PurchaseInvoicePaymentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PurchaseInvoicePaymentId")); + + b.Property("Amount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BankAccountName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("GlBankAccountId") + .HasColumnType("bigint"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PaymentDate") + .HasColumnType("timestamp with time zone"); + + b.Property("PurchaseInvoiceId") + .HasColumnType("integer"); + + b.Property("Reference") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("PurchaseInvoicePaymentId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("PurchaseInvoiceId"); + + b.ToTable("purchase_invoice_payments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => + { + b.Property("PoId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PoId")); + + b.Property("ApprovalRequired") + .HasColumnType("boolean"); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("ApproverUserId") + .HasColumnType("integer"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RequisitionId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.HasKey("PoId"); + + b.HasIndex("ApproverUserId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("RequisitionId"); + + b.HasIndex("Status"); + + b.HasIndex("VendorId"); + + b.ToTable("purchase_orders", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturn", b => + { + b.Property("ReturnId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReasonCodeId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("ReturnId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("ReasonCodeId"); + + b.HasIndex("VendorId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("purchase_returns", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturnLine", b => + { + b.Property("ReturnLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnLineId")); + + b.Property("GrnLineId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReturnId") + .HasColumnType("integer"); + + b.HasKey("ReturnLineId"); + + b.HasIndex("GrnLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("ReturnId"); + + b.ToTable("purchase_return_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ReasonCode", b => + { + b.Property("ReasonCodeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReasonCodeId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Context") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.HasKey("ReasonCodeId"); + + b.HasIndex("Context", "Code") + .IsUnique(); + + b.ToTable("reason_codes", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => + { + b.Property("RequisitionId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RequisitionId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RequestedBy") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("RequisitionId"); + + b.HasIndex("BranchId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("RequestedBy"); + + b.HasIndex("Status"); + + b.ToTable("requisitions", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RequisitionLine", b => + { + b.Property("ReqLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReqLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RequiredBy") + .HasColumnType("date"); + + b.Property("RequisitionId") + .HasColumnType("integer"); + + b.HasKey("ReqLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RequisitionId"); + + b.ToTable("requisition_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => + { + b.Property("RfqId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RfqId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RequisitionId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("RfqId"); + + b.HasIndex("BranchId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("RequisitionId"); + + b.ToTable("rfqs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RfqLine", b => + { + b.Property("RfqLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RfqLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RfqId") + .HasColumnType("integer"); + + b.HasKey("RfqLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RfqId"); + + b.ToTable("rfq_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Role", b => + { + b.Property("RoleId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RoleId")); + + b.Property("AuthRoleId") + .HasColumnType("uuid") + .HasColumnName("auth_role_id"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsSystemRole") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("RoleId"); + + b.HasIndex("AuthRoleId") + .IsUnique(); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("roles", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RolePermission", b => + { + b.Property("RoleId") + .HasColumnType("integer"); + + b.Property("PermissionId") + .HasColumnType("integer"); + + b.Property("Actions") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(31); + + b.HasKey("RoleId", "PermissionId"); + + b.HasIndex("PermissionId"); + + b.ToTable("role_permissions", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunEdge", b => + { + b.Property("RunEdgeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunEdgeId")); + + b.Property("ChildRunStageId") + .HasColumnType("integer"); + + b.Property("ParentRunStageId") + .HasColumnType("integer"); + + b.Property("RunId") + .HasColumnType("integer"); + + b.HasKey("RunEdgeId"); + + b.HasIndex("ChildRunStageId"); + + b.HasIndex("RunId"); + + b.HasIndex("ParentRunStageId", "ChildRunStageId") + .IsUnique(); + + b.ToTable("run_edges", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStage", b => + { + b.Property("RunStageId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunStageId")); + + b.Property("ActualEndAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ActualStartAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EstimatedMinutes") + .HasColumnType("integer"); + + b.Property("FieldDefs") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("FieldValues") + .HasColumnType("jsonb"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("PosX") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PosY") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RoleLabel") + .HasMaxLength(60) + .HasColumnType("character varying(60)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("RunId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("TemplateStageId") + .HasColumnType("integer"); + + b.HasKey("RunStageId"); + + b.HasIndex("TemplateStageId"); + + b.HasIndex("RunId", "Status"); + + b.ToTable("run_stages", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageEvent", b => + { + b.Property("EventId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EventId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Note") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Payload") + .HasColumnType("jsonb"); + + b.Property("RunId") + .HasColumnType("integer"); + + b.Property("RunStageId") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("EventId"); + + b.HasIndex("RunStageId"); + + b.HasIndex("UserId"); + + b.HasIndex("RunId", "EventId"); + + b.ToTable("run_stage_events", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageInput", b => + { + b.Property("RunInputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunInputId")); + + b.Property("ConsumedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ConsumedValue") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DeliveredQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("FromRunOutputId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("PlannedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyUnit") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ReturnedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReturnedValue") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RunStageId") + .HasColumnType("integer"); + + b.Property("Source") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("RunInputId"); + + b.HasIndex("FromRunOutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RunStageId"); + + b.ToTable("run_stage_inputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageOutput", b => + { + b.Property("RunOutputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunOutputId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("PlannedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ProducedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RunStageId") + .HasColumnType("integer"); + + b.Property("ScrapReasonCodeId") + .HasColumnType("integer"); + + b.Property("ScrappedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TransferredQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UomId") + .HasColumnType("integer"); + + b.HasKey("RunOutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RunStageId"); + + b.HasIndex("ScrapReasonCodeId"); + + b.HasIndex("UomId"); + + b.ToTable("run_stage_outputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalaryComponent", b => + { + b.Property("SalaryComponentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalaryComponentId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ComponentType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsEpfEtfApplicable") + .HasColumnType("boolean"); + + b.Property("IsTaxable") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("SalaryComponentId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_salary_components", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesDayEnd", b => + { + b.Property("SalesDayEndId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesDayEndId")); + + b.Property("BalanceTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BundleCount") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("BusinessDate") + .HasColumnType("date"); + + b.Property("CashierUserId") + .HasColumnType("integer"); + + b.Property("ClosedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ClosedBy") + .HasColumnType("integer"); + + b.Property("CostOfGoodsSold") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SlipCount") + .HasColumnType("integer"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("SalesDayEndId"); + + b.HasIndex("ClosedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("CashierUserId", "BusinessDate") + .IsUnique(); + + b.ToTable("sales_day_ends", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoice", b => + { + b.Property("SalesInvoiceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesInvoiceId")); + + b.Property("BalanceAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("CreatorUserId") + .HasColumnType("integer"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("CustomerSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CustomerSnapshotTaxNo") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("InvoiceDate") + .HasColumnType("timestamp with time zone"); + + b.Property("InvoiceNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("InvoiceType") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("B2C"); + + b.Property("NetPayable") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RoundOff") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesInvoiceId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatorUserId"); + + b.HasIndex("CustomerId"); + + b.HasIndex("InvoiceDate"); + + b.HasIndex("InvoiceNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_invoices", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoiceLine", b => + { + b.Property("SalesInvoiceLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesInvoiceLineId")); + + b.Property("BaseCost") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DiscountAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DiscountMode") + .HasColumnType("integer"); + + b.Property("DiscountPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("FreeQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("IsFreeIssue") + .HasColumnType("boolean"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("NetUnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ParentLineId") + .HasColumnType("integer"); + + b.Property("PriceSource") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SalesInvoiceId") + .HasColumnType("integer"); + + b.Property("TaxAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesInvoiceLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SalesInvoiceId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_invoice_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoicePayment", b => + { + b.Property("SalesInvoicePaymentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesInvoicePaymentId")); + + b.Property("Amount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BankAccountName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("GlBankAccountId") + .HasColumnType("bigint"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PaymentDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Reference") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("SalesInvoiceId") + .HasColumnType("integer"); + + b.HasKey("SalesInvoicePaymentId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("SalesInvoiceId"); + + b.ToTable("sales_invoice_payments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturn", b => + { + b.Property("ReturnId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReasonCodeId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("ReturnId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("CustomerId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("ReasonCodeId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_returns", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturnLine", b => + { + b.Property("ReturnLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReturnId") + .HasColumnType("integer"); + + b.Property("SalesInvoiceLineId") + .HasColumnType("integer"); + + b.HasKey("ReturnLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("ReturnId"); + + b.HasIndex("SalesInvoiceLineId"); + + b.ToTable("sales_return_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlip", b => + { + b.Property("SalesSlipId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesSlipId")); + + b.Property("BalanceAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CashierUserId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("CustomerSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DayEndId") + .HasColumnType("integer"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SlipDate") + .HasColumnType("timestamp with time zone"); + + b.Property("SlipNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesSlipId"); + + b.HasIndex("CashierUserId"); + + b.HasIndex("CustomerId"); + + b.HasIndex("DayEndId"); + + b.HasIndex("SlipDate"); + + b.HasIndex("SlipNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_slips", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlipLine", b => + { + b.Property("SalesSlipLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesSlipLineId")); + + b.Property("BaseCost") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DiscountAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DiscountMode") + .HasColumnType("integer"); + + b.Property("DiscountPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("FreeQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("IsFreeIssue") + .HasColumnType("boolean"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("NetUnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ParentLineId") + .HasColumnType("integer"); + + b.Property("PriceSource") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SalesSlipId") + .HasColumnType("integer"); + + b.Property("TaxAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesSlipLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SalesSlipId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_slip_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Serial", b => + { + b.Property("SerialId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SerialId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("SerialNo") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("SerialId"); + + b.HasIndex("ItemId", "SerialNo") + .IsUnique(); + + b.ToTable("serials", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageEdge", b => + { + b.Property("EdgeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EdgeId")); + + b.Property("ChildStageId") + .HasColumnType("integer"); + + b.Property("ParentStageId") + .HasColumnType("integer"); + + b.Property("TemplateId") + .HasColumnType("integer"); + + b.HasKey("EdgeId"); + + b.HasIndex("ChildStageId"); + + b.HasIndex("TemplateId"); + + b.HasIndex("ParentStageId", "ChildStageId") + .IsUnique(); + + b.ToTable("stage_edges", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageInput", b => + { + b.Property("InputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("InputId")); + + b.Property("FromOutputId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyPerBatch") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyUnit") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Source") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("StageId") + .HasColumnType("integer"); + + b.HasKey("InputId"); + + b.HasIndex("FromOutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("StageId"); + + b.ToTable("stage_inputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageOutput", b => + { + b.Property("OutputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("OutputId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("QtyPerBatch") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("StageId") + .HasColumnType("integer"); + + b.Property("UomId") + .HasColumnType("integer"); + + b.HasKey("OutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("StageId"); + + b.HasIndex("UomId"); + + b.ToTable("stage_outputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustment", b => + { + b.Property("AdjustmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AdjustmentId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReasonCodeId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("AdjustmentId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("ReasonCodeId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("stock_adjustments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustmentLine", b => + { + b.Property("AdjLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AdjLineId")); + + b.Property("AdjustmentId") + .HasColumnType("integer"); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyDelta") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.HasKey("AdjLineId"); + + b.HasIndex("AdjustmentId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SerialId"); + + b.ToTable("stock_adjustment_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCount", b => + { + b.Property("CountId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CountId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CountType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("CountId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("stock_counts", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCountLine", b => + { + b.Property("CountLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CountLineId")); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("CountId") + .HasColumnType("integer"); + + b.Property("CountedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("SystemQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Variance") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("CountLineId"); + + b.HasIndex("BinId"); + + b.HasIndex("CountId"); + + b.HasIndex("ItemId"); + + b.ToTable("stock_count_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLayer", b => + { + b.Property("LayerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LayerId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("GrnLineId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyReceived") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyRemaining") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReceiptDate") + .HasColumnType("timestamp with time zone"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("LayerId"); + + b.HasIndex("BatchId"); + + b.HasIndex("GrnLineId"); + + b.HasIndex("SerialId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("ItemId", "WarehouseId", "ReceiptDate", "LayerId"); + + b.ToTable("stock_layers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLedger", b => + { + b.Property("LedgerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LedgerId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Direction") + .IsRequired() + .HasMaxLength(5) + .HasColumnType("character varying(5)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyBase") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RunningBalance") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("SourceDocId") + .HasColumnType("integer"); + + b.Property("SourceDocType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.Property("Value") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("LedgerId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("SerialId"); + + b.HasIndex("UserId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("SourceDocType", "SourceDocId"); + + b.HasIndex("ItemId", "WarehouseId", "CreatedAt"); + + b.HasIndex("ItemId", "WarehouseId", "LedgerId"); + + b.ToTable("stock_ledger", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransfer", b => + { + b.Property("TransferId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TransferId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DestWarehouseId") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SrcWarehouseId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("TransferId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DestWarehouseId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("SrcWarehouseId"); + + b.HasIndex("Status"); + + b.ToTable("stock_transfers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransferLine", b => + { + b.Property("TransferLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TransferLineId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("DestBinId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyReceived") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("SrcBinId") + .HasColumnType("integer"); + + b.Property("TransferId") + .HasColumnType("integer"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.HasKey("TransferLineId"); + + b.HasIndex("BatchId"); + + b.HasIndex("DestBinId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SerialId"); + + b.HasIndex("SrcBinId"); + + b.HasIndex("TransferId"); + + b.ToTable("stock_transfer_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubCategory", b => + { + b.Property("SubCategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SubCategoryId")); + + b.Property("CategoryId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("SubCategoryId"); + + b.HasIndex("Status"); + + b.HasIndex("CategoryId", "Name") + .IsUnique(); + + b.ToTable("subcategories", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubNavItem", b => + { + b.Property("SubNavItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SubNavItemId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Href") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Icon") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("NavItemId") + .HasColumnType("integer"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.HasKey("SubNavItemId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("NavItemId"); + + b.ToTable("sub_nav_items", (string)null); + + b.HasData( + new + { + SubNavItemId = 1, + Code = "products.item", + Href = "/dashboard/products", + Label = "Item", + NavItemId = 2, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 2, + Code = "products.category", + Href = "/dashboard/products/categories", + Label = "Category", + NavItemId = 2, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 3, + Code = "products.brand", + Href = "/dashboard/products/brands", + Label = "Brand", + NavItemId = 2, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 4, + Code = "products.item-type", + Href = "/dashboard/products/item-types", + Label = "Item Type", + NavItemId = 2, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 5, + Code = "products.uom", + Href = "/dashboard/products/uoms", + Label = "UOM", + NavItemId = 2, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 6, + Code = "products.configuration", + Href = "/dashboard/products/settings", + Label = "Configuration", + NavItemId = 2, + SortOrder = 6, + Status = "Active" + }, + new + { + SubNavItemId = 43, + Code = "products.tax-rates", + Href = "/dashboard/products/tax-rates", + Label = "Tax Rates", + NavItemId = 2, + SortOrder = 7, + Status = "Active" + }, + new + { + SubNavItemId = 29, + Code = "settings.branches", + Href = "/dashboard/settings/branches", + Label = "Branches", + NavItemId = 9, + SortOrder = 0, + Status = "Active" + }, + new + { + SubNavItemId = 7, + Code = "settings.roles", + Href = "/dashboard/settings/roles", + Label = "Roles", + NavItemId = 9, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 8, + Code = "settings.users", + Href = "/dashboard/settings/users", + Label = "Users", + NavItemId = 9, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 24, + Code = "settings.notification-config", + Href = "/dashboard/settings/notification-config", + Label = "Notification Config", + NavItemId = 9, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 40, + Code = "sales.invoices", + Href = "/dashboard/sales/invoices", + Label = "Sales", + NavItemId = 13, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 23, + Code = "sales.bundle-templates", + Href = "/dashboard/sales/bundles/templates", + Label = "Bundle Templates", + NavItemId = 13, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 41, + Code = "sales.free-issues", + Href = "/dashboard/sales/free-issues", + Label = "Free Issues", + NavItemId = 13, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 42, + Code = "sales.day-end", + Href = "/dashboard/sales/day-end", + Label = "Day End", + NavItemId = 13, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 30, + Code = "procurement.vendors", + Href = "/dashboard/vendors", + Label = "Vendors", + NavItemId = 4, + SortOrder = 0, + Status = "Active" + }, + new + { + SubNavItemId = 17, + Code = "procurement.requisitions", + Href = "/dashboard/procurement/requisitions", + Label = "Requisitions", + NavItemId = 4, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 18, + Code = "procurement.rfqs", + Href = "/dashboard/procurement/rfqs", + Label = "RFQs", + NavItemId = 4, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 19, + Code = "procurement.purchase-orders", + Href = "/dashboard/procurement/purchase-orders", + Label = "Purchase Orders", + NavItemId = 4, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 20, + Code = "procurement.purchase-returns", + Href = "/dashboard/procurement/purchase-returns", + Label = "Purchase Returns", + NavItemId = 4, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 28, + Code = "procurement.purchase-invoices", + Href = "/dashboard/procurement/purchase-invoices", + Label = "Purchase Invoices", + NavItemId = 4, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 9, + Code = "ledgers.trial-balance", + Href = "/dashboard/ledgers/trial-balance", + Label = "Trial Balance", + NavItemId = 11, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 10, + Code = "ledgers.balance-sheet", + Href = "/dashboard/ledgers/balance-sheet", + Label = "Balance Sheet", + NavItemId = 11, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 11, + Code = "ledgers.general-ledger", + Href = "/dashboard/ledgers/general-ledger", + Label = "General Ledger", + NavItemId = 11, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 12, + Code = "ledgers.profit-and-loss", + Href = "/dashboard/ledgers/profit-and-loss", + Label = "Profit & Loss", + NavItemId = 11, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 13, + Code = "ledgers.cash-flow", + Href = "/dashboard/ledgers/cash-flow", + Label = "Cash Flow", + NavItemId = 11, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 14, + Code = "ledgers.budget-vs-actual", + Href = "/dashboard/ledgers/budget-vs-actual", + Label = "Budget vs Actual", + NavItemId = 11, + SortOrder = 6, + Status = "Active" + }, + new + { + SubNavItemId = 16, + Code = "ledgers.tax-report", + Href = "/dashboard/ledgers/tax-report", + Label = "Tax Report", + NavItemId = 11, + SortOrder = 7, + Status = "Active" + }, + new + { + SubNavItemId = 15, + Code = "accounts.bank-accounts", + Href = "/dashboard/accounts/bank-accounts", + Label = "Cash / Bank Accounts", + NavItemId = 12, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 21, + Code = "accounts.cheque-books", + Href = "/dashboard/accounts/cheque-books", + Label = "Cheque Books", + NavItemId = 12, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 22, + Code = "accounts.received-cheques", + Href = "/dashboard/accounts/received-cheques", + Label = "Received Cheques", + NavItemId = 12, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 27, + Code = "production.templates", + Href = "/dashboard/production/templates", + Label = "Templates", + NavItemId = 14, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 25, + Code = "production.runs", + Href = "/dashboard/production/runs", + Label = "Runs", + NavItemId = 14, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 26, + Code = "production.produced", + Href = "/dashboard/production/produced", + Label = "Produced", + NavItemId = 14, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 31, + Code = "stock.ledger", + Href = "/dashboard/stock/ledger", + Label = "Stock Ledger", + NavItemId = 6, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 32, + Code = "stock.enquiry", + Href = "/dashboard/stock/enquiry", + Label = "Stock Enquiry", + NavItemId = 6, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 33, + Code = "stock.valuation", + Href = "/dashboard/stock/valuation", + Label = "Valuation", + NavItemId = 6, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 34, + Code = "stock.transfers", + Href = "/dashboard/stock/transfers", + Label = "Transfers", + NavItemId = 6, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 35, + Code = "stock.adjustments", + Href = "/dashboard/stock/adjustments", + Label = "Adjustments", + NavItemId = 6, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 36, + Code = "stock.counts", + Href = "/dashboard/stock/counts", + Label = "Counts", + NavItemId = 6, + SortOrder = 6, + Status = "Active" + }, + new + { + SubNavItemId = 37, + Code = "stock.reorder-alerts", + Href = "/dashboard/stock/reorder-alerts", + Label = "Reorder Alerts", + NavItemId = 6, + SortOrder = 7, + Status = "Active" + }, + new + { + SubNavItemId = 38, + Code = "stock.wastage", + Href = "/dashboard/stock/wastage", + Label = "Wastage", + NavItemId = 6, + SortOrder = 8, + Status = "Active" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicket", b => + { + b.Property("TicketId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TicketId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Subject") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.HasKey("TicketId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("Status"); + + b.ToTable("support_tickets", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicketMessage", b => + { + b.Property("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("MessageId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsFromAdmin") + .HasColumnType("boolean"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("SenderUserId") + .HasColumnType("integer"); + + b.Property("TicketId") + .HasColumnType("integer"); + + b.HasKey("MessageId"); + + b.HasIndex("TicketId", "CreatedAt"); + + b.ToTable("support_ticket_messages", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TaxRate", b => + { + b.Property("TaxRateId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TaxRateId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Percentage") + .HasPrecision(5, 2) + .HasColumnType("numeric(5,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("TaxRateId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("tax_rates", (string)null); + + b.HasData( + new + { + TaxRateId = 1, + Code = "STANDARD", + CreatedAt = new DateTime(2026, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc), + Name = "Standard", + Percentage = 15m, + RowVersion = 0u, + Status = "Active" + }, + new + { + TaxRateId = 2, + Code = "ZERO", + CreatedAt = new DateTime(2026, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc), + Name = "Zero-Rated", + Percentage = 0m, + RowVersion = 0u, + Status = "Active" + }, + new + { + TaxRateId = 3, + Code = "EXEMPT", + CreatedAt = new DateTime(2026, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc), + Name = "Exempt", + Percentage = 0m, + RowVersion = 0u, + Status = "Active" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TaxSlab", b => + { + b.Property("TaxSlabId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TaxSlabId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveTo") + .HasColumnType("timestamp with time zone"); + + b.Property("LowerBound") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("Rate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("UpperBound") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.HasKey("TaxSlabId"); + + b.HasIndex("EffectiveFrom"); + + b.ToTable("hr_tax_slabs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => + { + b.Property("StageId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("StageId")); + + b.Property("EstimatedMinutes") + .HasColumnType("integer"); + + b.Property("FieldDefs") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("PosX") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PosY") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RoleLabel") + .HasMaxLength(60) + .HasColumnType("character varying(60)"); + + b.Property("TemplateId") + .HasColumnType("integer"); + + b.HasKey("StageId"); + + b.HasIndex("TemplateId"); + + b.ToTable("template_stages", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Uom", b => + { + b.Property("UomId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("UomId")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("UomId"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("uoms", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.User", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("UserId")); + + b.Property("AuthUserId") + .HasColumnType("uuid") + .HasColumnName("auth_user_id"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Email") + .HasMaxLength(320) + .HasColumnType("character varying(320)"); + + b.Property("RoleId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("UserId"); + + b.HasIndex("AuthUserId") + .IsUnique(); + + b.HasIndex("Email") + .IsUnique(); + + b.HasIndex("RoleId"); + + b.HasIndex("Username") + .IsUnique(); + + b.ToTable("users", (string)null); + + b.HasData( + new + { + UserId = 1, + DisplayName = "System", + Status = "Active", + Username = "system" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Vendor", b => + { + b.Property("VendorId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("VendorId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Currency") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(3) + .HasColumnType("character varying(3)") + .HasDefaultValue("LKR"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TaxReg") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Terms") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("VendorId"); + + b.HasIndex("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("vendors", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => + { + b.Property("QuotationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("QuotationId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("RfqId") + .HasColumnType("integer"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.HasKey("QuotationId"); + + b.HasIndex("VendorId"); + + b.HasIndex("RfqId", "VendorId") + .IsUnique(); + + b.ToTable("vendor_quotations", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotationLine", b => + { + b.Property("QuotationLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("QuotationLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LeadDays") + .HasColumnType("integer"); + + b.Property("QuotationId") + .HasColumnType("integer"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("QuotationLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("QuotationId"); + + b.ToTable("vendor_quotation_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Warehouse", b => + { + b.Property("WarehouseId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("WarehouseId")); + + b.Property("Address") + .HasColumnType("text"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Phone") + .HasColumnType("text"); + + b.HasKey("WarehouseId"); + + b.HasIndex("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("warehouses", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.WorkShift", b => + { + b.Property("WorkShiftId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("WorkShiftId")); + + b.Property("BreakMinutes") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EndTime") + .HasColumnType("interval"); + + b.Property("GraceMinutes") + .HasColumnType("integer"); + + b.Property("IsOvernight") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("OtMultiplier") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("StandardWorkingMinutes") + .HasColumnType("integer"); + + b.Property("StartTime") + .HasColumnType("interval"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WorkingDaysMask") + .HasColumnType("integer"); + + b.HasKey("WorkShiftId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_work_shifts", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceRecord", b => + { + b.HasOne("ERPCore.Domain.Entities.AttendanceUploadBatch", "AttendanceUploadBatch") + .WithMany() + .HasForeignKey("AttendanceUploadBatchId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.WorkShift", "WorkShift") + .WithMany() + .HasForeignKey("WorkShiftId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("AttendanceUploadBatch"); + + b.Navigation("Employee"); + + b.Navigation("WorkShift"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AuditLog", b => + { + b.HasOne("ERPCore.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Batch", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Bin", b => + { + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany("Bins") + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BranchConfig", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSale", b => + { + b.HasOne("ERPCore.Domain.Entities.BundleSaleTemplate", "BundleSaleTemplate") + .WithMany() + .HasForeignKey("BundleSaleTemplateId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "CashierUser") + .WithMany() + .HasForeignKey("CashierUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesDayEnd", "DayEnd") + .WithMany("BundleSales") + .HasForeignKey("DayEndId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BundleSaleTemplate"); + + b.Navigation("CashierUser"); + + b.Navigation("Customer"); + + b.Navigation("DayEnd"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleLine", b => + { + b.HasOne("ERPCore.Domain.Entities.BundleSale", "BundleSale") + .WithMany("Lines") + .HasForeignKey("BundleSaleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BundleSale"); + + b.Navigation("Item"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplateLine", b => + { + b.HasOne("ERPCore.Domain.Entities.BundleSaleTemplate", "BundleSaleTemplate") + .WithMany("Lines") + .HasForeignKey("BundleSaleTemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BundleSaleTemplate"); + + b.Navigation("Item"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Customer", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "DefaultWarehouse") + .WithMany() + .HasForeignKey("DefaultWarehouseId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Branch"); + + b.Navigation("DefaultWarehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Department", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Employee", "HeadEmployee") + .WithMany() + .HasForeignKey("HeadEmployeeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Department", "ParentDepartment") + .WithMany() + .HasForeignKey("ParentDepartmentId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Branch"); + + b.Navigation("HeadEmployee"); + + b.Navigation("ParentDepartment"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Employee", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Department", "Department") + .WithMany() + .HasForeignKey("DepartmentId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Designation", "Designation") + .WithMany() + .HasForeignKey("DesignationId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.EmploymentType", "EmploymentType") + .WithMany() + .HasForeignKey("EmploymentTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Employee", "ReportingManager") + .WithMany() + .HasForeignKey("ReportingManagerId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithOne() + .HasForeignKey("ERPCore.Domain.Entities.Employee", "UserId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.WorkShift", "WorkShift") + .WithMany() + .HasForeignKey("WorkShiftId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Department"); + + b.Navigation("Designation"); + + b.Navigation("EmploymentType"); + + b.Navigation("ReportingManager"); + + b.Navigation("User"); + + b.Navigation("WorkShift"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeBankDetail", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeDocument", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.HrDocumentType", "HrDocumentType") + .WithMany() + .HasForeignKey("HrDocumentTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("HrDocumentType"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeLoan", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructure", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructureLine", b => + { + b.HasOne("ERPCore.Domain.Entities.EmployeeSalaryStructure", "EmployeeSalaryStructure") + .WithMany("Lines") + .HasForeignKey("EmployeeSalaryStructureId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalaryComponent", "SalaryComponent") + .WithMany() + .HasForeignKey("SalaryComponentId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("EmployeeSalaryStructure"); + + b.Navigation("SalaryComponent"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Grn", 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.HasOne("ERPCore.Domain.Entities.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("PoId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.PurchaseInvoice", "PurchaseInvoice") + .WithMany() + .HasForeignKey("PurchaseInvoiceId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("PurchaseInvoice"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Vendor"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", "Batch") + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", "Bin") + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Grn", "Grn") + .WithMany("Lines") + .HasForeignKey("GrnId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PoLine", "PoLine") + .WithMany() + .HasForeignKey("PoLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Batch"); + + b.Navigation("Bin"); + + b.Navigation("Grn"); + + b.Navigation("Item"); + + b.Navigation("PoLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLineWarrantyNumber", b => + { + b.HasOne("ERPCore.Domain.Entities.GrnLine", "GrnLine") + .WithMany("WarrantyNumbers") + .HasForeignKey("GrnLineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GrnLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Item", b => + { + b.HasOne("ERPCore.Domain.Entities.Uom", "BaseUom") + .WithMany() + .HasForeignKey("BaseUomId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Brand", "Brand") + .WithMany() + .HasForeignKey("BrandId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Category", "Category") + .WithMany() + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "DefaultVendor") + .WithMany() + .HasForeignKey("DefaultVendorId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.SubCategory", "SubCategory") + .WithMany() + .HasForeignKey("SubCategoryId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.TaxRate", "TaxRate") + .WithMany() + .HasForeignKey("TaxRateId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("BaseUom"); + + b.Navigation("Brand"); + + b.Navigation("Category"); + + b.Navigation("DefaultVendor"); + + b.Navigation("SubCategory"); + + b.Navigation("TaxRate"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ItemReorder", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany("ReorderSettings") + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveBalance", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.LeaveType", "LeaveType") + .WithMany() + .HasForeignKey("LeaveTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("LeaveType"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveRequest", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.LeaveType", "LeaveType") + .WithMany() + .HasForeignKey("LeaveTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("LeaveType"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoanInstallment", b => + { + b.HasOne("ERPCore.Domain.Entities.EmployeeLoan", "EmployeeLoan") + .WithMany("Installments") + .HasForeignKey("EmployeeLoanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PayrollRun", "PayrollRun") + .WithMany() + .HasForeignKey("PayrollRunId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("EmployeeLoan"); + + b.Navigation("PayrollRun"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoginActivity", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfigModule", b => + { + b.HasOne("ERPCore.Domain.Entities.NotificationConfig", "NotificationConfig") + .WithMany("Modules") + .HasForeignKey("NotificationConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("NotificationConfig"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationRecipient", b => + { + b.HasOne("ERPCore.Domain.Entities.Notification", "Notification") + .WithMany("Recipients") + .HasForeignKey("NotificationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Notification"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NumberSequence", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PayrollRun", "PayrollRun") + .WithMany("Lines") + .HasForeignKey("PayrollRunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("PayrollRun"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLineComponent", b => + { + b.HasOne("ERPCore.Domain.Entities.PayrollLine", "PayrollLine") + .WithMany("Components") + .HasForeignKey("PayrollLineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalaryComponent", "SalaryComponent") + .WithMany() + .HasForeignKey("SalaryComponentId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("PayrollLine"); + + b.Navigation("SalaryComponent"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollRun", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Branch"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Payslip", b => + { + b.HasOne("ERPCore.Domain.Entities.PayrollLine", "PayrollLine") + .WithOne() + .HasForeignKey("ERPCore.Domain.Entities.Payslip", "PayrollLineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PayrollLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Permission", b => + { + b.HasOne("ERPCore.Domain.Entities.NavItem", "NavItem") + .WithMany() + .HasForeignKey("NavItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ERPCore.Domain.Entities.SubNavItem", "SubNavItem") + .WithMany() + .HasForeignKey("SubNavItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("NavItem"); + + b.Navigation("SubNavItem"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PoLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseOrder", "PurchaseOrder") + .WithMany("Lines") + .HasForeignKey("PoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductConfig", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b => + { + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "CancelReason") + .WithMany() + .HasForeignKey("CancelReasonCodeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Bin", "OutputBin") + .WithMany() + .HasForeignKey("OutputBinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") + .WithMany("Runs") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CancelReason"); + + b.Navigation("Creator"); + + b.Navigation("OutputBin"); + + b.Navigation("Template"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionTemplate", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", 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.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoiceLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Grn", "Grn") + .WithMany() + .HasForeignKey("GrnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseInvoice", "PurchaseInvoice") + .WithMany("Lines") + .HasForeignKey("PurchaseInvoiceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Grn"); + + b.Navigation("PurchaseInvoice"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoicePayment", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseInvoice", "PurchaseInvoice") + .WithMany("Payments") + .HasForeignKey("PurchaseInvoiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("PurchaseInvoice"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Approver") + .WithMany() + .HasForeignKey("ApproverUserId"); + + 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.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") + .WithMany() + .HasForeignKey("RequisitionId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Approver"); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("Requisition"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturn", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ReasonCode") + .WithMany() + .HasForeignKey("ReasonCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("ReasonCode"); + + b.Navigation("Vendor"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturnLine", b => + { + b.HasOne("ERPCore.Domain.Entities.GrnLine", "GrnLine") + .WithMany() + .HasForeignKey("GrnLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseReturn", "Return") + .WithMany("Lines") + .HasForeignKey("ReturnId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GrnLine"); + + b.Navigation("Item"); + + b.Navigation("Return"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "Requester") + .WithMany() + .HasForeignKey("RequestedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Requester"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RequisitionLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") + .WithMany("Lines") + .HasForeignKey("RequisitionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Requisition"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") + .WithMany() + .HasForeignKey("RequisitionId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Requisition"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RfqLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Rfq", "Rfq") + .WithMany("Lines") + .HasForeignKey("RfqId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Rfq"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RolePermission", b => + { + b.HasOne("ERPCore.Domain.Entities.Permission", "Permission") + .WithMany() + .HasForeignKey("PermissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Role", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Permission"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunEdge", b => + { + b.HasOne("ERPCore.Domain.Entities.RunStage", "ChildRunStage") + .WithMany() + .HasForeignKey("ChildRunStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "ParentRunStage") + .WithMany() + .HasForeignKey("ParentRunStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ProductionRun", "Run") + .WithMany("Edges") + .HasForeignKey("RunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildRunStage"); + + b.Navigation("ParentRunStage"); + + b.Navigation("Run"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStage", b => + { + b.HasOne("ERPCore.Domain.Entities.ProductionRun", "Run") + .WithMany("Stages") + .HasForeignKey("RunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "TemplateStage") + .WithMany() + .HasForeignKey("TemplateStageId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Run"); + + b.Navigation("TemplateStage"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageEvent", b => + { + b.HasOne("ERPCore.Domain.Entities.ProductionRun", "Run") + .WithMany("Events") + .HasForeignKey("RunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "RunStage") + .WithMany("Events") + .HasForeignKey("RunStageId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Run"); + + b.Navigation("RunStage"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageInput", b => + { + b.HasOne("ERPCore.Domain.Entities.RunStageOutput", "FromRunOutput") + .WithMany() + .HasForeignKey("FromRunOutputId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "RunStage") + .WithMany("Inputs") + .HasForeignKey("RunStageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromRunOutput"); + + b.Navigation("Item"); + + b.Navigation("RunStage"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageOutput", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "RunStage") + .WithMany("Outputs") + .HasForeignKey("RunStageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ScrapReason") + .WithMany() + .HasForeignKey("ScrapReasonCodeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Uom", "Uom") + .WithMany() + .HasForeignKey("UomId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Item"); + + b.Navigation("RunStage"); + + b.Navigation("ScrapReason"); + + b.Navigation("Uom"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesDayEnd", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "CashierUser") + .WithMany() + .HasForeignKey("CashierUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "ClosedByUser") + .WithMany() + .HasForeignKey("ClosedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CashierUser"); + + b.Navigation("ClosedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoice", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatorUserId"); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("Customer"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoiceLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesInvoice", "SalesInvoice") + .WithMany("Lines") + .HasForeignKey("SalesInvoiceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SalesInvoice"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoicePayment", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesInvoice", "SalesInvoice") + .WithMany("Payments") + .HasForeignKey("SalesInvoiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("SalesInvoice"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturn", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ReasonCode") + .WithMany() + .HasForeignKey("ReasonCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("Customer"); + + b.Navigation("ReasonCode"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturnLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesReturn", "Return") + .WithMany("Lines") + .HasForeignKey("ReturnId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesInvoiceLine", "SalesInvoiceLine") + .WithMany() + .HasForeignKey("SalesInvoiceLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Item"); + + b.Navigation("Return"); + + b.Navigation("SalesInvoiceLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlip", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "CashierUser") + .WithMany() + .HasForeignKey("CashierUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesDayEnd", "DayEnd") + .WithMany("Slips") + .HasForeignKey("DayEndId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CashierUser"); + + b.Navigation("Customer"); + + b.Navigation("DayEnd"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlipLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesSlip", "SalesSlip") + .WithMany("Lines") + .HasForeignKey("SalesSlipId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SalesSlip"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Serial", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageEdge", b => + { + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "ChildStage") + .WithMany() + .HasForeignKey("ChildStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "ParentStage") + .WithMany() + .HasForeignKey("ParentStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") + .WithMany("Edges") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildStage"); + + b.Navigation("ParentStage"); + + b.Navigation("Template"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageInput", b => + { + b.HasOne("ERPCore.Domain.Entities.StageOutput", "FromOutput") + .WithMany() + .HasForeignKey("FromOutputId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "Stage") + .WithMany("Inputs") + .HasForeignKey("StageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromOutput"); + + b.Navigation("Item"); + + b.Navigation("Stage"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageOutput", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "Stage") + .WithMany("Outputs") + .HasForeignKey("StageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Uom", "Uom") + .WithMany() + .HasForeignKey("UomId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Item"); + + b.Navigation("Stage"); + + b.Navigation("Uom"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustment", 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.HasOne("ERPCore.Domain.Entities.ReasonCode", "ReasonCode") + .WithMany() + .HasForeignKey("ReasonCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("ReasonCode"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustmentLine", b => + { + b.HasOne("ERPCore.Domain.Entities.StockAdjustment", "Adjustment") + .WithMany("Lines") + .HasForeignKey("AdjustmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Batch", null) + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", null) + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Adjustment"); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCount", 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.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCountLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.StockCount", "Count") + .WithMany("Lines") + .HasForeignKey("CountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Count"); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLayer", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", "Batch") + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.GrnLine", "GrnLine") + .WithMany() + .HasForeignKey("GrnLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", "Serial") + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Batch"); + + b.Navigation("GrnLine"); + + b.Navigation("Item"); + + b.Navigation("Serial"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLedger", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", null) + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", null) + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", null) + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", null) + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransfer", 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.HasOne("ERPCore.Domain.Entities.Warehouse", "DestWarehouse") + .WithMany() + .HasForeignKey("DestWarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "SrcWarehouse") + .WithMany() + .HasForeignKey("SrcWarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("DestWarehouse"); + + b.Navigation("SrcWarehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransferLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", null) + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("DestBinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", null) + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("SrcBinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.StockTransfer", "Transfer") + .WithMany("Lines") + .HasForeignKey("TransferId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Transfer"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubCategory", b => + { + b.HasOne("ERPCore.Domain.Entities.Category", "Category") + .WithMany("SubCategories") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubNavItem", b => + { + b.HasOne("ERPCore.Domain.Entities.NavItem", "NavItem") + .WithMany("Children") + .HasForeignKey("NavItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("NavItem"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicketMessage", b => + { + b.HasOne("ERPCore.Domain.Entities.SupportTicket", "Ticket") + .WithMany("Messages") + .HasForeignKey("TicketId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ticket"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => + { + b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") + .WithMany("Stages") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Template"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.User", b => + { + b.HasOne("ERPCore.Domain.Entities.Role", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Vendor", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => + { + b.HasOne("ERPCore.Domain.Entities.Rfq", "Rfq") + .WithMany("Quotations") + .HasForeignKey("RfqId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Rfq"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotationLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.VendorQuotation", "Quotation") + .WithMany("Lines") + .HasForeignKey("QuotationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Quotation"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Warehouse", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSale", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplate", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Category", b => + { + b.Navigation("SubCategories"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeLoan", b => + { + b.Navigation("Installments"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructure", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Grn", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLine", b => + { + b.Navigation("WarrantyNumbers"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Item", b => + { + b.Navigation("ReorderSettings"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NavItem", b => + { + b.Navigation("Children"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Notification", b => + { + b.Navigation("Recipients"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => + { + b.Navigation("Modules"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => + { + b.Navigation("Components"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollRun", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b => + { + b.Navigation("Edges"); + + b.Navigation("Events"); + + b.Navigation("Stages"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionTemplate", b => + { + b.Navigation("Edges"); + + b.Navigation("Runs"); + + b.Navigation("Stages"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", b => + { + b.Navigation("Lines"); + + b.Navigation("Payments"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturn", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => + { + b.Navigation("Lines"); + + b.Navigation("Quotations"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStage", b => + { + b.Navigation("Events"); + + b.Navigation("Inputs"); + + b.Navigation("Outputs"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesDayEnd", b => + { + b.Navigation("BundleSales"); + + b.Navigation("Slips"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoice", b => + { + b.Navigation("Lines"); + + b.Navigation("Payments"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturn", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlip", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustment", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCount", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransfer", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicket", b => + { + b.Navigation("Messages"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => + { + b.Navigation("Inputs"); + + b.Navigation("Outputs"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Warehouse", b => + { + b.Navigation("Bins"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Backend/ERPCore/Migrations/20260916102635_BranchIsolationPhase1.cs b/Backend/ERPCore/Migrations/20260916102635_BranchIsolationPhase1.cs new file mode 100644 index 0000000..d2f9360 --- /dev/null +++ b/Backend/ERPCore/Migrations/20260916102635_BranchIsolationPhase1.cs @@ -0,0 +1,302 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace ERPCore.Migrations +{ + /// + public partial class BranchIsolationPhase1 : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_number_sequences_doc_type_year", + table: "number_sequences"); + + migrationBuilder.AddColumn( + name: "BranchId", + table: "vendors", + type: "integer", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "BranchId", + table: "rfqs", + type: "integer", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "BranchId", + table: "requisitions", + type: "integer", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "BranchId", + table: "purchase_orders", + type: "integer", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "BranchId", + table: "purchase_invoices", + type: "integer", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "branch_id", + table: "number_sequences", + type: "integer", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "BranchId", + table: "customers", + type: "integer", + nullable: false, + defaultValue: 0); + + // Backfill: every column just added defaulted existing rows to BranchId/branch_id = 0, + // which satisfies no FK. Point them at the deployment's single default branch + // ("BR-000"/"Main Branch" — same convention BranchConfigService.ResolveDefaultBranchIdAsync + // uses at runtime), creating it here if it doesn't exist yet so this migration is + // self-contained regardless of whether that runtime path has already run. + migrationBuilder.Sql(""" + INSERT INTO hr_branches ("Code", "Name", "Status", "CreatedAt") + SELECT 'BR-000', 'Main Branch', 'Active', now() + WHERE NOT EXISTS (SELECT 1 FROM hr_branches WHERE "Code" = 'BR-000'); + """); + migrationBuilder.Sql(""" + UPDATE vendors SET "BranchId" = (SELECT "BranchId" FROM hr_branches WHERE "Code" = 'BR-000') WHERE "BranchId" = 0; + UPDATE customers SET "BranchId" = (SELECT "BranchId" FROM hr_branches WHERE "Code" = 'BR-000') WHERE "BranchId" = 0; + UPDATE requisitions SET "BranchId" = (SELECT "BranchId" FROM hr_branches WHERE "Code" = 'BR-000') WHERE "BranchId" = 0; + UPDATE rfqs SET "BranchId" = (SELECT "BranchId" FROM hr_branches WHERE "Code" = 'BR-000') WHERE "BranchId" = 0; + UPDATE purchase_orders SET "BranchId" = (SELECT "BranchId" FROM hr_branches WHERE "Code" = 'BR-000') WHERE "BranchId" = 0; + UPDATE purchase_invoices SET "BranchId" = (SELECT "BranchId" FROM hr_branches WHERE "Code" = 'BR-000') WHERE "BranchId" = 0; + UPDATE number_sequences SET branch_id = (SELECT "BranchId" FROM hr_branches WHERE "Code" = 'BR-000') WHERE branch_id = 0; + """); + + migrationBuilder.InsertData( + table: "sub_nav_items", + columns: new[] { "SubNavItemId", "Code", "Href", "Icon", "Label", "NavItemId", "SortOrder" }, + values: new object[] { 43, "products.tax-rates", "/dashboard/products/tax-rates", null, "Tax Rates", 2, 7 }); + + migrationBuilder.InsertData( + table: "permissions", + columns: new[] { "PermissionId", "Code", "NavItemId", "SubNavItemId" }, + values: new object[] { 53, "NAV:products.tax-rates", null, 43 }); + + migrationBuilder.CreateIndex( + name: "IX_vendors_BranchId", + table: "vendors", + column: "BranchId"); + + migrationBuilder.CreateIndex( + name: "IX_rfqs_BranchId", + table: "rfqs", + column: "BranchId"); + + migrationBuilder.CreateIndex( + name: "IX_requisitions_BranchId", + table: "requisitions", + column: "BranchId"); + + migrationBuilder.CreateIndex( + name: "IX_purchase_orders_BranchId", + table: "purchase_orders", + column: "BranchId"); + + migrationBuilder.CreateIndex( + name: "IX_purchase_invoices_BranchId", + table: "purchase_invoices", + column: "BranchId"); + + migrationBuilder.CreateIndex( + name: "IX_number_sequences_branch_id", + table: "number_sequences", + column: "branch_id"); + + migrationBuilder.CreateIndex( + name: "IX_number_sequences_doc_type_branch_id_year", + table: "number_sequences", + columns: new[] { "doc_type", "branch_id", "year" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_customers_BranchId", + table: "customers", + column: "BranchId"); + + migrationBuilder.AddForeignKey( + name: "FK_customers_hr_branches_BranchId", + table: "customers", + column: "BranchId", + principalTable: "hr_branches", + principalColumn: "BranchId", + onDelete: ReferentialAction.Restrict); + + migrationBuilder.AddForeignKey( + name: "FK_number_sequences_hr_branches_branch_id", + table: "number_sequences", + column: "branch_id", + principalTable: "hr_branches", + principalColumn: "BranchId", + onDelete: ReferentialAction.Restrict); + + migrationBuilder.AddForeignKey( + name: "FK_purchase_invoices_hr_branches_BranchId", + table: "purchase_invoices", + column: "BranchId", + principalTable: "hr_branches", + principalColumn: "BranchId", + onDelete: ReferentialAction.Restrict); + + migrationBuilder.AddForeignKey( + name: "FK_purchase_orders_hr_branches_BranchId", + table: "purchase_orders", + column: "BranchId", + principalTable: "hr_branches", + principalColumn: "BranchId", + onDelete: ReferentialAction.Restrict); + + migrationBuilder.AddForeignKey( + name: "FK_requisitions_hr_branches_BranchId", + table: "requisitions", + column: "BranchId", + principalTable: "hr_branches", + principalColumn: "BranchId", + onDelete: ReferentialAction.Restrict); + + migrationBuilder.AddForeignKey( + name: "FK_rfqs_hr_branches_BranchId", + table: "rfqs", + column: "BranchId", + principalTable: "hr_branches", + principalColumn: "BranchId", + onDelete: ReferentialAction.Restrict); + + migrationBuilder.AddForeignKey( + name: "FK_vendors_hr_branches_BranchId", + table: "vendors", + column: "BranchId", + principalTable: "hr_branches", + principalColumn: "BranchId", + onDelete: ReferentialAction.Restrict); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_customers_hr_branches_BranchId", + table: "customers"); + + migrationBuilder.DropForeignKey( + name: "FK_number_sequences_hr_branches_branch_id", + table: "number_sequences"); + + migrationBuilder.DropForeignKey( + name: "FK_purchase_invoices_hr_branches_BranchId", + table: "purchase_invoices"); + + migrationBuilder.DropForeignKey( + name: "FK_purchase_orders_hr_branches_BranchId", + table: "purchase_orders"); + + migrationBuilder.DropForeignKey( + name: "FK_requisitions_hr_branches_BranchId", + table: "requisitions"); + + migrationBuilder.DropForeignKey( + name: "FK_rfqs_hr_branches_BranchId", + table: "rfqs"); + + migrationBuilder.DropForeignKey( + name: "FK_vendors_hr_branches_BranchId", + table: "vendors"); + + migrationBuilder.DropIndex( + name: "IX_vendors_BranchId", + table: "vendors"); + + migrationBuilder.DropIndex( + name: "IX_rfqs_BranchId", + table: "rfqs"); + + migrationBuilder.DropIndex( + name: "IX_requisitions_BranchId", + table: "requisitions"); + + migrationBuilder.DropIndex( + name: "IX_purchase_orders_BranchId", + table: "purchase_orders"); + + migrationBuilder.DropIndex( + name: "IX_purchase_invoices_BranchId", + table: "purchase_invoices"); + + migrationBuilder.DropIndex( + name: "IX_number_sequences_branch_id", + table: "number_sequences"); + + migrationBuilder.DropIndex( + name: "IX_number_sequences_doc_type_branch_id_year", + table: "number_sequences"); + + migrationBuilder.DropIndex( + name: "IX_customers_BranchId", + table: "customers"); + + migrationBuilder.DeleteData( + table: "permissions", + keyColumn: "PermissionId", + keyValue: 53); + + migrationBuilder.DeleteData( + table: "sub_nav_items", + keyColumn: "SubNavItemId", + keyValue: 43); + + migrationBuilder.DropColumn( + name: "BranchId", + table: "vendors"); + + migrationBuilder.DropColumn( + name: "BranchId", + table: "rfqs"); + + migrationBuilder.DropColumn( + name: "BranchId", + table: "requisitions"); + + migrationBuilder.DropColumn( + name: "BranchId", + table: "purchase_orders"); + + migrationBuilder.DropColumn( + name: "BranchId", + table: "purchase_invoices"); + + migrationBuilder.DropColumn( + name: "branch_id", + table: "number_sequences"); + + migrationBuilder.DropColumn( + name: "BranchId", + table: "customers"); + + migrationBuilder.CreateIndex( + name: "IX_number_sequences_doc_type_year", + table: "number_sequences", + columns: new[] { "doc_type", "year" }, + unique: true); + } + } +} diff --git a/Backend/ERPCore/Migrations/20260917052720_AddBarcodeLotScanning.Designer.cs b/Backend/ERPCore/Migrations/20260917052720_AddBarcodeLotScanning.Designer.cs new file mode 100644 index 0000000..6fb946a --- /dev/null +++ b/Backend/ERPCore/Migrations/20260917052720_AddBarcodeLotScanning.Designer.cs @@ -0,0 +1,8730 @@ +// +using System; +using ERPCore.Infra.Persistence; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace ERPCore.Migrations +{ + [DbContext(typeof(ErpDbContext))] + [Migration("20260917052720_AddBarcodeLotScanning")] + partial class AddBarcodeLotScanning + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.9") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceRecord", b => + { + b.Property("AttendanceRecordId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AttendanceRecordId")); + + b.Property("AttendanceDate") + .HasColumnType("timestamp with time zone"); + + b.Property("AttendanceStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("AttendanceUploadBatchId") + .HasColumnType("integer"); + + b.Property("CheckIn") + .HasColumnType("interval"); + + b.Property("CheckOut") + .HasColumnType("interval"); + + b.Property("DuplicateOfAttendanceRecordId") + .HasColumnType("integer"); + + b.Property("EarlyLeaveMinutes") + .HasColumnType("integer"); + + b.Property("EditedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EditedBy") + .HasColumnType("integer"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("IsManualOverride") + .HasColumnType("boolean"); + + b.Property("LateMinutes") + .HasColumnType("integer"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("OvertimeMinutes") + .HasColumnType("integer"); + + b.Property("RowValidationStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("WorkShiftId") + .HasColumnType("integer"); + + b.Property("WorkingMinutes") + .HasColumnType("integer"); + + b.HasKey("AttendanceRecordId"); + + b.HasIndex("AttendanceUploadBatchId"); + + b.HasIndex("WorkShiftId"); + + b.HasIndex("EmployeeId", "AttendanceDate"); + + b.ToTable("hr_attendance_records", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceUploadBatch", b => + { + b.Property("AttendanceUploadBatchId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AttendanceUploadBatchId")); + + b.Property("ConfirmedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ConfirmedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("OriginalFileName") + .HasMaxLength(260) + .HasColumnType("character varying(260)"); + + b.Property("PeriodEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("PeriodStart") + .HasColumnType("timestamp with time zone"); + + b.Property("RowCountDuplicate") + .HasColumnType("integer"); + + b.Property("RowCountError") + .HasColumnType("integer"); + + b.Property("RowCountTotal") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SourceType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UploadedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UploadedBy") + .HasColumnType("integer"); + + b.HasKey("AttendanceUploadBatchId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("PeriodStart", "PeriodEnd"); + + b.ToTable("hr_attendance_upload_batches", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AuditLog", b => + { + b.Property("AuditId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AuditId")); + + b.Property("Action") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("ChangeSet") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EntityId") + .HasColumnType("integer"); + + b.Property("EntityType") + .IsRequired() + .HasMaxLength(80) + .HasColumnType("character varying(80)"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("AuditId"); + + b.HasIndex("CreatedAt"); + + b.HasIndex("UserId"); + + b.HasIndex("EntityType", "EntityId"); + + b.ToTable("audit_logs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Batch", b => + { + b.Property("BatchId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BatchId")); + + b.Property("Barcode") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("BatchNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ExpiryDate") + .HasColumnType("date"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.HasKey("BatchId"); + + b.HasIndex("Barcode") + .IsUnique(); + + b.HasIndex("ItemId", "BatchNo") + .IsUnique(); + + b.ToTable("batches", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Bin", b => + { + b.Property("BinId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BinId")); + + b.Property("BinType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BinId"); + + b.HasIndex("WarehouseId", "Code") + .IsUnique(); + + b.ToTable("bins", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Branch", b => + { + b.Property("BranchId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BranchId")); + + b.Property("Address") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("PhoneNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_branches", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BranchConfig", b => + { + b.Property("ConfigId") + .HasColumnType("integer"); + + b.Property("BranchingEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.Property("WarehouseBranchingEnabled") + .HasColumnType("boolean"); + + b.HasKey("ConfigId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("branch_config", null, t => + { + t.HasCheckConstraint("ck_branch_config_singleton", "\"ConfigId\" = 1"); + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Brand", b => + { + b.Property("BrandId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BrandId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("BrandId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("brands", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSale", b => + { + b.Property("BundleSaleId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleId")); + + b.Property("BundleCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BundleDate") + .HasColumnType("timestamp with time zone"); + + b.Property("BundleName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("BundleNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BundlePrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BundleSaleTemplateId") + .HasColumnType("integer"); + + b.Property("CashierUserId") + .HasColumnType("integer"); + + b.Property("ComponentSubtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("CustomerSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DayEndId") + .HasColumnType("integer"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("MarginAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BundleSaleId"); + + b.HasIndex("BundleNo") + .IsUnique(); + + b.HasIndex("BundleSaleTemplateId"); + + b.HasIndex("CashierUserId"); + + b.HasIndex("CustomerId"); + + b.HasIndex("DayEndId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("bundle_sales", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleLine", b => + { + b.Property("BundleSaleLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleLineId")); + + b.Property("BundleSaleId") + .HasColumnType("integer"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("IncludeInBundle") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("IsComponent") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ParentLineId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BundleSaleLineId"); + + b.HasIndex("BundleSaleId"); + + b.HasIndex("ItemId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("bundle_sale_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplate", b => + { + b.Property("BundleSaleTemplateId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleTemplateId")); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TemplateCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("TemplateName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("BundleSaleTemplateId"); + + b.HasIndex("TemplateCode") + .IsUnique(); + + b.ToTable("bundle_sale_templates", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplateLine", b => + { + b.Property("BundleSaleTemplateLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BundleSaleTemplateLineId")); + + b.Property("BundleSaleTemplateId") + .HasColumnType("integer"); + + b.Property("IncludeInBundle") + .HasColumnType("boolean"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SortOrder") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("BundleSaleTemplateLineId"); + + b.HasIndex("BundleSaleTemplateId"); + + b.HasIndex("ItemId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("bundle_sale_template_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Category", b => + { + b.Property("CategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CategoryId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("CategoryId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("categories", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Customer", b => + { + b.Property("CustomerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CustomerId")); + + b.Property("AddressLine1") + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("AddressLine2") + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("City") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Country") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreditDays") + .HasColumnType("integer"); + + b.Property("CreditLimit") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CustomerCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CustomerType") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("B2C"); + + b.Property("DefaultWarehouseId") + .HasColumnType("integer"); + + b.Property("DisplayName") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Email") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Phone") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TaxRegistrationNo") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("CustomerId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CustomerCode") + .IsUnique(); + + b.HasIndex("CustomerType"); + + b.HasIndex("DefaultWarehouseId"); + + b.HasIndex("Status"); + + b.ToTable("customers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Department", b => + { + b.Property("DepartmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("DepartmentId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("HeadEmployeeId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("ParentDepartmentId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("DepartmentId"); + + b.HasIndex("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("HeadEmployeeId"); + + b.HasIndex("ParentDepartmentId"); + + b.HasIndex("Status"); + + b.ToTable("hr_departments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Designation", b => + { + b.Property("DesignationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("DesignationId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("DesignationId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_designations", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Employee", b => + { + b.Property("EmployeeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeId")); + + b.Property("AddressLine1") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("AddressLine2") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("City") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ConfirmationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Country") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DateOfBirth") + .HasColumnType("timestamp with time zone"); + + b.Property("DepartmentId") + .HasColumnType("integer"); + + b.Property("DesignationId") + .HasColumnType("integer"); + + b.Property("Email") + .HasMaxLength(320) + .HasColumnType("character varying(320)"); + + b.Property("EmergencyContactName") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("EmergencyContactPhone") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmergencyContactRelationship") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("EmployeeCode") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmploymentTypeId") + .HasColumnType("integer"); + + b.Property("EpfNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EtfNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Gender") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("HireDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LastWorkingDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Nationality") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Nic") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PersonalMobile") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PostalCode") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ProfilePhotoPath") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("ReportingManagerId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TaxIdentificationNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.Property("WorkShiftId") + .HasColumnType("integer"); + + b.HasKey("EmployeeId"); + + b.HasIndex("BranchId"); + + b.HasIndex("DepartmentId"); + + b.HasIndex("DesignationId"); + + b.HasIndex("Email"); + + b.HasIndex("EmployeeCode") + .IsUnique(); + + b.HasIndex("EmploymentTypeId"); + + b.HasIndex("ReportingManagerId"); + + b.HasIndex("Status"); + + b.HasIndex("UserId") + .IsUnique(); + + b.HasIndex("WorkShiftId"); + + b.ToTable("hr_employees", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeBankDetail", b => + { + b.Property("EmployeeBankDetailId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeBankDetailId")); + + b.Property("AccountHolderName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("AccountNumber") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BankName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("BranchName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("IsPrimary") + .HasColumnType("boolean"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("SwiftCode") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("EmployeeBankDetailId"); + + b.HasIndex("EmployeeId"); + + b.ToTable("hr_employee_bank_details", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeDocument", b => + { + b.Property("EmployeeDocumentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeDocumentId")); + + b.Property("ContentType") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("ExpiryDate") + .HasColumnType("timestamp with time zone"); + + b.Property("HrDocumentTypeId") + .HasColumnType("integer"); + + b.Property("IssueDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Notes") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("OriginalFileName") + .IsRequired() + .HasMaxLength(260) + .HasColumnType("character varying(260)"); + + b.Property("RelativePath") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SizeBytes") + .HasColumnType("bigint"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("StoredFileName") + .IsRequired() + .HasMaxLength(260) + .HasColumnType("character varying(260)"); + + b.Property("UploadedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UploadedBy") + .HasColumnType("integer"); + + b.Property("VerifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VerifiedBy") + .HasColumnType("integer"); + + b.HasKey("EmployeeDocumentId"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("ExpiryDate"); + + b.HasIndex("HrDocumentTypeId"); + + b.ToTable("hr_employee_documents", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeLoan", b => + { + b.Property("EmployeeLoanId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeLoanId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("InstallmentAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("InterestRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("LoanKind") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("NumberOfInstallments") + .HasColumnType("integer"); + + b.Property("OutstandingBalance") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("PrincipalAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("StartMonth") + .HasColumnType("integer"); + + b.Property("StartYear") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("EmployeeLoanId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("EmployeeId"); + + b.HasIndex("Status"); + + b.ToTable("hr_employee_loans", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructure", b => + { + b.Property("EmployeeSalaryStructureId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeSalaryStructureId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("BasicSalary") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("Currency") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("character varying(3)"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveTo") + .HasColumnType("timestamp with time zone"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("EmployeeSalaryStructureId"); + + b.HasIndex("EmployeeId", "EffectiveTo"); + + b.ToTable("hr_employee_salary_structures", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructureLine", b => + { + b.Property("EmployeeSalaryStructureLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmployeeSalaryStructureLineId")); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("EmployeeSalaryStructureId") + .HasColumnType("integer"); + + b.Property("SalaryComponentId") + .HasColumnType("integer"); + + b.HasKey("EmployeeSalaryStructureLineId"); + + b.HasIndex("EmployeeSalaryStructureId"); + + b.HasIndex("SalaryComponentId"); + + b.ToTable("hr_employee_salary_structure_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmploymentType", b => + { + b.Property("EmploymentTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmploymentTypeId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("EmploymentTypeId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_employment_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Grn", b => + { + b.Property("GrnId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("GrnId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PoId") + .HasColumnType("integer"); + + b.Property("PostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PurchaseInvoiceId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("GrnId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("PoId"); + + b.HasIndex("PurchaseInvoiceId"); + + b.HasIndex("Status"); + + b.HasIndex("VendorId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("grns", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLine", b => + { + b.Property("GrnLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("GrnLineId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("DiscountPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("GrnId") + .HasColumnType("integer"); + + b.Property("HoldStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("NetUnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("PoLineId") + .HasColumnType("integer"); + + b.Property("PoUnitPrice") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReceivedValue") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("VatAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("VatPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.HasKey("GrnLineId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("GrnId"); + + b.HasIndex("ItemId"); + + b.HasIndex("PoLineId"); + + b.ToTable("grn_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLineWarrantyNumber", b => + { + b.Property("GrnLineWarrantyNumberId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("GrnLineWarrantyNumberId")); + + b.Property("GrnLineId") + .HasColumnType("integer"); + + b.Property("WarrantyNo") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("WarrantyPeriodMonths") + .HasColumnType("integer"); + + b.HasKey("GrnLineWarrantyNumberId"); + + b.HasIndex("GrnLineId", "WarrantyNo") + .IsUnique(); + + b.ToTable("grn_line_warranty_numbers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.HrDocumentType", b => + { + b.Property("HrDocumentTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("HrDocumentTypeId")); + + b.Property("Category") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpiryTracked") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RequiredAtOnboarding") + .HasColumnType("boolean"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("HrDocumentTypeId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_document_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Item", b => + { + b.Property("ItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ItemId")); + + b.Property("Barcode") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("BaseUomId") + .HasColumnType("integer"); + + b.Property("BrandId") + .HasColumnType("integer"); + + b.Property("CategoryId") + .HasColumnType("integer"); + + b.Property("ContentBaseQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ContentBaseUnit") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ContentQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ContentUnit") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DefaultVendorId") + .HasColumnType("integer"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SellingFlatPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SellingMaxPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SellingMinPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Sku") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("StockNature") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("SubCategoryId") + .HasColumnType("integer"); + + b.Property("TaxRateId") + .HasColumnType("integer"); + + b.Property("TrackingMode") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Warranty") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("NonWarranty"); + + b.Property("WarrantyPeriodMonths") + .HasColumnType("integer"); + + b.HasKey("ItemId"); + + b.HasIndex("Barcode") + .IsUnique(); + + b.HasIndex("BaseUomId"); + + b.HasIndex("BrandId"); + + b.HasIndex("CategoryId"); + + b.HasIndex("DefaultVendorId"); + + b.HasIndex("Sku") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("SubCategoryId"); + + b.HasIndex("TaxRateId"); + + b.ToTable("items", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ItemReorder", b => + { + b.Property("ReorderId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReorderId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("ReorderPoint") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReorderQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("ReorderId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("ItemId", "WarehouseId") + .IsUnique(); + + b.ToTable("item_reorders", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ItemType", b => + { + b.Property("ItemTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ItemTypeId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsMeasurable") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("ItemTypeId"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("item_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.JournalEntryStub", b => + { + b.Property("JournalId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("JournalId")); + + b.Property("Amount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CreditAccount") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("DebitAccount") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("SourceDocId") + .HasColumnType("integer"); + + b.Property("SourceDocType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.HasKey("JournalId"); + + b.HasIndex("SourceDocType", "SourceDocId"); + + b.ToTable("journal_entry_stubs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveBalance", b => + { + b.Property("LeaveBalanceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LeaveBalanceId")); + + b.Property("AdjustmentDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("CarriedForwardDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("EntitledDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("LeaveTypeId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("TakenDays") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Year") + .HasColumnType("integer"); + + b.HasKey("LeaveBalanceId"); + + b.HasIndex("LeaveTypeId"); + + b.HasIndex("EmployeeId", "LeaveTypeId", "Year") + .IsUnique(); + + b.ToTable("hr_leave_balances", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveRequest", b => + { + b.Property("LeaveRequestId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LeaveRequestId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DaysCount") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("EndDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LeaveTypeId") + .HasColumnType("integer"); + + b.Property("Reason") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("RejectionReason") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("StartDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("LeaveRequestId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("EmployeeId"); + + b.HasIndex("LeaveTypeId"); + + b.HasIndex("Status"); + + b.HasIndex("StartDate", "EndDate"); + + b.ToTable("hr_leave_requests", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveType", b => + { + b.Property("LeaveTypeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LeaveTypeId")); + + b.Property("AccrualPerYear") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("CarryForwardAllowed") + .HasColumnType("boolean"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CountsAsNoPay") + .HasColumnType("boolean"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsPaid") + .HasColumnType("boolean"); + + b.Property("MaxCarryForwardDays") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RequiresApproval") + .HasColumnType("boolean"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("LeaveTypeId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_leave_types", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoanInstallment", b => + { + b.Property("LoanInstallmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LoanInstallmentId")); + + b.Property("DueMonth") + .HasColumnType("integer"); + + b.Property("DueYear") + .HasColumnType("integer"); + + b.Property("EmployeeLoanId") + .HasColumnType("integer"); + + b.Property("InstallmentNumber") + .HasColumnType("integer"); + + b.Property("PaidAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("PayrollRunId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("ScheduledAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("LoanInstallmentId"); + + b.HasIndex("EmployeeLoanId"); + + b.HasIndex("PayrollRunId"); + + b.HasIndex("DueYear", "DueMonth"); + + b.ToTable("hr_loan_installments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoginActivity", b => + { + b.Property("LoginActivityId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LoginActivityId")); + + b.Property("DeviceLabel") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("IpAddress") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("LoginAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserAgent") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("LoginActivityId"); + + b.HasIndex("UserId", "LoginAt"); + + b.ToTable("login_activities", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NavItem", b => + { + b.Property("NavItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NavItemId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Href") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Icon") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.HasKey("NavItemId"); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("nav_items", (string)null); + + b.HasData( + new + { + NavItemId = 1, + Code = "dashboard", + Href = "/dashboard", + Label = "Dashboard", + SortOrder = 1, + Status = "Active" + }, + new + { + NavItemId = 2, + Code = "products", + Href = "/dashboard/products", + Label = "Products", + SortOrder = 2, + Status = "Active" + }, + new + { + NavItemId = 4, + Code = "procurement", + Href = "/dashboard/procurement", + Label = "Procurement", + SortOrder = 4, + Status = "Active" + }, + new + { + NavItemId = 5, + Code = "receiving", + Href = "/dashboard/receiving/grn", + Label = "Receiving", + SortOrder = 5, + Status = "Active" + }, + new + { + NavItemId = 6, + Code = "stock", + Href = "/dashboard/stock", + Label = "Stock", + SortOrder = 6, + Status = "Active" + }, + new + { + NavItemId = 7, + Code = "warehouses", + Href = "/dashboard/warehouse", + Label = "Warehouses", + SortOrder = 7, + Status = "Active" + }, + new + { + NavItemId = 8, + Code = "orders", + Href = "/dashboard/orders", + Label = "Orders", + SortOrder = 8, + Status = "Active" + }, + new + { + NavItemId = 9, + Code = "settings", + Href = "/dashboard/settings", + Label = "Settings", + SortOrder = 9, + Status = "Active" + }, + new + { + NavItemId = 10, + Code = "help", + Href = "/dashboard/help", + Label = "Help", + SortOrder = 10, + Status = "Active" + }, + new + { + NavItemId = 11, + Code = "ledgers", + Href = "/dashboard/ledgers", + Label = "Ledgers", + SortOrder = 11, + Status = "Active" + }, + new + { + NavItemId = 12, + Code = "accounts", + Href = "/dashboard/accounts", + Label = "Accounts", + SortOrder = 12, + Status = "Active" + }, + new + { + NavItemId = 13, + Code = "sales", + Href = "/dashboard/sales", + Label = "Sales", + SortOrder = 13, + Status = "Active" + }, + new + { + NavItemId = 14, + Code = "production", + Href = "/dashboard/production", + Label = "Production", + SortOrder = 14, + Status = "Active" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Notification", b => + { + b.Property("NotificationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NotificationId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("ModuleKey") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("RelatedEntityId") + .HasColumnType("integer"); + + b.Property("RelatedEntityType") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.HasKey("NotificationId"); + + b.HasIndex("CreatedAt"); + + b.ToTable("notifications", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => + { + b.Property("NotificationConfigId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.HasKey("NotificationConfigId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("notification_config", null, t => + { + t.HasCheckConstraint("ck_notification_config_singleton", "\"NotificationConfigId\" = 1"); + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfigModule", b => + { + b.Property("NotificationConfigModuleId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NotificationConfigModuleId")); + + b.Property("EmailEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("InAppEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("ModuleKey") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("NotificationConfigId") + .HasColumnType("integer"); + + b.Property("SmsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.HasKey("NotificationConfigModuleId"); + + b.HasIndex("ModuleKey") + .IsUnique(); + + b.HasIndex("NotificationConfigId"); + + b.ToTable("notification_config_modules", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationRecipient", b => + { + b.Property("NotificationRecipientId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NotificationRecipientId")); + + b.Property("IsRead") + .HasColumnType("boolean"); + + b.Property("NotificationId") + .HasColumnType("integer"); + + b.Property("ReadAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("NotificationRecipientId"); + + b.HasIndex("NotificationId"); + + b.HasIndex("UserId", "IsRead", "NotificationId"); + + b.ToTable("notification_recipients", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NumberSequence", b => + { + b.Property("SequenceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SequenceId")); + + b.Property("BranchId") + .HasColumnType("integer") + .HasColumnName("branch_id"); + + b.Property("DocType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)") + .HasColumnName("doc_type"); + + b.Property("LastNumber") + .HasColumnType("integer") + .HasColumnName("last_number"); + + b.Property("Year") + .HasColumnType("integer") + .HasColumnName("year"); + + b.HasKey("SequenceId"); + + b.HasIndex("BranchId"); + + b.HasIndex("DocType", "BranchId", "Year") + .IsUnique(); + + b.ToTable("number_sequences", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => + { + b.Property("PayrollLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollLineId")); + + b.Property("AbsentDays") + .HasColumnType("integer"); + + b.Property("BasicSalary") + .HasColumnType("numeric(18,2)"); + + b.Property("EmployeeId") + .HasColumnType("integer"); + + b.Property("EpfEmployeeAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("EpfEmployerAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("EtfEmployerAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("GrossSalary") + .HasColumnType("numeric(18,2)"); + + b.Property("LateDeductionAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("LateMinutesTotal") + .HasColumnType("integer"); + + b.Property("LeaveDays") + .HasColumnType("integer"); + + b.Property("LoanDeductionAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("NetSalary") + .HasColumnType("numeric(18,2)"); + + b.Property("NoPayAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("OtMinutesTotal") + .HasColumnType("integer"); + + b.Property("OtherDeductionsAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("OvertimeAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("PayrollRunId") + .HasColumnType("integer"); + + b.Property("PresentDays") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("TaxAmount") + .HasColumnType("numeric(18,2)"); + + b.Property("TotalAllowances") + .HasColumnType("numeric(18,2)"); + + b.Property("WorkingDays") + .HasColumnType("integer"); + + b.HasKey("PayrollLineId"); + + b.HasIndex("EmployeeId"); + + b.HasIndex("PayrollRunId", "EmployeeId") + .IsUnique(); + + b.ToTable("hr_payroll_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLineComponent", b => + { + b.Property("PayrollLineComponentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollLineComponentId")); + + b.Property("Amount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("ComponentCategory") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("PayrollLineId") + .HasColumnType("integer"); + + b.Property("SalaryComponentId") + .HasColumnType("integer"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.HasKey("PayrollLineComponentId"); + + b.HasIndex("PayrollLineId"); + + b.HasIndex("SalaryComponentId"); + + b.ToTable("hr_payroll_line_components", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollRun", b => + { + b.Property("PayrollRunId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollRunId")); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GeneratedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GeneratedBy") + .HasColumnType("integer"); + + b.Property("LockedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("LockedBy") + .HasColumnType("integer"); + + b.Property("PeriodMonth") + .HasColumnType("integer"); + + b.Property("PeriodYear") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UnlockReason") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("UnlockedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UnlockedBy") + .HasColumnType("integer"); + + b.HasKey("PayrollRunId"); + + b.HasIndex("BranchId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("PeriodYear", "PeriodMonth", "BranchId"); + + b.ToTable("hr_payroll_runs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollStatutorySetting", b => + { + b.Property("PayrollStatutorySettingId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayrollStatutorySettingId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveTo") + .HasColumnType("timestamp with time zone"); + + b.Property("EpfEmployeeRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("EpfEmployerRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("EtfEmployerRate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("OtMultiplierDefault") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.HasKey("PayrollStatutorySettingId"); + + b.HasIndex("EffectiveFrom"); + + b.ToTable("hr_payroll_statutory_settings", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Payslip", b => + { + b.Property("PayslipId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PayslipId")); + + b.Property("GeneratedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PayrollLineId") + .HasColumnType("integer"); + + b.Property("ReleasedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReleasedBy") + .HasColumnType("integer"); + + b.HasKey("PayslipId"); + + b.HasIndex("PayrollLineId") + .IsUnique(); + + b.ToTable("hr_payslips", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Permission", b => + { + b.Property("PermissionId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PermissionId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(80) + .HasColumnType("character varying(80)"); + + b.Property("NavItemId") + .HasColumnType("integer"); + + b.Property("SubNavItemId") + .HasColumnType("integer"); + + b.HasKey("PermissionId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("NavItemId"); + + b.HasIndex("SubNavItemId"); + + b.ToTable("permissions", (string)null); + + b.HasData( + new + { + PermissionId = 1, + Code = "NAV:dashboard", + NavItemId = 1 + }, + new + { + PermissionId = 2, + Code = "NAV:products", + NavItemId = 2 + }, + new + { + PermissionId = 3, + Code = "NAV:procurement.vendors", + SubNavItemId = 30 + }, + new + { + PermissionId = 4, + Code = "NAV:procurement", + NavItemId = 4 + }, + new + { + PermissionId = 5, + Code = "NAV:receiving", + NavItemId = 5 + }, + new + { + PermissionId = 6, + Code = "NAV:stock", + NavItemId = 6 + }, + new + { + PermissionId = 7, + Code = "NAV:warehouses", + NavItemId = 7 + }, + new + { + PermissionId = 8, + Code = "NAV:orders", + NavItemId = 8 + }, + new + { + PermissionId = 9, + Code = "NAV:settings", + NavItemId = 9 + }, + new + { + PermissionId = 10, + Code = "NAV:help", + NavItemId = 10 + }, + new + { + PermissionId = 11, + Code = "NAV:products.item", + SubNavItemId = 1 + }, + new + { + PermissionId = 12, + Code = "NAV:products.category", + SubNavItemId = 2 + }, + new + { + PermissionId = 13, + Code = "NAV:products.brand", + SubNavItemId = 3 + }, + new + { + PermissionId = 14, + Code = "NAV:products.item-type", + SubNavItemId = 4 + }, + new + { + PermissionId = 15, + Code = "NAV:products.uom", + SubNavItemId = 5 + }, + new + { + PermissionId = 16, + Code = "NAV:products.configuration", + SubNavItemId = 6 + }, + new + { + PermissionId = 17, + Code = "NAV:settings.roles", + SubNavItemId = 7 + }, + new + { + PermissionId = 18, + Code = "NAV:settings.users", + SubNavItemId = 8 + }, + new + { + PermissionId = 28, + Code = "NAV:procurement.requisitions", + SubNavItemId = 17 + }, + new + { + PermissionId = 29, + Code = "NAV:procurement.rfqs", + SubNavItemId = 18 + }, + new + { + PermissionId = 30, + Code = "NAV:procurement.purchase-orders", + SubNavItemId = 19 + }, + new + { + PermissionId = 31, + Code = "NAV:procurement.purchase-returns", + SubNavItemId = 20 + }, + new + { + PermissionId = 19, + Code = "NAV:ledgers", + NavItemId = 11 + }, + new + { + PermissionId = 20, + Code = "NAV:ledgers.trial-balance", + SubNavItemId = 9 + }, + new + { + PermissionId = 21, + Code = "NAV:ledgers.balance-sheet", + SubNavItemId = 10 + }, + new + { + PermissionId = 22, + Code = "NAV:ledgers.general-ledger", + SubNavItemId = 11 + }, + new + { + PermissionId = 23, + Code = "NAV:ledgers.profit-and-loss", + SubNavItemId = 12 + }, + new + { + PermissionId = 24, + Code = "NAV:ledgers.cash-flow", + SubNavItemId = 13 + }, + new + { + PermissionId = 25, + Code = "NAV:ledgers.budget-vs-actual", + SubNavItemId = 14 + }, + new + { + PermissionId = 27, + Code = "NAV:ledgers.tax-report", + SubNavItemId = 16 + }, + new + { + PermissionId = 26, + Code = "NAV:accounts.bank-accounts", + SubNavItemId = 15 + }, + new + { + PermissionId = 32, + Code = "NAV:accounts", + NavItemId = 12 + }, + new + { + PermissionId = 33, + Code = "NAV:accounts.cheque-books", + SubNavItemId = 21 + }, + new + { + PermissionId = 34, + Code = "NAV:accounts.received-cheques", + SubNavItemId = 22 + }, + new + { + PermissionId = 35, + Code = "NAV:production", + NavItemId = 14 + }, + new + { + PermissionId = 36, + Code = "NAV:production.templates", + SubNavItemId = 27 + }, + new + { + PermissionId = 37, + Code = "NAV:production.runs", + SubNavItemId = 25 + }, + new + { + PermissionId = 38, + Code = "NAV:production.produced", + SubNavItemId = 26 + }, + new + { + PermissionId = 39, + Code = "NAV:procurement.purchase-invoices", + SubNavItemId = 28 + }, + new + { + PermissionId = 40, + Code = "NAV:settings.branches", + SubNavItemId = 29 + }, + new + { + PermissionId = 41, + Code = "NAV:stock.ledger", + SubNavItemId = 31 + }, + new + { + PermissionId = 42, + Code = "NAV:stock.enquiry", + SubNavItemId = 32 + }, + new + { + PermissionId = 43, + Code = "NAV:stock.valuation", + SubNavItemId = 33 + }, + new + { + PermissionId = 44, + Code = "NAV:stock.transfers", + SubNavItemId = 34 + }, + new + { + PermissionId = 45, + Code = "NAV:stock.adjustments", + SubNavItemId = 35 + }, + new + { + PermissionId = 46, + Code = "NAV:stock.counts", + SubNavItemId = 36 + }, + new + { + PermissionId = 47, + Code = "NAV:stock.reorder-alerts", + SubNavItemId = 37 + }, + new + { + PermissionId = 48, + Code = "NAV:stock.wastage", + SubNavItemId = 38 + }, + new + { + PermissionId = 49, + Code = "NAV:sales.bundle-templates", + SubNavItemId = 23 + }, + new + { + PermissionId = 50, + Code = "NAV:sales.invoices", + SubNavItemId = 40 + }, + new + { + PermissionId = 51, + Code = "NAV:sales.free-issues", + SubNavItemId = 41 + }, + new + { + PermissionId = 52, + Code = "NAV:sales.day-end", + SubNavItemId = 42 + }, + new + { + PermissionId = 53, + Code = "NAV:products.tax-rates", + SubNavItemId = 43 + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PoLine", b => + { + b.Property("PoLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PoLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("PoId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyReceived") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Tax") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("PoLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("PoId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("po_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductConfig", b => + { + b.Property("ConfigId") + .HasColumnType("integer"); + + b.Property("BatchListsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("BrandsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("ItemTypesEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SellingPricesEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("SerialNumbersEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("SubcategoriesEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.Property("WarrantyPeriodsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.HasKey("ConfigId"); + + b.HasIndex("UpdatedBy"); + + b.ToTable("product_config", null, t => + { + t.HasCheckConstraint("ck_product_config_singleton", "\"ConfigId\" = 1"); + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b => + { + b.Property("RunId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunId")); + + b.Property("CancelReasonCodeId") + .HasColumnType("integer"); + + b.Property("CompletedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("OutputBinId") + .HasColumnType("integer"); + + b.Property("ReworkCount") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("ScaleFactor") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("TargetQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TemplateId") + .HasColumnType("integer"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("RunId"); + + b.HasIndex("CancelReasonCodeId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("OutputBinId"); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("TemplateId", "Status"); + + b.ToTable("production_runs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionTemplate", b => + { + b.Property("TemplateId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TemplateId")); + + b.Property("Annotations") + .HasColumnType("jsonb"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("TemplateId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("CreatedBy"); + + b.HasIndex("Status"); + + b.ToTable("production_templates", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", b => + { + b.Property("PurchaseInvoiceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PurchaseInvoiceId")); + + b.Property("BalanceAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VatTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.Property("VendorInvoiceDate") + .HasColumnType("timestamp with time zone"); + + b.Property("VendorInvoiceNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("VendorSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("VendorSnapshotTaxNo") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("PurchaseInvoiceId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("VendorId"); + + b.HasIndex("VendorId", "VendorInvoiceNo"); + + b.ToTable("purchase_invoices", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoiceLine", b => + { + b.Property("PurchaseInvoiceLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PurchaseInvoiceLineId")); + + b.Property("GrnId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PurchaseInvoiceId") + .HasColumnType("integer"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("VatTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("PurchaseInvoiceLineId"); + + b.HasIndex("GrnId") + .IsUnique(); + + b.HasIndex("PurchaseInvoiceId"); + + b.ToTable("purchase_invoice_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoicePayment", b => + { + b.Property("PurchaseInvoicePaymentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PurchaseInvoicePaymentId")); + + b.Property("Amount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BankAccountName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("GlBankAccountId") + .HasColumnType("bigint"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PaymentDate") + .HasColumnType("timestamp with time zone"); + + b.Property("PurchaseInvoiceId") + .HasColumnType("integer"); + + b.Property("Reference") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("PurchaseInvoicePaymentId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("PurchaseInvoiceId"); + + b.ToTable("purchase_invoice_payments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => + { + b.Property("PoId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PoId")); + + b.Property("ApprovalRequired") + .HasColumnType("boolean"); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("ApproverUserId") + .HasColumnType("integer"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RequisitionId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.HasKey("PoId"); + + b.HasIndex("ApproverUserId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("RequisitionId"); + + b.HasIndex("Status"); + + b.HasIndex("VendorId"); + + b.ToTable("purchase_orders", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturn", b => + { + b.Property("ReturnId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReasonCodeId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("ReturnId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("ReasonCodeId"); + + b.HasIndex("VendorId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("purchase_returns", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturnLine", b => + { + b.Property("ReturnLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnLineId")); + + b.Property("GrnLineId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReturnId") + .HasColumnType("integer"); + + b.HasKey("ReturnLineId"); + + b.HasIndex("GrnLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("ReturnId"); + + b.ToTable("purchase_return_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ReasonCode", b => + { + b.Property("ReasonCodeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReasonCodeId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Context") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.HasKey("ReasonCodeId"); + + b.HasIndex("Context", "Code") + .IsUnique(); + + b.ToTable("reason_codes", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => + { + b.Property("RequisitionId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RequisitionId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RequestedBy") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("RequisitionId"); + + b.HasIndex("BranchId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("RequestedBy"); + + b.HasIndex("Status"); + + b.ToTable("requisitions", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RequisitionLine", b => + { + b.Property("ReqLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReqLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RequiredBy") + .HasColumnType("date"); + + b.Property("RequisitionId") + .HasColumnType("integer"); + + b.HasKey("ReqLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RequisitionId"); + + b.ToTable("requisition_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => + { + b.Property("RfqId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RfqId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RequisitionId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("RfqId"); + + b.HasIndex("BranchId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("RequisitionId"); + + b.ToTable("rfqs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RfqLine", b => + { + b.Property("RfqLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RfqLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RfqId") + .HasColumnType("integer"); + + b.HasKey("RfqLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RfqId"); + + b.ToTable("rfq_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Role", b => + { + b.Property("RoleId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RoleId")); + + b.Property("AuthRoleId") + .HasColumnType("uuid") + .HasColumnName("auth_role_id"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsSystemRole") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("RoleId"); + + b.HasIndex("AuthRoleId") + .IsUnique(); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("roles", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RolePermission", b => + { + b.Property("RoleId") + .HasColumnType("integer"); + + b.Property("PermissionId") + .HasColumnType("integer"); + + b.Property("Actions") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(31); + + b.HasKey("RoleId", "PermissionId"); + + b.HasIndex("PermissionId"); + + b.ToTable("role_permissions", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunEdge", b => + { + b.Property("RunEdgeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunEdgeId")); + + b.Property("ChildRunStageId") + .HasColumnType("integer"); + + b.Property("ParentRunStageId") + .HasColumnType("integer"); + + b.Property("RunId") + .HasColumnType("integer"); + + b.HasKey("RunEdgeId"); + + b.HasIndex("ChildRunStageId"); + + b.HasIndex("RunId"); + + b.HasIndex("ParentRunStageId", "ChildRunStageId") + .IsUnique(); + + b.ToTable("run_edges", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStage", b => + { + b.Property("RunStageId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunStageId")); + + b.Property("ActualEndAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ActualStartAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EstimatedMinutes") + .HasColumnType("integer"); + + b.Property("FieldDefs") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("FieldValues") + .HasColumnType("jsonb"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("PosX") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PosY") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RoleLabel") + .HasMaxLength(60) + .HasColumnType("character varying(60)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("RunId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("TemplateStageId") + .HasColumnType("integer"); + + b.HasKey("RunStageId"); + + b.HasIndex("TemplateStageId"); + + b.HasIndex("RunId", "Status"); + + b.ToTable("run_stages", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageEvent", b => + { + b.Property("EventId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EventId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EventType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Note") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Payload") + .HasColumnType("jsonb"); + + b.Property("RunId") + .HasColumnType("integer"); + + b.Property("RunStageId") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("EventId"); + + b.HasIndex("RunStageId"); + + b.HasIndex("UserId"); + + b.HasIndex("RunId", "EventId"); + + b.ToTable("run_stage_events", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageInput", b => + { + b.Property("RunInputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunInputId")); + + b.Property("ConsumedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ConsumedValue") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DeliveredQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("FromRunOutputId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("PlannedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyUnit") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ReturnedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReturnedValue") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RunStageId") + .HasColumnType("integer"); + + b.Property("Source") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("RunInputId"); + + b.HasIndex("FromRunOutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RunStageId"); + + b.ToTable("run_stage_inputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageOutput", b => + { + b.Property("RunOutputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RunOutputId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("PlannedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ProducedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RunStageId") + .HasColumnType("integer"); + + b.Property("ScrapReasonCodeId") + .HasColumnType("integer"); + + b.Property("ScrappedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TransferredQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UomId") + .HasColumnType("integer"); + + b.HasKey("RunOutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("RunStageId"); + + b.HasIndex("ScrapReasonCodeId"); + + b.HasIndex("UomId"); + + b.ToTable("run_stage_outputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalaryComponent", b => + { + b.Property("SalaryComponentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalaryComponentId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ComponentType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsEpfEtfApplicable") + .HasColumnType("boolean"); + + b.Property("IsTaxable") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("SalaryComponentId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_salary_components", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesDayEnd", b => + { + b.Property("SalesDayEndId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesDayEndId")); + + b.Property("BalanceTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BundleCount") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("BusinessDate") + .HasColumnType("date"); + + b.Property("CashierUserId") + .HasColumnType("integer"); + + b.Property("ClosedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ClosedBy") + .HasColumnType("integer"); + + b.Property("CostOfGoodsSold") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SlipCount") + .HasColumnType("integer"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("SalesDayEndId"); + + b.HasIndex("ClosedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("CashierUserId", "BusinessDate") + .IsUnique(); + + b.ToTable("sales_day_ends", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoice", b => + { + b.Property("SalesInvoiceId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesInvoiceId")); + + b.Property("BalanceAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("CreatorUserId") + .HasColumnType("integer"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("CustomerSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CustomerSnapshotTaxNo") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("InvoiceDate") + .HasColumnType("timestamp with time zone"); + + b.Property("InvoiceNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("InvoiceType") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("B2C"); + + b.Property("NetPayable") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RoundOff") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesInvoiceId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatorUserId"); + + b.HasIndex("CustomerId"); + + b.HasIndex("InvoiceDate"); + + b.HasIndex("InvoiceNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_invoices", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoiceLine", b => + { + b.Property("SalesInvoiceLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesInvoiceLineId")); + + b.Property("BaseCost") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DiscountAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DiscountMode") + .HasColumnType("integer"); + + b.Property("DiscountPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("FreeQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("IsFreeIssue") + .HasColumnType("boolean"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("NetUnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ParentLineId") + .HasColumnType("integer"); + + b.Property("PriceSource") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SalesInvoiceId") + .HasColumnType("integer"); + + b.Property("TaxAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesInvoiceLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SalesInvoiceId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_invoice_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoicePayment", b => + { + b.Property("SalesInvoicePaymentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesInvoicePaymentId")); + + b.Property("Amount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BankAccountName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("GlBankAccountId") + .HasColumnType("bigint"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PaymentDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Reference") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("SalesInvoiceId") + .HasColumnType("integer"); + + b.HasKey("SalesInvoicePaymentId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("SalesInvoiceId"); + + b.ToTable("sales_invoice_payments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturn", b => + { + b.Property("ReturnId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReasonCodeId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("ReturnId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("CustomerId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("ReasonCodeId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_returns", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturnLine", b => + { + b.Property("ReturnLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ReturnLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReturnId") + .HasColumnType("integer"); + + b.Property("SalesInvoiceLineId") + .HasColumnType("integer"); + + b.HasKey("ReturnLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("ReturnId"); + + b.HasIndex("SalesInvoiceLineId"); + + b.ToTable("sales_return_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlip", b => + { + b.Property("SalesSlipId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesSlipId")); + + b.Property("BalanceAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("CashierUserId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CustomerId") + .HasColumnType("integer"); + + b.Property("CustomerSnapshotName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DayEndId") + .HasColumnType("integer"); + + b.Property("DiscountTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("GrandTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PaidAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SlipDate") + .HasColumnType("timestamp with time zone"); + + b.Property("SlipNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Draft"); + + b.Property("Subtotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesSlipId"); + + b.HasIndex("CashierUserId"); + + b.HasIndex("CustomerId"); + + b.HasIndex("DayEndId"); + + b.HasIndex("SlipDate"); + + b.HasIndex("SlipNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_slips", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlipLine", b => + { + b.Property("SalesSlipLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesSlipLineId")); + + b.Property("BaseCost") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("DiscountAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("DiscountMode") + .HasColumnType("integer"); + + b.Property("DiscountPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("FreeQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("IsFreeIssue") + .HasColumnType("boolean"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LineTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("NetUnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ParentLineId") + .HasColumnType("integer"); + + b.Property("PriceSource") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SalesSlipId") + .HasColumnType("integer"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("TaxAmount") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("TaxPct") + .HasPrecision(9, 4) + .HasColumnType("numeric(9,4)"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("SalesSlipLineId"); + + b.HasIndex("BatchId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SalesSlipId"); + + b.HasIndex("SerialId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("sales_slip_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Serial", b => + { + b.Property("SerialId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SerialId")); + + b.Property("Barcode") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("SerialNo") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("SerialId"); + + b.HasIndex("Barcode") + .IsUnique(); + + b.HasIndex("ItemId", "SerialNo") + .IsUnique(); + + b.ToTable("serials", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageEdge", b => + { + b.Property("EdgeId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EdgeId")); + + b.Property("ChildStageId") + .HasColumnType("integer"); + + b.Property("ParentStageId") + .HasColumnType("integer"); + + b.Property("TemplateId") + .HasColumnType("integer"); + + b.HasKey("EdgeId"); + + b.HasIndex("ChildStageId"); + + b.HasIndex("TemplateId"); + + b.HasIndex("ParentStageId", "ChildStageId") + .IsUnique(); + + b.ToTable("stage_edges", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageInput", b => + { + b.Property("InputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("InputId")); + + b.Property("FromOutputId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyPerBatch") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyUnit") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Source") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("StageId") + .HasColumnType("integer"); + + b.HasKey("InputId"); + + b.HasIndex("FromOutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("StageId"); + + b.ToTable("stage_inputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageOutput", b => + { + b.Property("OutputId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("OutputId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("QtyPerBatch") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("StageId") + .HasColumnType("integer"); + + b.Property("UomId") + .HasColumnType("integer"); + + b.HasKey("OutputId"); + + b.HasIndex("ItemId"); + + b.HasIndex("StageId"); + + b.HasIndex("UomId"); + + b.ToTable("stage_outputs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustment", b => + { + b.Property("AdjustmentId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AdjustmentId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlJournalNo") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GlPostedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ReasonCodeId") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("AdjustmentId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("ReasonCodeId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("stock_adjustments", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustmentLine", b => + { + b.Property("AdjLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AdjLineId")); + + b.Property("AdjustmentId") + .HasColumnType("integer"); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyDelta") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.HasKey("AdjLineId"); + + b.HasIndex("AdjustmentId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SerialId"); + + b.ToTable("stock_adjustment_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCount", b => + { + b.Property("CountId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CountId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CountType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("CountId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("Status"); + + b.HasIndex("WarehouseId"); + + b.ToTable("stock_counts", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCountLine", b => + { + b.Property("CountLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CountLineId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("CountId") + .HasColumnType("integer"); + + b.Property("CountedQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("SystemQty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("Variance") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("CountLineId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("CountId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SerialId"); + + b.ToTable("stock_count_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLayer", b => + { + b.Property("LayerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LayerId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("GrnLineId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyReceived") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyRemaining") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("ReceiptDate") + .HasColumnType("timestamp with time zone"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("LayerId"); + + b.HasIndex("BatchId"); + + b.HasIndex("GrnLineId"); + + b.HasIndex("SerialId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("ItemId", "WarehouseId", "ReceiptDate", "LayerId"); + + b.ToTable("stock_layers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLedger", b => + { + b.Property("LedgerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("LedgerId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("BinId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Direction") + .IsRequired() + .HasMaxLength(5) + .HasColumnType("character varying(5)"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("QtyBase") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RunningBalance") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("SourceDocId") + .HasColumnType("integer"); + + b.Property("SourceDocType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.Property("Value") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("WarehouseId") + .HasColumnType("integer"); + + b.HasKey("LedgerId"); + + b.HasIndex("BatchId"); + + b.HasIndex("BinId"); + + b.HasIndex("SerialId"); + + b.HasIndex("UserId"); + + b.HasIndex("WarehouseId"); + + b.HasIndex("SourceDocType", "SourceDocId"); + + b.HasIndex("ItemId", "WarehouseId", "CreatedAt"); + + b.HasIndex("ItemId", "WarehouseId", "LedgerId"); + + b.ToTable("stock_ledger", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransfer", b => + { + b.Property("TransferId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TransferId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("DestWarehouseId") + .HasColumnType("integer"); + + b.Property("DocNo") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("SrcWarehouseId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("TransferId"); + + b.HasIndex("BranchId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("DestWarehouseId"); + + b.HasIndex("DocNo") + .IsUnique(); + + b.HasIndex("SrcWarehouseId"); + + b.HasIndex("Status"); + + b.ToTable("stock_transfers", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransferLine", b => + { + b.Property("TransferLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TransferLineId")); + + b.Property("BatchId") + .HasColumnType("integer"); + + b.Property("DestBinId") + .HasColumnType("integer"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("Qty") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("QtyReceived") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("SerialId") + .HasColumnType("integer"); + + b.Property("SrcBinId") + .HasColumnType("integer"); + + b.Property("TransferId") + .HasColumnType("integer"); + + b.Property("UnitCost") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.HasKey("TransferLineId"); + + b.HasIndex("BatchId"); + + b.HasIndex("DestBinId"); + + b.HasIndex("ItemId"); + + b.HasIndex("SerialId"); + + b.HasIndex("SrcBinId"); + + b.HasIndex("TransferId"); + + b.ToTable("stock_transfer_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubCategory", b => + { + b.Property("SubCategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SubCategoryId")); + + b.Property("CategoryId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("SubCategoryId"); + + b.HasIndex("Status"); + + b.HasIndex("CategoryId", "Name") + .IsUnique(); + + b.ToTable("subcategories", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubNavItem", b => + { + b.Property("SubNavItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SubNavItemId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Href") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Icon") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("NavItemId") + .HasColumnType("integer"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.HasKey("SubNavItemId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("NavItemId"); + + b.ToTable("sub_nav_items", (string)null); + + b.HasData( + new + { + SubNavItemId = 1, + Code = "products.item", + Href = "/dashboard/products", + Label = "Item", + NavItemId = 2, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 2, + Code = "products.category", + Href = "/dashboard/products/categories", + Label = "Category", + NavItemId = 2, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 3, + Code = "products.brand", + Href = "/dashboard/products/brands", + Label = "Brand", + NavItemId = 2, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 4, + Code = "products.item-type", + Href = "/dashboard/products/item-types", + Label = "Item Type", + NavItemId = 2, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 5, + Code = "products.uom", + Href = "/dashboard/products/uoms", + Label = "UOM", + NavItemId = 2, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 6, + Code = "products.configuration", + Href = "/dashboard/products/settings", + Label = "Configuration", + NavItemId = 2, + SortOrder = 6, + Status = "Active" + }, + new + { + SubNavItemId = 43, + Code = "products.tax-rates", + Href = "/dashboard/products/tax-rates", + Label = "Tax Rates", + NavItemId = 2, + SortOrder = 7, + Status = "Active" + }, + new + { + SubNavItemId = 29, + Code = "settings.branches", + Href = "/dashboard/settings/branches", + Label = "Branches", + NavItemId = 9, + SortOrder = 0, + Status = "Active" + }, + new + { + SubNavItemId = 7, + Code = "settings.roles", + Href = "/dashboard/settings/roles", + Label = "Roles", + NavItemId = 9, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 8, + Code = "settings.users", + Href = "/dashboard/settings/users", + Label = "Users", + NavItemId = 9, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 24, + Code = "settings.notification-config", + Href = "/dashboard/settings/notification-config", + Label = "Notification Config", + NavItemId = 9, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 40, + Code = "sales.invoices", + Href = "/dashboard/sales/invoices", + Label = "Sales", + NavItemId = 13, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 23, + Code = "sales.bundle-templates", + Href = "/dashboard/sales/bundles/templates", + Label = "Bundle Templates", + NavItemId = 13, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 41, + Code = "sales.free-issues", + Href = "/dashboard/sales/free-issues", + Label = "Free Issues", + NavItemId = 13, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 42, + Code = "sales.day-end", + Href = "/dashboard/sales/day-end", + Label = "Day End", + NavItemId = 13, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 30, + Code = "procurement.vendors", + Href = "/dashboard/vendors", + Label = "Vendors", + NavItemId = 4, + SortOrder = 0, + Status = "Active" + }, + new + { + SubNavItemId = 17, + Code = "procurement.requisitions", + Href = "/dashboard/procurement/requisitions", + Label = "Requisitions", + NavItemId = 4, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 18, + Code = "procurement.rfqs", + Href = "/dashboard/procurement/rfqs", + Label = "RFQs", + NavItemId = 4, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 19, + Code = "procurement.purchase-orders", + Href = "/dashboard/procurement/purchase-orders", + Label = "Purchase Orders", + NavItemId = 4, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 20, + Code = "procurement.purchase-returns", + Href = "/dashboard/procurement/purchase-returns", + Label = "Purchase Returns", + NavItemId = 4, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 28, + Code = "procurement.purchase-invoices", + Href = "/dashboard/procurement/purchase-invoices", + Label = "Purchase Invoices", + NavItemId = 4, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 9, + Code = "ledgers.trial-balance", + Href = "/dashboard/ledgers/trial-balance", + Label = "Trial Balance", + NavItemId = 11, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 10, + Code = "ledgers.balance-sheet", + Href = "/dashboard/ledgers/balance-sheet", + Label = "Balance Sheet", + NavItemId = 11, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 11, + Code = "ledgers.general-ledger", + Href = "/dashboard/ledgers/general-ledger", + Label = "General Ledger", + NavItemId = 11, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 12, + Code = "ledgers.profit-and-loss", + Href = "/dashboard/ledgers/profit-and-loss", + Label = "Profit & Loss", + NavItemId = 11, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 13, + Code = "ledgers.cash-flow", + Href = "/dashboard/ledgers/cash-flow", + Label = "Cash Flow", + NavItemId = 11, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 14, + Code = "ledgers.budget-vs-actual", + Href = "/dashboard/ledgers/budget-vs-actual", + Label = "Budget vs Actual", + NavItemId = 11, + SortOrder = 6, + Status = "Active" + }, + new + { + SubNavItemId = 16, + Code = "ledgers.tax-report", + Href = "/dashboard/ledgers/tax-report", + Label = "Tax Report", + NavItemId = 11, + SortOrder = 7, + Status = "Active" + }, + new + { + SubNavItemId = 15, + Code = "accounts.bank-accounts", + Href = "/dashboard/accounts/bank-accounts", + Label = "Cash / Bank Accounts", + NavItemId = 12, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 21, + Code = "accounts.cheque-books", + Href = "/dashboard/accounts/cheque-books", + Label = "Cheque Books", + NavItemId = 12, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 22, + Code = "accounts.received-cheques", + Href = "/dashboard/accounts/received-cheques", + Label = "Received Cheques", + NavItemId = 12, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 27, + Code = "production.templates", + Href = "/dashboard/production/templates", + Label = "Templates", + NavItemId = 14, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 25, + Code = "production.runs", + Href = "/dashboard/production/runs", + Label = "Runs", + NavItemId = 14, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 26, + Code = "production.produced", + Href = "/dashboard/production/produced", + Label = "Produced", + NavItemId = 14, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 31, + Code = "stock.ledger", + Href = "/dashboard/stock/ledger", + Label = "Stock Ledger", + NavItemId = 6, + SortOrder = 1, + Status = "Active" + }, + new + { + SubNavItemId = 32, + Code = "stock.enquiry", + Href = "/dashboard/stock/enquiry", + Label = "Stock Enquiry", + NavItemId = 6, + SortOrder = 2, + Status = "Active" + }, + new + { + SubNavItemId = 33, + Code = "stock.valuation", + Href = "/dashboard/stock/valuation", + Label = "Valuation", + NavItemId = 6, + SortOrder = 3, + Status = "Active" + }, + new + { + SubNavItemId = 34, + Code = "stock.transfers", + Href = "/dashboard/stock/transfers", + Label = "Transfers", + NavItemId = 6, + SortOrder = 4, + Status = "Active" + }, + new + { + SubNavItemId = 35, + Code = "stock.adjustments", + Href = "/dashboard/stock/adjustments", + Label = "Adjustments", + NavItemId = 6, + SortOrder = 5, + Status = "Active" + }, + new + { + SubNavItemId = 36, + Code = "stock.counts", + Href = "/dashboard/stock/counts", + Label = "Counts", + NavItemId = 6, + SortOrder = 6, + Status = "Active" + }, + new + { + SubNavItemId = 37, + Code = "stock.reorder-alerts", + Href = "/dashboard/stock/reorder-alerts", + Label = "Reorder Alerts", + NavItemId = 6, + SortOrder = 7, + Status = "Active" + }, + new + { + SubNavItemId = 38, + Code = "stock.wastage", + Href = "/dashboard/stock/wastage", + Label = "Wastage", + NavItemId = 6, + SortOrder = 8, + Status = "Active" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicket", b => + { + b.Property("TicketId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TicketId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Subject") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.HasKey("TicketId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("Status"); + + b.ToTable("support_tickets", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicketMessage", b => + { + b.Property("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("MessageId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsFromAdmin") + .HasColumnType("boolean"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("SenderUserId") + .HasColumnType("integer"); + + b.Property("TicketId") + .HasColumnType("integer"); + + b.HasKey("MessageId"); + + b.HasIndex("TicketId", "CreatedAt"); + + b.ToTable("support_ticket_messages", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TaxRate", b => + { + b.Property("TaxRateId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TaxRateId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Percentage") + .HasPrecision(5, 2) + .HasColumnType("numeric(5,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("TaxRateId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("tax_rates", (string)null); + + b.HasData( + new + { + TaxRateId = 1, + Code = "STANDARD", + CreatedAt = new DateTime(2026, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc), + Name = "Standard", + Percentage = 15m, + RowVersion = 0u, + Status = "Active" + }, + new + { + TaxRateId = 2, + Code = "ZERO", + CreatedAt = new DateTime(2026, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc), + Name = "Zero-Rated", + Percentage = 0m, + RowVersion = 0u, + Status = "Active" + }, + new + { + TaxRateId = 3, + Code = "EXEMPT", + CreatedAt = new DateTime(2026, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc), + Name = "Exempt", + Percentage = 0m, + RowVersion = 0u, + Status = "Active" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TaxSlab", b => + { + b.Property("TaxSlabId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TaxSlabId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("EffectiveTo") + .HasColumnType("timestamp with time zone"); + + b.Property("LowerBound") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("Rate") + .HasPrecision(6, 4) + .HasColumnType("numeric(6,4)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("UpperBound") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.HasKey("TaxSlabId"); + + b.HasIndex("EffectiveFrom"); + + b.ToTable("hr_tax_slabs", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => + { + b.Property("StageId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("StageId")); + + b.Property("EstimatedMinutes") + .HasColumnType("integer"); + + b.Property("FieldDefs") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("PosX") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("PosY") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.Property("RoleLabel") + .HasMaxLength(60) + .HasColumnType("character varying(60)"); + + b.Property("TemplateId") + .HasColumnType("integer"); + + b.HasKey("StageId"); + + b.HasIndex("TemplateId"); + + b.ToTable("template_stages", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Uom", b => + { + b.Property("UomId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("UomId")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("UomId"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("uoms", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.User", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("UserId")); + + b.Property("AuthUserId") + .HasColumnType("uuid") + .HasColumnName("auth_user_id"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Email") + .HasMaxLength(320) + .HasColumnType("character varying(320)"); + + b.Property("RoleId") + .HasColumnType("integer"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("UserId"); + + b.HasIndex("AuthUserId") + .IsUnique(); + + b.HasIndex("Email") + .IsUnique(); + + b.HasIndex("RoleId"); + + b.HasIndex("Username") + .IsUnique(); + + b.ToTable("users", (string)null); + + b.HasData( + new + { + UserId = 1, + DisplayName = "System", + Status = "Active", + Username = "system" + }); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Vendor", b => + { + b.Property("VendorId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("VendorId")); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Currency") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(3) + .HasColumnType("character varying(3)") + .HasDefaultValue("LKR"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("TaxReg") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Terms") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("VendorId"); + + b.HasIndex("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("vendors", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => + { + b.Property("QuotationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("QuotationId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("RfqId") + .HasColumnType("integer"); + + b.Property("VendorId") + .HasColumnType("integer"); + + b.HasKey("QuotationId"); + + b.HasIndex("VendorId"); + + b.HasIndex("RfqId", "VendorId") + .IsUnique(); + + b.ToTable("vendor_quotations", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotationLine", b => + { + b.Property("QuotationLineId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("QuotationLineId")); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("LeadDays") + .HasColumnType("integer"); + + b.Property("QuotationId") + .HasColumnType("integer"); + + b.Property("UnitPrice") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + + b.HasKey("QuotationLineId"); + + b.HasIndex("ItemId"); + + b.HasIndex("QuotationId"); + + b.ToTable("vendor_quotation_lines", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Warehouse", b => + { + b.Property("WarehouseId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("WarehouseId")); + + b.Property("Address") + .HasColumnType("text"); + + b.Property("BranchId") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Phone") + .HasColumnType("text"); + + b.HasKey("WarehouseId"); + + b.HasIndex("BranchId"); + + b.HasIndex("Code") + .IsUnique(); + + b.ToTable("warehouses", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.WorkShift", b => + { + b.Property("WorkShiftId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("WorkShiftId")); + + b.Property("BreakMinutes") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EndTime") + .HasColumnType("interval"); + + b.Property("GraceMinutes") + .HasColumnType("integer"); + + b.Property("IsOvernight") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("OtMultiplier") + .HasPrecision(6, 2) + .HasColumnType("numeric(6,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("StandardWorkingMinutes") + .HasColumnType("integer"); + + b.Property("StartTime") + .HasColumnType("interval"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("WorkingDaysMask") + .HasColumnType("integer"); + + b.HasKey("WorkShiftId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("hr_work_shifts", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AttendanceRecord", b => + { + b.HasOne("ERPCore.Domain.Entities.AttendanceUploadBatch", "AttendanceUploadBatch") + .WithMany() + .HasForeignKey("AttendanceUploadBatchId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.WorkShift", "WorkShift") + .WithMany() + .HasForeignKey("WorkShiftId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("AttendanceUploadBatch"); + + b.Navigation("Employee"); + + b.Navigation("WorkShift"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.AuditLog", b => + { + b.HasOne("ERPCore.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Batch", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Bin", b => + { + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany("Bins") + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BranchConfig", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSale", b => + { + b.HasOne("ERPCore.Domain.Entities.BundleSaleTemplate", "BundleSaleTemplate") + .WithMany() + .HasForeignKey("BundleSaleTemplateId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "CashierUser") + .WithMany() + .HasForeignKey("CashierUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesDayEnd", "DayEnd") + .WithMany("BundleSales") + .HasForeignKey("DayEndId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BundleSaleTemplate"); + + b.Navigation("CashierUser"); + + b.Navigation("Customer"); + + b.Navigation("DayEnd"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleLine", b => + { + b.HasOne("ERPCore.Domain.Entities.BundleSale", "BundleSale") + .WithMany("Lines") + .HasForeignKey("BundleSaleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BundleSale"); + + b.Navigation("Item"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplateLine", b => + { + b.HasOne("ERPCore.Domain.Entities.BundleSaleTemplate", "BundleSaleTemplate") + .WithMany("Lines") + .HasForeignKey("BundleSaleTemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("BundleSaleTemplate"); + + b.Navigation("Item"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Customer", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "DefaultWarehouse") + .WithMany() + .HasForeignKey("DefaultWarehouseId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Branch"); + + b.Navigation("DefaultWarehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Department", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Employee", "HeadEmployee") + .WithMany() + .HasForeignKey("HeadEmployeeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Department", "ParentDepartment") + .WithMany() + .HasForeignKey("ParentDepartmentId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Branch"); + + b.Navigation("HeadEmployee"); + + b.Navigation("ParentDepartment"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Employee", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Department", "Department") + .WithMany() + .HasForeignKey("DepartmentId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Designation", "Designation") + .WithMany() + .HasForeignKey("DesignationId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.EmploymentType", "EmploymentType") + .WithMany() + .HasForeignKey("EmploymentTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Employee", "ReportingManager") + .WithMany() + .HasForeignKey("ReportingManagerId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithOne() + .HasForeignKey("ERPCore.Domain.Entities.Employee", "UserId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.WorkShift", "WorkShift") + .WithMany() + .HasForeignKey("WorkShiftId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Department"); + + b.Navigation("Designation"); + + b.Navigation("EmploymentType"); + + b.Navigation("ReportingManager"); + + b.Navigation("User"); + + b.Navigation("WorkShift"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeBankDetail", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeDocument", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.HrDocumentType", "HrDocumentType") + .WithMany() + .HasForeignKey("HrDocumentTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("HrDocumentType"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeLoan", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructure", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructureLine", b => + { + b.HasOne("ERPCore.Domain.Entities.EmployeeSalaryStructure", "EmployeeSalaryStructure") + .WithMany("Lines") + .HasForeignKey("EmployeeSalaryStructureId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalaryComponent", "SalaryComponent") + .WithMany() + .HasForeignKey("SalaryComponentId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("EmployeeSalaryStructure"); + + b.Navigation("SalaryComponent"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Grn", 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.HasOne("ERPCore.Domain.Entities.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("PoId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.PurchaseInvoice", "PurchaseInvoice") + .WithMany() + .HasForeignKey("PurchaseInvoiceId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("PurchaseInvoice"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Vendor"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", "Batch") + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", "Bin") + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Grn", "Grn") + .WithMany("Lines") + .HasForeignKey("GrnId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PoLine", "PoLine") + .WithMany() + .HasForeignKey("PoLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Batch"); + + b.Navigation("Bin"); + + b.Navigation("Grn"); + + b.Navigation("Item"); + + b.Navigation("PoLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLineWarrantyNumber", b => + { + b.HasOne("ERPCore.Domain.Entities.GrnLine", "GrnLine") + .WithMany("WarrantyNumbers") + .HasForeignKey("GrnLineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GrnLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Item", b => + { + b.HasOne("ERPCore.Domain.Entities.Uom", "BaseUom") + .WithMany() + .HasForeignKey("BaseUomId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Brand", "Brand") + .WithMany() + .HasForeignKey("BrandId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Category", "Category") + .WithMany() + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "DefaultVendor") + .WithMany() + .HasForeignKey("DefaultVendorId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.SubCategory", "SubCategory") + .WithMany() + .HasForeignKey("SubCategoryId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.TaxRate", "TaxRate") + .WithMany() + .HasForeignKey("TaxRateId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("BaseUom"); + + b.Navigation("Brand"); + + b.Navigation("Category"); + + b.Navigation("DefaultVendor"); + + b.Navigation("SubCategory"); + + b.Navigation("TaxRate"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ItemReorder", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany("ReorderSettings") + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveBalance", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.LeaveType", "LeaveType") + .WithMany() + .HasForeignKey("LeaveTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("LeaveType"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LeaveRequest", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.LeaveType", "LeaveType") + .WithMany() + .HasForeignKey("LeaveTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("LeaveType"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoanInstallment", b => + { + b.HasOne("ERPCore.Domain.Entities.EmployeeLoan", "EmployeeLoan") + .WithMany("Installments") + .HasForeignKey("EmployeeLoanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PayrollRun", "PayrollRun") + .WithMany() + .HasForeignKey("PayrollRunId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("EmployeeLoan"); + + b.Navigation("PayrollRun"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.LoginActivity", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfigModule", b => + { + b.HasOne("ERPCore.Domain.Entities.NotificationConfig", "NotificationConfig") + .WithMany("Modules") + .HasForeignKey("NotificationConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("NotificationConfig"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationRecipient", b => + { + b.HasOne("ERPCore.Domain.Entities.Notification", "Notification") + .WithMany("Recipients") + .HasForeignKey("NotificationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Notification"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NumberSequence", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") + .WithMany() + .HasForeignKey("EmployeeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PayrollRun", "PayrollRun") + .WithMany("Lines") + .HasForeignKey("PayrollRunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Employee"); + + b.Navigation("PayrollRun"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLineComponent", b => + { + b.HasOne("ERPCore.Domain.Entities.PayrollLine", "PayrollLine") + .WithMany("Components") + .HasForeignKey("PayrollLineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalaryComponent", "SalaryComponent") + .WithMany() + .HasForeignKey("SalaryComponentId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("PayrollLine"); + + b.Navigation("SalaryComponent"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollRun", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Branch"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Payslip", b => + { + b.HasOne("ERPCore.Domain.Entities.PayrollLine", "PayrollLine") + .WithOne() + .HasForeignKey("ERPCore.Domain.Entities.Payslip", "PayrollLineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PayrollLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Permission", b => + { + b.HasOne("ERPCore.Domain.Entities.NavItem", "NavItem") + .WithMany() + .HasForeignKey("NavItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ERPCore.Domain.Entities.SubNavItem", "SubNavItem") + .WithMany() + .HasForeignKey("SubNavItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("NavItem"); + + b.Navigation("SubNavItem"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PoLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseOrder", "PurchaseOrder") + .WithMany("Lines") + .HasForeignKey("PoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductConfig", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "UpdatedByUser") + .WithMany() + .HasForeignKey("UpdatedBy") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("UpdatedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b => + { + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "CancelReason") + .WithMany() + .HasForeignKey("CancelReasonCodeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Bin", "OutputBin") + .WithMany() + .HasForeignKey("OutputBinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") + .WithMany("Runs") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CancelReason"); + + b.Navigation("Creator"); + + b.Navigation("OutputBin"); + + b.Navigation("Template"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionTemplate", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", 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.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoiceLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Grn", "Grn") + .WithMany() + .HasForeignKey("GrnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseInvoice", "PurchaseInvoice") + .WithMany("Lines") + .HasForeignKey("PurchaseInvoiceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Grn"); + + b.Navigation("PurchaseInvoice"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoicePayment", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseInvoice", "PurchaseInvoice") + .WithMany("Payments") + .HasForeignKey("PurchaseInvoiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("PurchaseInvoice"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Approver") + .WithMany() + .HasForeignKey("ApproverUserId"); + + 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.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") + .WithMany() + .HasForeignKey("RequisitionId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Approver"); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("Requisition"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturn", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ReasonCode") + .WithMany() + .HasForeignKey("ReasonCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("ReasonCode"); + + b.Navigation("Vendor"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturnLine", b => + { + b.HasOne("ERPCore.Domain.Entities.GrnLine", "GrnLine") + .WithMany() + .HasForeignKey("GrnLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.PurchaseReturn", "Return") + .WithMany("Lines") + .HasForeignKey("ReturnId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GrnLine"); + + b.Navigation("Item"); + + b.Navigation("Return"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "Requester") + .WithMany() + .HasForeignKey("RequestedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Requester"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RequisitionLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") + .WithMany("Lines") + .HasForeignKey("RequisitionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Requisition"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") + .WithMany() + .HasForeignKey("RequisitionId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Requisition"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RfqLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Rfq", "Rfq") + .WithMany("Lines") + .HasForeignKey("RfqId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Rfq"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RolePermission", b => + { + b.HasOne("ERPCore.Domain.Entities.Permission", "Permission") + .WithMany() + .HasForeignKey("PermissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Role", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Permission"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunEdge", b => + { + b.HasOne("ERPCore.Domain.Entities.RunStage", "ChildRunStage") + .WithMany() + .HasForeignKey("ChildRunStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "ParentRunStage") + .WithMany() + .HasForeignKey("ParentRunStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ProductionRun", "Run") + .WithMany("Edges") + .HasForeignKey("RunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildRunStage"); + + b.Navigation("ParentRunStage"); + + b.Navigation("Run"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStage", b => + { + b.HasOne("ERPCore.Domain.Entities.ProductionRun", "Run") + .WithMany("Stages") + .HasForeignKey("RunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "TemplateStage") + .WithMany() + .HasForeignKey("TemplateStageId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Run"); + + b.Navigation("TemplateStage"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageEvent", b => + { + b.HasOne("ERPCore.Domain.Entities.ProductionRun", "Run") + .WithMany("Events") + .HasForeignKey("RunId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "RunStage") + .WithMany("Events") + .HasForeignKey("RunStageId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Run"); + + b.Navigation("RunStage"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageInput", b => + { + b.HasOne("ERPCore.Domain.Entities.RunStageOutput", "FromRunOutput") + .WithMany() + .HasForeignKey("FromRunOutputId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "RunStage") + .WithMany("Inputs") + .HasForeignKey("RunStageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromRunOutput"); + + b.Navigation("Item"); + + b.Navigation("RunStage"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStageOutput", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.RunStage", "RunStage") + .WithMany("Outputs") + .HasForeignKey("RunStageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ScrapReason") + .WithMany() + .HasForeignKey("ScrapReasonCodeId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Uom", "Uom") + .WithMany() + .HasForeignKey("UomId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Item"); + + b.Navigation("RunStage"); + + b.Navigation("ScrapReason"); + + b.Navigation("Uom"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesDayEnd", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "CashierUser") + .WithMany() + .HasForeignKey("CashierUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "ClosedByUser") + .WithMany() + .HasForeignKey("ClosedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CashierUser"); + + b.Navigation("ClosedByUser"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoice", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatorUserId"); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("Customer"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoiceLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesInvoice", "SalesInvoice") + .WithMany("Lines") + .HasForeignKey("SalesInvoiceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SalesInvoice"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoicePayment", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesInvoice", "SalesInvoice") + .WithMany("Payments") + .HasForeignKey("SalesInvoiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("SalesInvoice"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturn", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "Creator") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ReasonCode", "ReasonCode") + .WithMany() + .HasForeignKey("ReasonCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Creator"); + + b.Navigation("Customer"); + + b.Navigation("ReasonCode"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturnLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesReturn", "Return") + .WithMany("Lines") + .HasForeignKey("ReturnId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesInvoiceLine", "SalesInvoiceLine") + .WithMany() + .HasForeignKey("SalesInvoiceLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Item"); + + b.Navigation("Return"); + + b.Navigation("SalesInvoiceLine"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlip", b => + { + b.HasOne("ERPCore.Domain.Entities.User", "CashierUser") + .WithMany() + .HasForeignKey("CashierUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesDayEnd", "DayEnd") + .WithMany("Slips") + .HasForeignKey("DayEndId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CashierUser"); + + b.Navigation("Customer"); + + b.Navigation("DayEnd"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlipLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", "Batch") + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.SalesSlip", "SalesSlip") + .WithMany("Lines") + .HasForeignKey("SalesSlipId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", "Serial") + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Batch"); + + b.Navigation("Item"); + + b.Navigation("SalesSlip"); + + b.Navigation("Serial"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Serial", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageEdge", b => + { + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "ChildStage") + .WithMany() + .HasForeignKey("ChildStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "ParentStage") + .WithMany() + .HasForeignKey("ParentStageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") + .WithMany("Edges") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildStage"); + + b.Navigation("ParentStage"); + + b.Navigation("Template"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageInput", b => + { + b.HasOne("ERPCore.Domain.Entities.StageOutput", "FromOutput") + .WithMany() + .HasForeignKey("FromOutputId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "Stage") + .WithMany("Inputs") + .HasForeignKey("StageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromOutput"); + + b.Navigation("Item"); + + b.Navigation("Stage"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StageOutput", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.TemplateStage", "Stage") + .WithMany("Outputs") + .HasForeignKey("StageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Uom", "Uom") + .WithMany() + .HasForeignKey("UomId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Item"); + + b.Navigation("Stage"); + + b.Navigation("Uom"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustment", 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.HasOne("ERPCore.Domain.Entities.ReasonCode", "ReasonCode") + .WithMany() + .HasForeignKey("ReasonCodeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("ReasonCode"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustmentLine", b => + { + b.HasOne("ERPCore.Domain.Entities.StockAdjustment", "Adjustment") + .WithMany("Lines") + .HasForeignKey("AdjustmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Batch", null) + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", null) + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Adjustment"); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCount", 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.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCountLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", "Batch") + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.StockCount", "Count") + .WithMany("Lines") + .HasForeignKey("CountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", "Serial") + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Batch"); + + b.Navigation("Count"); + + b.Navigation("Item"); + + b.Navigation("Serial"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLayer", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", "Batch") + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.GrnLine", "GrnLine") + .WithMany() + .HasForeignKey("GrnLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", "Serial") + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Batch"); + + b.Navigation("GrnLine"); + + b.Navigation("Item"); + + b.Navigation("Serial"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockLedger", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", null) + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("BinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", null) + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", null) + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", null) + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransfer", 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.HasOne("ERPCore.Domain.Entities.Warehouse", "DestWarehouse") + .WithMany() + .HasForeignKey("DestWarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Warehouse", "SrcWarehouse") + .WithMany() + .HasForeignKey("SrcWarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + + b.Navigation("Creator"); + + b.Navigation("DestWarehouse"); + + b.Navigation("SrcWarehouse"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransferLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Batch", null) + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("DestBinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Serial", null) + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.Bin", null) + .WithMany() + .HasForeignKey("SrcBinId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ERPCore.Domain.Entities.StockTransfer", "Transfer") + .WithMany("Lines") + .HasForeignKey("TransferId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Transfer"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubCategory", b => + { + b.HasOne("ERPCore.Domain.Entities.Category", "Category") + .WithMany("SubCategories") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SubNavItem", b => + { + b.HasOne("ERPCore.Domain.Entities.NavItem", "NavItem") + .WithMany("Children") + .HasForeignKey("NavItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("NavItem"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicketMessage", b => + { + b.HasOne("ERPCore.Domain.Entities.SupportTicket", "Ticket") + .WithMany("Messages") + .HasForeignKey("TicketId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ticket"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => + { + b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") + .WithMany("Stages") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Template"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.User", b => + { + b.HasOne("ERPCore.Domain.Entities.Role", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Vendor", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => + { + b.HasOne("ERPCore.Domain.Entities.Rfq", "Rfq") + .WithMany("Quotations") + .HasForeignKey("RfqId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.Vendor", "Vendor") + .WithMany() + .HasForeignKey("VendorId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Rfq"); + + b.Navigation("Vendor"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotationLine", b => + { + b.HasOne("ERPCore.Domain.Entities.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.VendorQuotation", "Quotation") + .WithMany("Lines") + .HasForeignKey("QuotationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Quotation"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Warehouse", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSale", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.BundleSaleTemplate", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Category", b => + { + b.Navigation("SubCategories"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeLoan", b => + { + b.Navigation("Installments"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.EmployeeSalaryStructure", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Grn", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.GrnLine", b => + { + b.Navigation("WarrantyNumbers"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Item", b => + { + b.Navigation("ReorderSettings"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NavItem", b => + { + b.Navigation("Children"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Notification", b => + { + b.Navigation("Recipients"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => + { + b.Navigation("Modules"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => + { + b.Navigation("Components"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollRun", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionRun", b => + { + b.Navigation("Edges"); + + b.Navigation("Events"); + + b.Navigation("Stages"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.ProductionTemplate", b => + { + b.Navigation("Edges"); + + b.Navigation("Runs"); + + b.Navigation("Stages"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", b => + { + b.Navigation("Lines"); + + b.Navigation("Payments"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseReturn", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => + { + b.Navigation("Lines"); + + b.Navigation("Quotations"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.RunStage", b => + { + b.Navigation("Events"); + + b.Navigation("Inputs"); + + b.Navigation("Outputs"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesDayEnd", b => + { + b.Navigation("BundleSales"); + + b.Navigation("Slips"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesInvoice", b => + { + b.Navigation("Lines"); + + b.Navigation("Payments"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesReturn", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlip", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockAdjustment", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockCount", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.StockTransfer", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicket", b => + { + b.Navigation("Messages"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => + { + b.Navigation("Inputs"); + + b.Navigation("Outputs"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => + { + b.Navigation("Lines"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.Warehouse", b => + { + b.Navigation("Bins"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Backend/ERPCore/Migrations/20260917052720_AddBarcodeLotScanning.cs b/Backend/ERPCore/Migrations/20260917052720_AddBarcodeLotScanning.cs new file mode 100644 index 0000000..0c90d77 --- /dev/null +++ b/Backend/ERPCore/Migrations/20260917052720_AddBarcodeLotScanning.cs @@ -0,0 +1,205 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace ERPCore.Migrations +{ + /// + public partial class AddBarcodeLotScanning : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "BatchId", + table: "stock_count_lines", + type: "integer", + nullable: true); + + migrationBuilder.AddColumn( + name: "SerialId", + table: "stock_count_lines", + type: "integer", + nullable: true); + + migrationBuilder.AddColumn( + name: "Barcode", + table: "serials", + type: "character varying(100)", + maxLength: 100, + nullable: true); + + migrationBuilder.AddColumn( + name: "BatchId", + table: "sales_slip_lines", + type: "integer", + nullable: true); + + migrationBuilder.AddColumn( + name: "SerialId", + table: "sales_slip_lines", + type: "integer", + nullable: true); + + migrationBuilder.AddColumn( + name: "Barcode", + table: "items", + type: "character varying(100)", + maxLength: 100, + nullable: true); + + migrationBuilder.AddColumn( + name: "Barcode", + table: "batches", + type: "character varying(100)", + maxLength: 100, + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_stock_count_lines_BatchId", + table: "stock_count_lines", + column: "BatchId"); + + migrationBuilder.CreateIndex( + name: "IX_stock_count_lines_SerialId", + table: "stock_count_lines", + column: "SerialId"); + + migrationBuilder.CreateIndex( + name: "IX_serials_Barcode", + table: "serials", + column: "Barcode", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_sales_slip_lines_BatchId", + table: "sales_slip_lines", + column: "BatchId"); + + migrationBuilder.CreateIndex( + name: "IX_sales_slip_lines_SerialId", + table: "sales_slip_lines", + column: "SerialId"); + + migrationBuilder.CreateIndex( + name: "IX_items_Barcode", + table: "items", + column: "Barcode", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_batches_Barcode", + table: "batches", + column: "Barcode", + unique: true); + + migrationBuilder.AddForeignKey( + name: "FK_sales_slip_lines_batches_BatchId", + table: "sales_slip_lines", + column: "BatchId", + principalTable: "batches", + principalColumn: "BatchId", + onDelete: ReferentialAction.Restrict); + + migrationBuilder.AddForeignKey( + name: "FK_sales_slip_lines_serials_SerialId", + table: "sales_slip_lines", + column: "SerialId", + principalTable: "serials", + principalColumn: "SerialId", + onDelete: ReferentialAction.Restrict); + + migrationBuilder.AddForeignKey( + name: "FK_stock_count_lines_batches_BatchId", + table: "stock_count_lines", + column: "BatchId", + principalTable: "batches", + principalColumn: "BatchId", + onDelete: ReferentialAction.Restrict); + + migrationBuilder.AddForeignKey( + name: "FK_stock_count_lines_serials_SerialId", + table: "stock_count_lines", + column: "SerialId", + principalTable: "serials", + principalColumn: "SerialId", + onDelete: ReferentialAction.Restrict); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_sales_slip_lines_batches_BatchId", + table: "sales_slip_lines"); + + migrationBuilder.DropForeignKey( + name: "FK_sales_slip_lines_serials_SerialId", + table: "sales_slip_lines"); + + migrationBuilder.DropForeignKey( + name: "FK_stock_count_lines_batches_BatchId", + table: "stock_count_lines"); + + migrationBuilder.DropForeignKey( + name: "FK_stock_count_lines_serials_SerialId", + table: "stock_count_lines"); + + migrationBuilder.DropIndex( + name: "IX_stock_count_lines_BatchId", + table: "stock_count_lines"); + + migrationBuilder.DropIndex( + name: "IX_stock_count_lines_SerialId", + table: "stock_count_lines"); + + migrationBuilder.DropIndex( + name: "IX_serials_Barcode", + table: "serials"); + + migrationBuilder.DropIndex( + name: "IX_sales_slip_lines_BatchId", + table: "sales_slip_lines"); + + migrationBuilder.DropIndex( + name: "IX_sales_slip_lines_SerialId", + table: "sales_slip_lines"); + + migrationBuilder.DropIndex( + name: "IX_items_Barcode", + table: "items"); + + migrationBuilder.DropIndex( + name: "IX_batches_Barcode", + table: "batches"); + + migrationBuilder.DropColumn( + name: "BatchId", + table: "stock_count_lines"); + + migrationBuilder.DropColumn( + name: "SerialId", + table: "stock_count_lines"); + + migrationBuilder.DropColumn( + name: "Barcode", + table: "serials"); + + migrationBuilder.DropColumn( + name: "BatchId", + table: "sales_slip_lines"); + + migrationBuilder.DropColumn( + name: "SerialId", + table: "sales_slip_lines"); + + migrationBuilder.DropColumn( + name: "Barcode", + table: "items"); + + migrationBuilder.DropColumn( + name: "Barcode", + table: "batches"); + } + } +} diff --git a/Backend/ERPCore/Migrations/ErpDbContextModelSnapshot.cs b/Backend/ERPCore/Migrations/ErpDbContextModelSnapshot.cs index 35bad24..58f6338 100644 --- a/Backend/ERPCore/Migrations/ErpDbContextModelSnapshot.cs +++ b/Backend/ERPCore/Migrations/ErpDbContextModelSnapshot.cs @@ -225,6 +225,10 @@ namespace ERPCore.Migrations NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BatchId")); + b.Property("Barcode") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + b.Property("BatchNo") .IsRequired() .HasMaxLength(50) @@ -238,6 +242,9 @@ namespace ERPCore.Migrations b.HasKey("BatchId"); + b.HasIndex("Barcode") + .IsUnique(); + b.HasIndex("ItemId", "BatchNo") .IsUnique(); @@ -349,6 +356,9 @@ namespace ERPCore.Migrations b.Property("UpdatedBy") .HasColumnType("integer"); + b.Property("WarehouseBranchingEnabled") + .HasColumnType("boolean"); + b.HasKey("ConfigId"); b.HasIndex("UpdatedBy"); @@ -717,6 +727,9 @@ namespace ERPCore.Migrations .HasMaxLength(250) .HasColumnType("character varying(250)"); + b.Property("BranchId") + .HasColumnType("integer"); + b.Property("City") .HasMaxLength(100) .HasColumnType("character varying(100)"); @@ -789,6 +802,8 @@ namespace ERPCore.Migrations b.HasKey("CustomerId"); + b.HasIndex("BranchId"); + b.HasIndex("CustomerCode") .IsUnique(); @@ -1688,6 +1703,10 @@ namespace ERPCore.Migrations NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ItemId")); + b.Property("Barcode") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + b.Property("BaseUomId") .HasColumnType("integer"); @@ -1766,9 +1785,8 @@ namespace ERPCore.Migrations b.Property("SubCategoryId") .HasColumnType("integer"); - b.Property("TaxClass") - .HasMaxLength(20) - .HasColumnType("character varying(20)"); + b.Property("TaxRateId") + .HasColumnType("integer"); b.Property("TrackingMode") .IsRequired() @@ -1790,6 +1808,9 @@ namespace ERPCore.Migrations b.HasKey("ItemId"); + b.HasIndex("Barcode") + .IsUnique(); + b.HasIndex("BaseUomId"); b.HasIndex("BrandId"); @@ -1805,6 +1826,8 @@ namespace ERPCore.Migrations b.HasIndex("SubCategoryId"); + b.HasIndex("TaxRateId"); + b.ToTable("items", (string)null); }); @@ -2367,6 +2390,46 @@ namespace ERPCore.Migrations }); }); + modelBuilder.Entity("ERPCore.Domain.Entities.Notification", b => + { + b.Property("NotificationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NotificationId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("ModuleKey") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("RelatedEntityId") + .HasColumnType("integer"); + + b.Property("RelatedEntityType") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.HasKey("NotificationId"); + + b.HasIndex("CreatedAt"); + + b.ToTable("notifications", (string)null); + }); + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => { b.Property("NotificationConfigId") @@ -2435,6 +2498,35 @@ namespace ERPCore.Migrations b.ToTable("notification_config_modules", (string)null); }); + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationRecipient", b => + { + b.Property("NotificationRecipientId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("NotificationRecipientId")); + + b.Property("IsRead") + .HasColumnType("boolean"); + + b.Property("NotificationId") + .HasColumnType("integer"); + + b.Property("ReadAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("NotificationRecipientId"); + + b.HasIndex("NotificationId"); + + b.HasIndex("UserId", "IsRead", "NotificationId"); + + b.ToTable("notification_recipients", (string)null); + }); + modelBuilder.Entity("ERPCore.Domain.Entities.NumberSequence", b => { b.Property("SequenceId") @@ -2443,6 +2535,10 @@ namespace ERPCore.Migrations NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SequenceId")); + b.Property("BranchId") + .HasColumnType("integer") + .HasColumnName("branch_id"); + b.Property("DocType") .IsRequired() .HasMaxLength(10) @@ -2459,7 +2555,9 @@ namespace ERPCore.Migrations b.HasKey("SequenceId"); - b.HasIndex("DocType", "Year") + b.HasIndex("BranchId"); + + b.HasIndex("DocType", "BranchId", "Year") .IsUnique(); b.ToTable("number_sequences", (string)null); @@ -3086,6 +3184,12 @@ namespace ERPCore.Migrations PermissionId = 52, Code = "NAV:sales.day-end", SubNavItemId = 42 + }, + new + { + PermissionId = 53, + Code = "NAV:products.tax-rates", + SubNavItemId = 43 }); }); @@ -3337,6 +3441,9 @@ namespace ERPCore.Migrations .HasPrecision(18, 4) .HasColumnType("numeric(18,4)"); + b.Property("BranchId") + .HasColumnType("integer"); + b.Property("CreatedAt") .HasColumnType("timestamp with time zone"); @@ -3409,6 +3516,8 @@ namespace ERPCore.Migrations b.HasKey("PurchaseInvoiceId"); + b.HasIndex("BranchId"); + b.HasIndex("CreatedBy"); b.HasIndex("DocNo") @@ -3519,6 +3628,18 @@ namespace ERPCore.Migrations b.Property("ApprovalRequired") .HasColumnType("boolean"); + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedBy") + .HasColumnType("integer"); + + b.Property("ApproverUserId") + .HasColumnType("integer"); + + b.Property("BranchId") + .HasColumnType("integer"); + b.Property("CreatedAt") .HasColumnType("timestamp with time zone"); @@ -3552,6 +3673,10 @@ namespace ERPCore.Migrations b.HasKey("PoId"); + b.HasIndex("ApproverUserId"); + + b.HasIndex("BranchId"); + b.HasIndex("CreatedBy"); b.HasIndex("DocNo") @@ -3693,6 +3818,9 @@ namespace ERPCore.Migrations NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RequisitionId")); + b.Property("BranchId") + .HasColumnType("integer"); + b.Property("CreatedAt") .HasColumnType("timestamp with time zone"); @@ -3711,6 +3839,8 @@ namespace ERPCore.Migrations b.HasKey("RequisitionId"); + b.HasIndex("BranchId"); + b.HasIndex("DocNo") .IsUnique(); @@ -3759,6 +3889,9 @@ namespace ERPCore.Migrations NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("RfqId")); + b.Property("BranchId") + .HasColumnType("integer"); + b.Property("CreatedAt") .HasColumnType("timestamp with time zone"); @@ -3777,6 +3910,8 @@ namespace ERPCore.Migrations b.HasKey("RfqId"); + b.HasIndex("BranchId"); + b.HasIndex("DocNo") .IsUnique(); @@ -3877,6 +4012,11 @@ namespace ERPCore.Migrations b.Property("PermissionId") .HasColumnType("integer"); + b.Property("Actions") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(31); + b.HasKey("RoleId", "PermissionId"); b.HasIndex("PermissionId"); @@ -4205,6 +4345,10 @@ namespace ERPCore.Migrations NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SalesDayEndId")); + b.Property("BalanceTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + b.Property("BundleCount") .ValueGeneratedOnAdd() .HasColumnType("integer") @@ -4246,6 +4390,10 @@ namespace ERPCore.Migrations .HasPrecision(18, 4) .HasColumnType("numeric(18,4)"); + b.Property("PaidTotal") + .HasPrecision(18, 4) + .HasColumnType("numeric(18,4)"); + b.Property("RowVersion") .IsConcurrencyToken() .ValueGeneratedOnAddOrUpdate() @@ -4739,6 +4887,9 @@ namespace ERPCore.Migrations .HasPrecision(18, 4) .HasColumnType("numeric(18,4)"); + b.Property("BatchId") + .HasColumnType("integer"); + b.Property("Description") .IsRequired() .HasMaxLength(200) @@ -4794,6 +4945,9 @@ namespace ERPCore.Migrations b.Property("SalesSlipId") .HasColumnType("integer"); + b.Property("SerialId") + .HasColumnType("integer"); + b.Property("TaxAmount") .HasPrecision(18, 4) .HasColumnType("numeric(18,4)"); @@ -4811,10 +4965,14 @@ namespace ERPCore.Migrations b.HasKey("SalesSlipLineId"); + b.HasIndex("BatchId"); + b.HasIndex("ItemId"); b.HasIndex("SalesSlipId"); + b.HasIndex("SerialId"); + b.HasIndex("WarehouseId"); b.ToTable("sales_slip_lines", (string)null); @@ -4828,6 +4986,10 @@ namespace ERPCore.Migrations NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SerialId")); + b.Property("Barcode") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + b.Property("ItemId") .HasColumnType("integer"); @@ -4843,6 +5005,9 @@ namespace ERPCore.Migrations b.HasKey("SerialId"); + b.HasIndex("Barcode") + .IsUnique(); + b.HasIndex("ItemId", "SerialNo") .IsUnique(); @@ -5126,6 +5291,9 @@ namespace ERPCore.Migrations NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CountLineId")); + b.Property("BatchId") + .HasColumnType("integer"); + b.Property("BinId") .HasColumnType("integer"); @@ -5139,6 +5307,9 @@ namespace ERPCore.Migrations b.Property("ItemId") .HasColumnType("integer"); + b.Property("SerialId") + .HasColumnType("integer"); + b.Property("SystemQty") .HasPrecision(18, 4) .HasColumnType("numeric(18,4)"); @@ -5149,12 +5320,16 @@ namespace ERPCore.Migrations b.HasKey("CountLineId"); + b.HasIndex("BatchId"); + b.HasIndex("BinId"); b.HasIndex("CountId"); b.HasIndex("ItemId"); + b.HasIndex("SerialId"); + b.ToTable("stock_count_lines", (string)null); }); @@ -5557,6 +5732,16 @@ namespace ERPCore.Migrations Status = "Active" }, new + { + SubNavItemId = 43, + Code = "products.tax-rates", + Href = "/dashboard/products/tax-rates", + Label = "Tax Rates", + NavItemId = 2, + SortOrder = 7, + Status = "Active" + }, + new { SubNavItemId = 29, Code = "settings.branches", @@ -5908,6 +6093,166 @@ namespace ERPCore.Migrations }); }); + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicket", b => + { + b.Property("TicketId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TicketId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .HasColumnType("integer"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Subject") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedBy") + .HasColumnType("integer"); + + b.HasKey("TicketId"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("Status"); + + b.ToTable("support_tickets", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicketMessage", b => + { + b.Property("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("MessageId")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsFromAdmin") + .HasColumnType("boolean"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("SenderUserId") + .HasColumnType("integer"); + + b.Property("TicketId") + .HasColumnType("integer"); + + b.HasKey("MessageId"); + + b.HasIndex("TicketId", "CreatedAt"); + + b.ToTable("support_ticket_messages", (string)null); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.TaxRate", b => + { + b.Property("TaxRateId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TaxRateId")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Percentage") + .HasPrecision(5, 2) + .HasColumnType("numeric(5,2)"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("TaxRateId"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("Status"); + + b.ToTable("tax_rates", (string)null); + + b.HasData( + new + { + TaxRateId = 1, + Code = "STANDARD", + CreatedAt = new DateTime(2026, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc), + Name = "Standard", + Percentage = 15m, + RowVersion = 0u, + Status = "Active" + }, + new + { + TaxRateId = 2, + Code = "ZERO", + CreatedAt = new DateTime(2026, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc), + Name = "Zero-Rated", + Percentage = 0m, + RowVersion = 0u, + Status = "Active" + }, + new + { + TaxRateId = 3, + Code = "EXEMPT", + CreatedAt = new DateTime(2026, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc), + Name = "Exempt", + Percentage = 0m, + RowVersion = 0u, + Status = "Active" + }); + }); + modelBuilder.Entity("ERPCore.Domain.Entities.TaxSlab", b => { b.Property("TaxSlabId") @@ -6000,16 +6345,31 @@ namespace ERPCore.Migrations NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("UomId")); + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + b.Property("Name") .IsRequired() .HasMaxLength(50) .HasColumnType("character varying(50)"); + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasDefaultValue("Active"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + b.HasKey("UomId"); b.HasIndex("Name") .IsUnique(); + b.HasIndex("Status"); + b.ToTable("uoms", (string)null); }); @@ -6080,6 +6440,9 @@ namespace ERPCore.Migrations NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("VendorId")); + b.Property("BranchId") + .HasColumnType("integer"); + b.Property("Code") .IsRequired() .HasMaxLength(50) @@ -6126,6 +6489,8 @@ namespace ERPCore.Migrations b.HasKey("VendorId"); + b.HasIndex("BranchId"); + b.HasIndex("Code") .IsUnique(); @@ -6199,6 +6564,9 @@ namespace ERPCore.Migrations NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("WarehouseId")); + b.Property("Address") + .HasColumnType("text"); + b.Property("BranchId") .HasColumnType("integer"); @@ -6212,6 +6580,9 @@ namespace ERPCore.Migrations .HasMaxLength(200) .HasColumnType("character varying(200)"); + b.Property("Phone") + .HasColumnType("text"); + b.HasKey("WarehouseId"); b.HasIndex("BranchId"); @@ -6459,11 +6830,19 @@ namespace ERPCore.Migrations modelBuilder.Entity("ERPCore.Domain.Entities.Customer", b => { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + b.HasOne("ERPCore.Domain.Entities.Warehouse", "DefaultWarehouse") .WithMany() .HasForeignKey("DefaultWarehouseId") .OnDelete(DeleteBehavior.SetNull); + b.Navigation("Branch"); + b.Navigation("DefaultWarehouse"); }); @@ -6748,6 +7127,11 @@ namespace ERPCore.Migrations .HasForeignKey("SubCategoryId") .OnDelete(DeleteBehavior.Restrict); + b.HasOne("ERPCore.Domain.Entities.TaxRate", "TaxRate") + .WithMany() + .HasForeignKey("TaxRateId") + .OnDelete(DeleteBehavior.Restrict); + b.Navigation("BaseUom"); b.Navigation("Brand"); @@ -6757,6 +7141,8 @@ namespace ERPCore.Migrations b.Navigation("DefaultVendor"); b.Navigation("SubCategory"); + + b.Navigation("TaxRate"); }); modelBuilder.Entity("ERPCore.Domain.Entities.ItemReorder", b => @@ -6866,6 +7252,36 @@ namespace ERPCore.Migrations b.Navigation("NotificationConfig"); }); + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationRecipient", b => + { + b.HasOne("ERPCore.Domain.Entities.Notification", "Notification") + .WithMany("Recipients") + .HasForeignKey("NotificationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ERPCore.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Notification"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ERPCore.Domain.Entities.NumberSequence", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + }); + modelBuilder.Entity("ERPCore.Domain.Entities.PayrollLine", b => { b.HasOne("ERPCore.Domain.Entities.Employee", "Employee") @@ -7032,6 +7448,12 @@ namespace ERPCore.Migrations modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseInvoice", 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") @@ -7044,6 +7466,8 @@ namespace ERPCore.Migrations .OnDelete(DeleteBehavior.Restrict) .IsRequired(); + b.Navigation("Branch"); + b.Navigation("Creator"); b.Navigation("Vendor"); @@ -7089,6 +7513,16 @@ namespace ERPCore.Migrations modelBuilder.Entity("ERPCore.Domain.Entities.PurchaseOrder", b => { + b.HasOne("ERPCore.Domain.Entities.User", "Approver") + .WithMany() + .HasForeignKey("ApproverUserId"); + + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + b.HasOne("ERPCore.Domain.Entities.User", "Creator") .WithMany() .HasForeignKey("CreatedBy") @@ -7106,6 +7540,10 @@ namespace ERPCore.Migrations .OnDelete(DeleteBehavior.Restrict) .IsRequired(); + b.Navigation("Approver"); + + b.Navigation("Branch"); + b.Navigation("Creator"); b.Navigation("Requisition"); @@ -7176,12 +7614,20 @@ namespace ERPCore.Migrations modelBuilder.Entity("ERPCore.Domain.Entities.Requisition", b => { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + b.HasOne("ERPCore.Domain.Entities.User", "Requester") .WithMany() .HasForeignKey("RequestedBy") .OnDelete(DeleteBehavior.Restrict) .IsRequired(); + b.Navigation("Branch"); + b.Navigation("Requester"); }); @@ -7206,12 +7652,20 @@ namespace ERPCore.Migrations modelBuilder.Entity("ERPCore.Domain.Entities.Rfq", b => { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + b.HasOne("ERPCore.Domain.Entities.Requisition", "Requisition") .WithMany() .HasForeignKey("RequisitionId") .OnDelete(DeleteBehavior.Restrict) .IsRequired(); + b.Navigation("Branch"); + b.Navigation("Requisition"); }); @@ -7576,6 +8030,11 @@ namespace ERPCore.Migrations modelBuilder.Entity("ERPCore.Domain.Entities.SalesSlipLine", b => { + b.HasOne("ERPCore.Domain.Entities.Batch", "Batch") + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + b.HasOne("ERPCore.Domain.Entities.Item", "Item") .WithMany() .HasForeignKey("ItemId") @@ -7588,16 +8047,25 @@ namespace ERPCore.Migrations .OnDelete(DeleteBehavior.Cascade) .IsRequired(); + b.HasOne("ERPCore.Domain.Entities.Serial", "Serial") + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + b.HasOne("ERPCore.Domain.Entities.Warehouse", "Warehouse") .WithMany() .HasForeignKey("WarehouseId") .OnDelete(DeleteBehavior.Restrict) .IsRequired(); + b.Navigation("Batch"); + b.Navigation("Item"); b.Navigation("SalesSlip"); + b.Navigation("Serial"); + b.Navigation("Warehouse"); }); @@ -7787,6 +8255,11 @@ namespace ERPCore.Migrations modelBuilder.Entity("ERPCore.Domain.Entities.StockCountLine", b => { + b.HasOne("ERPCore.Domain.Entities.Batch", "Batch") + .WithMany() + .HasForeignKey("BatchId") + .OnDelete(DeleteBehavior.Restrict); + b.HasOne("ERPCore.Domain.Entities.Bin", null) .WithMany() .HasForeignKey("BinId") @@ -7804,9 +8277,18 @@ namespace ERPCore.Migrations .OnDelete(DeleteBehavior.Restrict) .IsRequired(); + b.HasOne("ERPCore.Domain.Entities.Serial", "Serial") + .WithMany() + .HasForeignKey("SerialId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Batch"); + b.Navigation("Count"); b.Navigation("Item"); + + b.Navigation("Serial"); }); modelBuilder.Entity("ERPCore.Domain.Entities.StockLayer", b => @@ -7981,6 +8463,17 @@ namespace ERPCore.Migrations b.Navigation("NavItem"); }); + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicketMessage", b => + { + b.HasOne("ERPCore.Domain.Entities.SupportTicket", "Ticket") + .WithMany("Messages") + .HasForeignKey("TicketId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ticket"); + }); + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => { b.HasOne("ERPCore.Domain.Entities.ProductionTemplate", "Template") @@ -8002,6 +8495,17 @@ namespace ERPCore.Migrations b.Navigation("Role"); }); + modelBuilder.Entity("ERPCore.Domain.Entities.Vendor", b => + { + b.HasOne("ERPCore.Domain.Entities.Branch", "Branch") + .WithMany() + .HasForeignKey("BranchId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Branch"); + }); + modelBuilder.Entity("ERPCore.Domain.Entities.VendorQuotation", b => { b.HasOne("ERPCore.Domain.Entities.Rfq", "Rfq") @@ -8096,6 +8600,11 @@ namespace ERPCore.Migrations b.Navigation("Children"); }); + modelBuilder.Entity("ERPCore.Domain.Entities.Notification", b => + { + b.Navigation("Recipients"); + }); + modelBuilder.Entity("ERPCore.Domain.Entities.NotificationConfig", b => { b.Navigation("Modules"); @@ -8206,6 +8715,11 @@ namespace ERPCore.Migrations b.Navigation("Lines"); }); + modelBuilder.Entity("ERPCore.Domain.Entities.SupportTicket", b => + { + b.Navigation("Messages"); + }); + modelBuilder.Entity("ERPCore.Domain.Entities.TemplateStage", b => { b.Navigation("Inputs"); diff --git a/Backend/ERPCore/Program.cs b/Backend/ERPCore/Program.cs index 3b3f451..5294c25 100644 --- a/Backend/ERPCore/Program.cs +++ b/Backend/ERPCore/Program.cs @@ -15,6 +15,7 @@ using ERPCore.Services.Production; using ERPCore.Services.Stock; using ERPCore.System.Errors; using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authorization; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.OpenApi; @@ -46,6 +47,12 @@ builder.Services.AddExceptionHandler(); // Auth: validate external AuthHex RS256 tokens + ERP door policy (docs/10 A.4) builder.Services.AddErpJwtAuth(builder.Configuration); +// Per-endpoint RBAC (docs/02-SECURITY.md AR-01) — [Authorize(Policy = NavPolicies.For("..."))]. +builder.Services.AddMemoryCache(); +builder.Services.AddScoped(); +builder.Services.AddSingleton(); +builder.Services.AddScoped(); + // AuthController proxy → AuthHex (docs/11 §2.0) builder.Services.AddHttpClient(c => { @@ -70,6 +77,7 @@ builder.Services.AddScoped(); // JIT-provisions a local shadow user and injects the local `int` id as `nameid`. builder.Services.AddHttpContextAccessor(); builder.Services.AddScoped(); +builder.Services.AddScoped(); builder.Services.AddScoped(); // Unit of work + generic repository base @@ -82,6 +90,7 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); builder.Services.AddScoped(); //builder.Services.AddScoped(); builder.Services.AddScoped(); @@ -89,8 +98,11 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddSingleton(); builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); // RBAC / sidebar: Role (shadow of AuthHex) + Permission assignment + user management builder.Services.AddScoped(); diff --git a/Backend/ERPCore/Services/AdjustmentService.cs b/Backend/ERPCore/Services/AdjustmentService.cs index ceab142..baee3bc 100644 --- a/Backend/ERPCore/Services/AdjustmentService.cs +++ b/Backend/ERPCore/Services/AdjustmentService.cs @@ -33,6 +33,7 @@ public sealed class AdjustmentService : IAdjustmentService private readonly INumberSequenceService _numbers; private readonly ICurrentUser _currentUser; private readonly IBranchConfigService _branchConfig; + private readonly INotificationService _notifications; private readonly IUnitOfWork _uow; private readonly IGeneralLedgerService _gl; private readonly string _glInventoryAccountCode; @@ -42,7 +43,7 @@ public sealed class AdjustmentService : IAdjustmentService public AdjustmentService( IRepository adjustments, IRepository warehouses, IRepository items, IRepository reasonCodes, IRepository ledger, IStockMutator mutator, - INumberSequenceService numbers, ICurrentUser currentUser, IBranchConfigService branchConfig, IUnitOfWork uow, + INumberSequenceService numbers, ICurrentUser currentUser, IBranchConfigService branchConfig, INotificationService notifications, IUnitOfWork uow, IGeneralLedgerService gl, IConfiguration configuration) { _adjustments = adjustments; @@ -54,6 +55,7 @@ public sealed class AdjustmentService : IAdjustmentService _numbers = numbers; _currentUser = currentUser; _branchConfig = branchConfig; + _notifications = notifications; _uow = uow; _gl = gl; _glInventoryAccountCode = configuration["Adjustment:GlInventoryAccountCode"] ?? string.Empty; @@ -198,6 +200,8 @@ public sealed class AdjustmentService : IAdjustmentService return (entity, refs); }, ct); + await _notifications.RaiseAsync("stock.adjustment.created", "Stock Adjustment Created", $"Stock adjustment {adjustment.DocNo} was created.", nameof(StockAdjustment), adjustment.AdjustmentId, ct); + return ToDto(adjustment, ledgerRefs.Select(l => l.LedgerId).ToList()); } diff --git a/Backend/ERPCore/Services/BranchConfigService.cs b/Backend/ERPCore/Services/BranchConfigService.cs index d688687..5fc9194 100644 --- a/Backend/ERPCore/Services/BranchConfigService.cs +++ b/Backend/ERPCore/Services/BranchConfigService.cs @@ -53,6 +53,7 @@ public sealed class BranchConfigService : IBranchConfigService throw new DomainException(ErrorCodes.ConcurrencyConflict, "The configuration was modified by another request.", 412); config.BranchingEnabled = request.BranchingEnabled!.Value; + config.WarehouseBranchingEnabled = request.WarehouseBranchingEnabled!.Value; config.UpdatedAt = DateTime.UtcNow; config.UpdatedBy = _currentUser.AuditUserId; @@ -86,9 +87,34 @@ public sealed class BranchConfigService : IBranchConfigService return requestedBranchId; } - // Branching is off — ignore whatever was posted and use the deployment's one default - // branch, creating it on first use (same placeholder MakeEmployeeBranchRequired/ - // AddWarehouseBranch backfill onto for pre-existing rows). + return await ResolveDefaultBranchIdAsync(ct); + } + + public async Task IsWarehouseBranchingEnabledAsync(CancellationToken ct = default) + { + var config = await _config.Query().AsNoTracking() + .FirstOrDefaultAsync(c => c.ConfigId == BranchConfig.SingletonId, ct); + // The global flag off implies this is meaningless (and effectively off) too. + return (config?.BranchingEnabled ?? true) && (config?.WarehouseBranchingEnabled ?? true); + } + + public async Task ResolveWarehouseBranchIdAsync(int requestedBranchId, CancellationToken ct = default) + { + if (await IsWarehouseBranchingEnabledAsync(ct)) + { + if (requestedBranchId <= 0) + throw new DomainException(ErrorCodes.Validation, "Branch is required.", 422); + return requestedBranchId; + } + + return await ResolveDefaultBranchIdAsync(ct); + } + + // Branching (or warehouse branching specifically) is off — ignore whatever was posted and + // use the deployment's one default branch, creating it on first use (same placeholder + // MakeEmployeeBranchRequired/AddWarehouseBranch backfill onto for pre-existing rows). + public async Task ResolveDefaultBranchIdAsync(CancellationToken ct = default) + { var existingId = await _branches.Query().AsNoTracking() .Where(b => b.Code == DefaultBranchCode).Select(b => b.BranchId).FirstOrDefaultAsync(ct); if (existingId != 0) return existingId; @@ -99,5 +125,5 @@ public sealed class BranchConfigService : IBranchConfigService return branch.BranchId; } - private static BranchConfigDto Map(BranchConfig c) => new(c.BranchingEnabled, c.UpdatedAt, c.UpdatedBy); + private static BranchConfigDto Map(BranchConfig c) => new(c.BranchingEnabled, c.WarehouseBranchingEnabled, c.UpdatedAt, c.UpdatedBy); } diff --git a/Backend/ERPCore/Services/CountService.cs b/Backend/ERPCore/Services/CountService.cs index 50073de..a3d662c 100644 --- a/Backend/ERPCore/Services/CountService.cs +++ b/Backend/ERPCore/Services/CountService.cs @@ -37,6 +37,9 @@ public sealed class CountService : ICountService private readonly IBranchConfigService _branchConfig; private readonly IUnitOfWork _uow; private readonly IGeneralLedgerService _gl; + private readonly IRepository _stockLayers; + private readonly IRepository _batches; + private readonly IRepository _serials; private readonly string _glInventoryAccountCode; private readonly string _glGainAccountCode; private readonly string _glLossAccountCode; @@ -45,7 +48,8 @@ public sealed class CountService : ICountService IRepository counts, IRepository adjustments, IRepository warehouses, IRepository items, IRepository reasonCodes, IFifoCostingService fifo, IStockMutator mutator, INumberSequenceService numbers, ICurrentUser currentUser, IBranchConfigService branchConfig, IUnitOfWork uow, - IGeneralLedgerService gl, IConfiguration configuration) + IGeneralLedgerService gl, IRepository stockLayers, IRepository batches, + IRepository serials, IConfiguration configuration) { _counts = counts; _adjustments = adjustments; @@ -59,6 +63,9 @@ public sealed class CountService : ICountService _branchConfig = branchConfig; _uow = uow; _gl = gl; + _stockLayers = stockLayers; + _batches = batches; + _serials = serials; _glInventoryAccountCode = configuration["Adjustment:GlInventoryAccountCode"] ?? string.Empty; _glGainAccountCode = configuration["Adjustment:GlGainAccountCode"] ?? string.Empty; _glLossAccountCode = configuration["Adjustment:GlLossAccountCode"] ?? string.Empty; @@ -126,7 +133,9 @@ public sealed class CountService : ICountService public async Task GetAsync(int countId, CancellationToken ct = default) { - var count = await _counts.Query().AsNoTracking().Include(c => c.Lines) + var count = await _counts.Query().AsNoTracking() + .Include(c => c.Lines).ThenInclude(l => l.Batch) + .Include(c => c.Lines).ThenInclude(l => l.Serial) .FirstOrDefaultAsync(c => c.CountId == countId, ct); return count is null ? null : Map(count); } @@ -143,12 +152,44 @@ public sealed class CountService : ICountService if (!await _items.Query().AnyAsync(i => i.ItemId == id, ct)) throw new DomainException(ErrorCodes.Validation, $"Item {id} does not exist.", 422); - // Snapshot system quantities now (immutable once opened). + // Snapshot system quantities now (immutable once opened). Batch/serial-tracked items + // get one line per lot instead of one aggregate line, so counting can be done lot by lot. var lines = new List(); foreach (var id in itemIds) { - var systemQty = await _fifo.GetOnHandAsync(id, request.WarehouseId, ct); - lines.Add(new StockCountLine { ItemId = id, SystemQty = systemQty }); + var item = await _items.Query().AsNoTracking().FirstAsync(i => i.ItemId == id, ct); + if (item.TrackingMode == TrackingMode.Batch) + { + var batches = await _batches.Query().AsNoTracking().Where(b => b.ItemId == id).ToListAsync(ct); + if (batches.Count == 0) + { + lines.Add(new StockCountLine { ItemId = id, BatchId = null, SystemQty = 0 }); + continue; + } + foreach (var batch in batches) + { + var systemQty = await _stockLayers.Query().AsNoTracking() + .Where(l => l.ItemId == id && l.WarehouseId == request.WarehouseId && l.BatchId == batch.BatchId) + .SumAsync(l => (decimal?)l.QtyRemaining, ct) ?? 0m; + lines.Add(new StockCountLine { ItemId = id, BatchId = batch.BatchId, SystemQty = systemQty }); + } + } + else if (item.TrackingMode == TrackingMode.Serial) + { + var serials = await _serials.Query().AsNoTracking() + .Where(s => s.ItemId == id && s.Status == "InStock").ToListAsync(ct); + foreach (var serial in serials) + { + var open = await _stockLayers.Query().AsNoTracking().AnyAsync( + l => l.ItemId == id && l.WarehouseId == request.WarehouseId && l.SerialId == serial.SerialId && l.QtyRemaining > 0, ct); + lines.Add(new StockCountLine { ItemId = id, SerialId = serial.SerialId, SystemQty = open ? 1 : 0 }); + } + } + else + { + var systemQty = await _fifo.GetOnHandAsync(id, request.WarehouseId, ct); + lines.Add(new StockCountLine { ItemId = id, SystemQty = systemQty }); + } } var count = await _uow.ExecuteInTransactionAsync(async token => @@ -174,7 +215,9 @@ public sealed class CountService : ICountService public async Task EnterCountsAsync(int countId, EnterCountsRequest request, CancellationToken ct = default) { - var count = await _counts.Query().Include(c => c.Lines) + var count = await _counts.Query() + .Include(c => c.Lines).ThenInclude(l => l.Batch) + .Include(c => c.Lines).ThenInclude(l => l.Serial) .FirstOrDefaultAsync(c => c.CountId == countId, ct) ?? throw new NotFoundException($"Count {countId} was not found."); if (count.Status == CountStatus.Posted) @@ -195,7 +238,9 @@ public sealed class CountService : ICountService public async Task PostAsync(int countId, CancellationToken ct = default) { - var count = await _counts.Query().Include(c => c.Lines) + var count = await _counts.Query() + .Include(c => c.Lines).ThenInclude(l => l.Batch) + .Include(c => c.Lines).ThenInclude(l => l.Serial) .FirstOrDefaultAsync(c => c.CountId == countId, ct) ?? throw new NotFoundException($"Count {countId} was not found."); if (count.Status == CountStatus.Posted) @@ -259,5 +304,7 @@ public sealed class CountService : ICountService private static CountDto Map(StockCount c) => new( c.CountId, c.DocNo, c.WarehouseId, c.BranchId, c.CountType, c.Status, c.CreatedBy, c.CreatedAt, c.Lines.OrderBy(l => l.CountLineId) - .Select(l => new CountLineDto(l.CountLineId, l.ItemId, l.BinId, l.SystemQty, l.CountedQty, l.Variance)).ToList()); + .Select(l => new CountLineDto( + l.CountLineId, l.ItemId, l.BinId, l.SystemQty, l.CountedQty, l.Variance, + l.BatchId, l.Batch?.BatchNo, l.SerialId, l.Serial?.SerialNo)).ToList()); } diff --git a/Backend/ERPCore/Services/CustomerService.cs b/Backend/ERPCore/Services/CustomerService.cs index 0f7c64e..a98737f 100644 --- a/Backend/ERPCore/Services/CustomerService.cs +++ b/Backend/ERPCore/Services/CustomerService.cs @@ -15,12 +15,14 @@ public sealed class CustomerService : ICustomerService { private readonly IRepository _customers; private readonly IRepository _warehouses; + private readonly IBranchConfigService _branchConfig; private readonly IUnitOfWork _uow; - public CustomerService(IRepository customers, IRepository warehouses, IUnitOfWork uow) + public CustomerService(IRepository customers, IRepository warehouses, IBranchConfigService branchConfig, IUnitOfWork uow) { _customers = customers; _warehouses = warehouses; + _branchConfig = branchConfig; _uow = uow; } @@ -43,7 +45,7 @@ public sealed class CustomerService : ICustomerService .Select(c => new CustomerDto( c.CustomerId, c.CustomerCode, c.CustomerType, c.Name, c.DisplayName, c.Phone, c.Email, c.AddressLine1, c.AddressLine2, c.City, c.Country, c.TaxRegistrationNo, - c.CreditLimit, c.CreditDays, c.DefaultWarehouseId, c.Status, c.CreatedAt, c.UpdatedAt)) + c.CreditLimit, c.CreditDays, c.DefaultWarehouseId, c.Status, c.BranchId, c.CreatedAt, c.UpdatedAt)) .ToListAsync(ct); return PagedResponse.Create(rows, query.Page, query.PageSize, total); @@ -77,6 +79,7 @@ public sealed class CustomerService : ICustomerService if (!exists) throw new NotFoundException($"Warehouse {request.DefaultWarehouseId} was not found."); } + var branchId = await _branchConfig.ResolveBranchIdAsync(request.BranchId, ct); var customer = new Customer { CustomerCode = code, @@ -94,6 +97,7 @@ public sealed class CustomerService : ICustomerService CreditDays = request.CreditDays, DefaultWarehouseId = request.DefaultWarehouseId, Status = EntityStatus.Active, + BranchId = branchId, CreatedAt = DateTime.UtcNow }; @@ -143,6 +147,7 @@ public sealed class CustomerService : ICustomerService customer.CreditLimit = request.CreditLimit; customer.CreditDays = request.CreditDays; customer.DefaultWarehouseId = request.DefaultWarehouseId; + customer.BranchId = await _branchConfig.ResolveBranchIdAsync(request.BranchId, ct); customer.UpdatedAt = DateTime.UtcNow; await _uow.SaveChangesAsync(ct); @@ -162,7 +167,7 @@ public sealed class CustomerService : ICustomerService private static CustomerDto Map(Customer c) => new( c.CustomerId, c.CustomerCode, c.CustomerType, c.Name, c.DisplayName, c.Phone, c.Email, c.AddressLine1, c.AddressLine2, c.City, c.Country, c.TaxRegistrationNo, - c.CreditLimit, c.CreditDays, c.DefaultWarehouseId, c.Status, c.CreatedAt, c.UpdatedAt); + c.CreditLimit, c.CreditDays, c.DefaultWarehouseId, c.Status, c.BranchId, c.CreatedAt, c.UpdatedAt); private static string? Normalize(string? value) => string.IsNullOrWhiteSpace(value) ? null : value.Trim(); } diff --git a/Backend/ERPCore/Services/DashboardService.cs b/Backend/ERPCore/Services/DashboardService.cs index 4be8377..3ae9c92 100644 --- a/Backend/ERPCore/Services/DashboardService.cs +++ b/Backend/ERPCore/Services/DashboardService.cs @@ -24,11 +24,19 @@ public sealed class DashboardService : IDashboardService private readonly IRepository _requisitions; private readonly IRepository _counts; private readonly IRepository _rfqs; + private readonly IRepository _leaveRequests; + private readonly IRepository _salesInvoices; private readonly IReorderService _reorder; + // Neither SalesInvoice nor PurchaseInvoice carries a DueDate field (Phase 1 schema + // has none), so "overdue" is approximated as a Posted invoice with an outstanding + // balance older than this many days from its invoice date. + private const int OverdueAgeDays = 30; + public DashboardService( IRepository layers, IRepository grns, IRepository pos, IRepository requisitions, IRepository counts, IRepository rfqs, + IRepository leaveRequests, IRepository salesInvoices, IReorderService reorder) { _layers = layers; @@ -37,6 +45,8 @@ public sealed class DashboardService : IDashboardService _requisitions = requisitions; _counts = counts; _rfqs = rfqs; + _leaveRequests = leaveRequests; + _salesInvoices = salesInvoices; _reorder = reorder; } @@ -78,12 +88,24 @@ public sealed class DashboardService : IDashboardService .CountAsync(r => r.Status == RequisitionStatus.Submitted, ct); var openRfqs = await _rfqs.Query().AsNoTracking().CountAsync(r => r.Status == RfqStatus.Open, ct); + // LeaveRequest carries no BranchId (like PO/Requisition/RFQ) — global regardless + // of the selected branch. + var pendingLeaveRequests = await _leaveRequests.Query().AsNoTracking() + .CountAsync(l => l.Status == LeaveRequestStatus.Submitted, ct); + + var overdueSince = DateTime.UtcNow.AddDays(-OverdueAgeDays); + var salesInvoices = _salesInvoices.Query().AsNoTracking(); + if (branchId is not null) salesInvoices = salesInvoices.Where(i => i.BranchId == branchId); + var overdueSalesInvoices = await salesInvoices.CountAsync( + i => i.Status == SalesInvoiceStatus.Posted && i.BalanceAmount > 0 && i.InvoiceDate < overdueSince, ct); + // PageSize:1 is enough — GetAlertsAsync computes the full alert count before paging. var lowStockAlerts = (await _reorder.GetAlertsAsync(null, branchId, new PageQuery { Page = 1, PageSize = 1 }, ct)) .Pagination.TotalItems; return new DashboardStatsDto( lowStockAlerts, onHandTotal, onHandWarehouses, stockValuationTotal, stockValuationByWarehouse, - pendingApprovalPOs, pendingGrns, openRequisitions, pendingCounts, openRfqs); + pendingApprovalPOs, pendingGrns, openRequisitions, pendingCounts, openRfqs, + pendingLeaveRequests, overdueSalesInvoices); } } diff --git a/Backend/ERPCore/Services/GlobalSearchService.cs b/Backend/ERPCore/Services/GlobalSearchService.cs new file mode 100644 index 0000000..40ba042 --- /dev/null +++ b/Backend/ERPCore/Services/GlobalSearchService.cs @@ -0,0 +1,77 @@ +using ERPCore.Domain.Entities; +using ERPCore.Dtos.Search; +using ERPCore.Repositories.Interfaces; +using ERPCore.Services.Interfaces; +using Microsoft.EntityFrameworkCore; + +namespace ERPCore.Services; + +/// +/// Backs the global command palette (⌘K). Fans a single free-text term out across +/// Items, Purchase Orders, Sales Slips (invoices) and Employees in parallel and +/// returns a combined, capped result set — no persistence, read-only. +/// +public sealed class GlobalSearchService : IGlobalSearchService +{ + private readonly IRepository _items; + private readonly IRepository _purchaseOrders; + private readonly IRepository _salesSlips; + private readonly IRepository _employees; + + public GlobalSearchService( + IRepository items, + IRepository purchaseOrders, + IRepository salesSlips, + IRepository employees) + { + _items = items; + _purchaseOrders = purchaseOrders; + _salesSlips = salesSlips; + _employees = employees; + } + + public async Task> SearchAsync(string term, int takePerType = 6, CancellationToken ct = default) + { + var q = term?.Trim() ?? string.Empty; + if (q.Length < 2) return Array.Empty(); + + var pattern = $"%{q}%"; + + // Sequential, not parallel: these share one scoped DbContext, which EF Core + // does not allow concurrent operations against. + var items = await _items.Query().AsNoTracking() + .Where(i => EF.Functions.ILike(i.Sku, pattern) || EF.Functions.ILike(i.Name, pattern)) + .OrderBy(i => i.Name) + .Take(takePerType) + .Select(i => new GlobalSearchResultDto(GlobalSearchResultType.Item, i.ItemId, i.Sku, i.Name, i.Sku)) + .ToListAsync(ct); + + var pos = await _purchaseOrders.Query().AsNoTracking() + .Where(p => EF.Functions.ILike(p.DocNo, pattern)) + .OrderByDescending(p => p.PoId) + .Take(takePerType) + .Select(p => new GlobalSearchResultDto(GlobalSearchResultType.PurchaseOrder, p.PoId, p.DocNo, p.DocNo, p.Status.ToString())) + .ToListAsync(ct); + + var invoices = await _salesSlips.Query().AsNoTracking() + .Where(s => EF.Functions.ILike(s.SlipNo, pattern) || EF.Functions.ILike(s.CustomerSnapshotName, pattern)) + .OrderByDescending(s => s.SalesSlipId) + .Take(takePerType) + .Select(s => new GlobalSearchResultDto(GlobalSearchResultType.Invoice, s.SalesSlipId, s.SlipNo, s.SlipNo, s.CustomerSnapshotName)) + .ToListAsync(ct); + + var employees = await _employees.Query().AsNoTracking() + .Where(e => EF.Functions.ILike(e.FullName, pattern) || EF.Functions.ILike(e.EmployeeCode, pattern)) + .OrderBy(e => e.FullName) + .Take(takePerType) + .Select(e => new GlobalSearchResultDto(GlobalSearchResultType.Employee, e.EmployeeId, e.EmployeeCode, e.FullName, e.EmployeeCode)) + .ToListAsync(ct); + + var results = new List(); + results.AddRange(items); + results.AddRange(pos); + results.AddRange(invoices); + results.AddRange(employees); + return results; + } +} diff --git a/Backend/ERPCore/Services/GrnService.cs b/Backend/ERPCore/Services/GrnService.cs index c5a12a7..36345cd 100644 --- a/Backend/ERPCore/Services/GrnService.cs +++ b/Backend/ERPCore/Services/GrnService.cs @@ -35,12 +35,14 @@ public sealed class GrnService : IGrnService private readonly IRepository _batches; private readonly IRepository _layers; private readonly IRepository _ledger; + private readonly IRepository _taxRates; private readonly IFifoCostingService _fifo; private readonly INumberSequenceService _numbers; private readonly ICurrentUser _currentUser; private readonly IBranchConfigService _branchConfig; private readonly IUnitOfWork _uow; private readonly IGeneralLedgerService _gl; + private readonly INotificationService _notifications; private readonly string _glInventoryAccountCode; private readonly string _glVatRecoverableAccountCode; private readonly string _glClearingAccountCode; @@ -49,9 +51,9 @@ public sealed class GrnService : IGrnService IRepository grns, IRepository pos, IRepository poLines, IRepository items, IRepository warehouses, IRepository bins, IRepository vendors, IRepository batches, - IRepository layers, IRepository ledger, + IRepository layers, IRepository ledger, IRepository taxRates, IFifoCostingService fifo, INumberSequenceService numbers, ICurrentUser currentUser, IBranchConfigService branchConfig, - IUnitOfWork uow, IGeneralLedgerService gl, IConfiguration configuration) + IUnitOfWork uow, IGeneralLedgerService gl, INotificationService notifications, IConfiguration configuration) { _grns = grns; _pos = pos; @@ -63,12 +65,14 @@ public sealed class GrnService : IGrnService _batches = batches; _layers = layers; _ledger = ledger; + _taxRates = taxRates; _fifo = fifo; _numbers = numbers; _currentUser = currentUser; _branchConfig = branchConfig; _uow = uow; _gl = gl; + _notifications = notifications; _glInventoryAccountCode = configuration["Grn:GlInventoryAccountCode"] ?? string.Empty; _glVatRecoverableAccountCode = configuration["Grn:GlVatRecoverableAccountCode"] ?? string.Empty; _glClearingAccountCode = configuration["Grn:GlClearingAccountCode"] ?? string.Empty; @@ -180,7 +184,13 @@ public sealed class GrnService : IGrnService // Derived figures are always computed server-side, never accepted from the client. var netUnitCost = Math.Round(unitCost * (1 - input.DiscountPct / 100m), 6, MidpointRounding.AwayFromZero); var receivedValue = Math.Round(input.Qty * netUnitCost, 4, MidpointRounding.AwayFromZero); - var vatAmount = Math.Round(receivedValue * input.VatPct / 100m, 4, MidpointRounding.AwayFromZero); + // input.VatPct supplied is an explicit override; omitted (null) resolves from the + // item's assigned TaxRate — see ISalesDomainService.ResolveLineTaxPctAsync's sales-side + // equivalent of this same "Item.TaxRate drives the default, don't hand-type it" rule. + var vatPct = input.VatPct ?? (item.TaxRateId is int taxRateId + ? await _taxRates.Query().AsNoTracking().Where(t => t.TaxRateId == taxRateId).Select(t => t.Percentage).FirstAsync(ct) + : 0m); + var vatAmount = Math.Round(receivedValue * vatPct / 100m, 4, MidpointRounding.AwayFromZero); var batch = await ResolveBatchAsync(item, input.Batch, batchCache, ct); var warrantyNumbers = ResolveWarrantyNumbers(item, input.WarrantyNumbers, input.Qty); @@ -196,7 +206,7 @@ public sealed class GrnService : IGrnService PoUnitPrice = poUnitPrice, DiscountPct = input.DiscountPct, NetUnitCost = netUnitCost, - VatPct = input.VatPct, + VatPct = vatPct, VatAmount = vatAmount, ReceivedValue = receivedValue, LineTotal = receivedValue + vatAmount, @@ -224,6 +234,8 @@ public sealed class GrnService : IGrnService return entity; }, ct); + await _notifications.RaiseAsync("grn.created", "GRN Created", $"GRN {grn.DocNo} was created.", nameof(Grn), grn.GrnId, ct); + return Map(grn); } @@ -316,6 +328,8 @@ public sealed class GrnService : IGrnService return 0; }, ct); + await _notifications.RaiseAsync("grn.confirmed", "GRN Confirmed", $"GRN {grn.DocNo} was confirmed.", nameof(Grn), grn.GrnId, ct); + return new GrnConfirmResultDto( grn.GrnId, grn.Status, now, grn.GlJournalNo ?? string.Empty, createdLayers.Select(ToCreatedLayer).ToList(), @@ -345,26 +359,14 @@ public sealed class GrnService : IGrnService return new ReleaseLineResultDto(grnLineId, HoldStatus.Available); } - // Reject: remove the held stock from on-hand and post a reversing ledger entry. - // Linking rejected stock to a formal purchase return is deferred (§3.4). - var actor = _currentUser.AuditUserId; - var now = DateTime.UtcNow; - await _uow.ExecuteInTransactionAsync(async token => - { - line.HoldStatus = HoldStatus.Rejected; - var layers = await _layers.Query() - .Where(l => l.GrnLineId == grnLineId && l.QtyRemaining > 0).ToListAsync(token); - - foreach (var layer in layers) - { - var bal = await _fifo.GetOnHandAsync(layer.ItemId, layer.WarehouseId, token) - layer.QtyRemaining; - await _fifo.PostLedgerAsync( - layer.ItemId, layer.WarehouseId, line.BinId, layer.BatchId, null, actor, - Direction.Out, layer.QtyRemaining, layer.UnitCost, bal, DocumentTypes.Grn, grn.GrnId, now, token); - layer.QtyRemaining = 0; - } - return 0; - }, ct); + // Reject: the held stock stays exactly where it is — still on the layer, still + // excluded from issuable on-hand (FifoCostingService.ConsumeAsync excludes both + // OnHold and Rejected lines) — until a Purchase Return actually ships it back to + // the vendor. That return (not this action) posts the real outbound ledger entry, + // scoped to this line's own layer(s), so the movement is attributable to a real + // document instead of vanishing against the GRN itself (§3.4). + line.HoldStatus = HoldStatus.Rejected; + await _uow.SaveChangesAsync(ct); return new ReleaseLineResultDto(grnLineId, HoldStatus.Rejected); } diff --git a/Backend/ERPCore/Services/Hrm/EmployeeService.cs b/Backend/ERPCore/Services/Hrm/EmployeeService.cs index eb8e478..76f89ec 100644 --- a/Backend/ERPCore/Services/Hrm/EmployeeService.cs +++ b/Backend/ERPCore/Services/Hrm/EmployeeService.cs @@ -3,12 +3,14 @@ using ERPCore.Domain.Entities; using ERPCore.Domain.Enums; using ERPCore.Dtos.Common; using ERPCore.Dtos.Hrm; +using ERPCore.Infra.Auth.AuthHex; using ERPCore.Infra.Storage; using ERPCore.Infra.UoW; using ERPCore.Repositories.Interfaces; using ERPCore.Services.Interfaces; using ERPCore.System.Errors; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; namespace ERPCore.Services.Hrm; @@ -30,13 +32,16 @@ public sealed class EmployeeService : IEmployeeService private readonly IFileStorageService _fileStorage; private readonly IBranchConfigService _branchConfig; private readonly IBranchAccessService _branchAccess; + private readonly IAuthHexClient _authHex; + private readonly ILogger _logger; private readonly IUnitOfWork _uow; public EmployeeService( IRepository employees, IRepository users, IRepository bankDetails, IRepository documents, IRepository salaryStructures, IRepository loans, IRepository leaveBalances, IRepository payrollLines, - IFileStorageService fileStorage, IBranchConfigService branchConfig, IBranchAccessService branchAccess, IUnitOfWork uow) + IFileStorageService fileStorage, IBranchConfigService branchConfig, IBranchAccessService branchAccess, + IAuthHexClient authHex, ILogger logger, IUnitOfWork uow) { _employees = employees; _users = users; @@ -49,6 +54,8 @@ public sealed class EmployeeService : IEmployeeService _fileStorage = fileStorage; _branchConfig = branchConfig; _branchAccess = branchAccess; + _authHex = authHex; + _logger = logger; _uow = uow; } @@ -212,7 +219,7 @@ public sealed class EmployeeService : IEmployeeService await _uow.SaveChangesAsync(ct); } - public async Task DeleteAsync(int employeeId, CancellationToken ct = default) + public async Task DeleteAsync(int employeeId, bool deleteUserAccount, CancellationToken ct = default) { var employee = await _employees.GetByIdAsync(employeeId, ct) ?? throw new NotFoundException($"Employee {employeeId} was not found."); @@ -220,13 +227,19 @@ public sealed class EmployeeService : IEmployeeService if (await _payrollLines.Query().AnyAsync(l => l.EmployeeId == employeeId, ct)) throw new DomainException(ErrorCodes.EmployeeHasPayrollHistory, "This employee has payroll history and cannot be deleted.", 409); - // A linked system-user account survives the employee row (Employee.UserId → User is - // Restrict, so cascading it away isn't even an option) — deactivate it (same as the - // Active/Deactivate toggle on Settings > Users) rather than leaving a login standing - // with no staff record behind it. The User row itself is never removed. - if (employee.UserId is not null) + var linkedUserId = employee.UserId; + + // A linked system-user account is Employee.UserId → User (Restrict), so it never + // cascades away with the employee row automatically. Default behaviour: deactivate it + // (same as the Active/Deactivate toggle on Settings > Users) rather than leaving a + // login standing with no staff record behind it. The caller may instead ask for the + // account to be permanently removed (deleteUserAccount) — attempted separately, below, + // after the employee row itself is safely gone, so a hard-delete failure (the user has + // real linked business/audit records — see AuditLog/GRN/etc. Restrict FKs) never blocks + // the employee deletion that was actually confirmed. + if (linkedUserId is not null && !deleteUserAccount) { - var linkedUser = await _users.GetByIdAsync(employee.UserId.Value, ct); + var linkedUser = await _users.GetByIdAsync(linkedUserId.Value, ct); if (linkedUser is not null) linkedUser.Status = EntityStatus.Inactive; } @@ -252,6 +265,47 @@ public sealed class EmployeeService : IEmployeeService _employees.Remove(employee); await _uow.SaveChangesAsync(ct); + + if (linkedUserId is null || !deleteUserAccount) + return new EmployeeDeleteResultDto(UserAccountDeleted: false, UserAccountDeactivated: linkedUserId is not null); + + // Attempted as its own save, after the employee is already committed, so a Restrict-FK + // failure here (the user posted real transactions — GRNs, purchase orders, audit log + // entries, ...) can't roll back the employee deletion the caller already confirmed. + var user = await _users.GetByIdAsync(linkedUserId.Value, ct); + if (user is null) return new EmployeeDeleteResultDto(UserAccountDeleted: false, UserAccountDeactivated: false); + + string? userEmail = user.Email; + string? username = user.Username; + + try + { + _users.Remove(user); + await _uow.SaveChangesAsync(ct); + } + catch (DbUpdateException) + { + user.Status = EntityStatus.Inactive; + await _uow.SaveChangesAsync(ct); + return new EmployeeDeleteResultDto(UserAccountDeleted: false, UserAccountDeactivated: true, AuthHexIdentityPurged: false); + } + + // The local User row is gone, but AuthHex's own duplicate check (CanRegisterUser) has no + // notion of "deleted" — its stale identity would otherwise permanently block this email/ + // username from ever being registered again. Best-effort: AuthHex may not be reachable, or + // the admin deleteUser function may not be deployed/configured yet (AdminApiKey unset on + // either side) — either way, the local deletion the caller confirmed must not roll back + // over this, so failures here are only logged, never rethrown. + try + { + var result = await _authHex.DeleteUserAsync(userEmail, null, null, username, ct); + return new EmployeeDeleteResultDto(UserAccountDeleted: true, UserAccountDeactivated: false, AuthHexIdentityPurged: result.DeletedCount > 0); + } + catch (Exception ex) + { + _logger.LogWarning(ex, "Deleted local User for employee {EmployeeId}, but purging the AuthHex identity (email={Email}, username={Username}) failed — that email/username may still be blocked from re-registration.", employeeId, userEmail, username); + return new EmployeeDeleteResultDto(UserAccountDeleted: true, UserAccountDeactivated: false, AuthHexIdentityPurged: false); + } } public async Task> ListBankDetailsAsync(int employeeId, CancellationToken ct = default) diff --git a/Backend/ERPCore/Services/Hrm/EmployeeUserLinkService.cs b/Backend/ERPCore/Services/Hrm/EmployeeUserLinkService.cs index 88e7299..4cf3cb9 100644 --- a/Backend/ERPCore/Services/Hrm/EmployeeUserLinkService.cs +++ b/Backend/ERPCore/Services/Hrm/EmployeeUserLinkService.cs @@ -1,10 +1,12 @@ using ERPCore.Domain.Entities; using ERPCore.Dtos.Hrm; +using ERPCore.Infra.Auth.AuthHex; using ERPCore.Infra.UoW; using ERPCore.Repositories.Interfaces; using ERPCore.Services.Interfaces; using ERPCore.System.Errors; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; namespace ERPCore.Services.Hrm; @@ -13,12 +15,18 @@ public sealed class EmployeeUserLinkService : IEmployeeUserLinkService { private readonly IRepository _employees; private readonly IRepository _users; + private readonly IAuthHexClient _authHex; + private readonly ILogger _logger; private readonly IUnitOfWork _uow; - public EmployeeUserLinkService(IRepository employees, IRepository users, IUnitOfWork uow) + public EmployeeUserLinkService( + IRepository employees, IRepository users, + IAuthHexClient authHex, ILogger logger, IUnitOfWork uow) { _employees = employees; _users = users; + _authHex = authHex; + _logger = logger; _uow = uow; } @@ -66,8 +74,41 @@ public sealed class EmployeeUserLinkService : IEmployeeUserLinkService var employee = await _employees.GetByIdAsync(employeeId, ct) ?? throw new NotFoundException($"Employee {employeeId} was not found."); + var linkedUserId = employee.UserId; employee.UserId = null; employee.UpdatedAt = DateTime.UtcNow; + + string? userEmail = null; + string? username = null; + var userRemoved = false; + + if (linkedUserId is not null) + { + var linkedUser = await _users.GetByIdAsync(linkedUserId.Value, ct); + if (linkedUser is not null) + { + userEmail = linkedUser.Email; + username = linkedUser.Username; + _users.Remove(linkedUser); + userRemoved = true; + } + } + await _uow.SaveChangesAsync(ct); + + // Best-effort, same as EmployeeService.DeleteAsync's hard-delete path — AuthHex's own + // duplicate check has no notion of "deleted", so without this the email/username stays + // permanently blocked from re-registration even though the local User row is gone. + if (userRemoved) + { + try + { + await _authHex.DeleteUserAsync(userEmail, null, null, username, ct); + } + catch (Exception ex) + { + _logger.LogWarning(ex, "Unlinked and deleted local User for employee {EmployeeId}, but purging the AuthHex identity (email={Email}, username={Username}) failed.", employeeId, userEmail, username); + } + } } } diff --git a/Backend/ERPCore/Services/Interfaces/IBranchConfigService.cs b/Backend/ERPCore/Services/Interfaces/IBranchConfigService.cs index 1123ee3..8d8b29d 100644 --- a/Backend/ERPCore/Services/Interfaces/IBranchConfigService.cs +++ b/Backend/ERPCore/Services/Interfaces/IBranchConfigService.cs @@ -20,4 +20,17 @@ public interface IBranchConfigService /// default branch when branching is disabled — creating that default branch on first use. /// Task ResolveBranchIdAsync(int requestedBranchId, CancellationToken ct = default); + + /// True when Warehouses specifically should ask for/show a branch. Independent + /// of , but never true when that is false. + Task IsWarehouseBranchingEnabledAsync(CancellationToken ct = default); + + /// Same as but gated on + /// instead of the global flag. + Task ResolveWarehouseBranchIdAsync(int requestedBranchId, CancellationToken ct = default); + + /// The deployment's single default branch ("BR-000"/"Main Branch"), created on + /// first use if it doesn't exist yet. Used as a fallback branch for document types that + /// don't yet carry an explicit branch (docs/BRANCH_ISOLATION_PLAN.md). + Task ResolveDefaultBranchIdAsync(CancellationToken ct = default); } diff --git a/Backend/ERPCore/Services/Interfaces/IEmployeeService.cs b/Backend/ERPCore/Services/Interfaces/IEmployeeService.cs index a2732d2..ce9ab91 100644 --- a/Backend/ERPCore/Services/Interfaces/IEmployeeService.cs +++ b/Backend/ERPCore/Services/Interfaces/IEmployeeService.cs @@ -21,7 +21,12 @@ public interface IEmployeeService /// 409 if the employee has any payroll history, since that's financial/audit record that /// must never be destroyed. /// - Task DeleteAsync(int employeeId, CancellationToken ct = default); + /// + /// Permanently deletes the employee. When is true and the + /// employee has a linked login, the User row is also hard-deleted if possible — it falls back to + /// deactivating the account when the user has real linked business/audit records instead. + /// + Task DeleteAsync(int employeeId, bool deleteUserAccount = false, CancellationToken ct = default); Task> ListBankDetailsAsync(int employeeId, CancellationToken ct = default); Task> ReplaceBankDetailsAsync(int employeeId, ReplaceEmployeeBankDetailsRequest request, CancellationToken ct = default); diff --git a/Backend/ERPCore/Services/Interfaces/IGlobalSearchService.cs b/Backend/ERPCore/Services/Interfaces/IGlobalSearchService.cs new file mode 100644 index 0000000..1f1cf0d --- /dev/null +++ b/Backend/ERPCore/Services/Interfaces/IGlobalSearchService.cs @@ -0,0 +1,8 @@ +using ERPCore.Dtos.Search; + +namespace ERPCore.Services.Interfaces; + +public interface IGlobalSearchService +{ + Task> SearchAsync(string term, int takePerType = 6, CancellationToken ct = default); +} diff --git a/Backend/ERPCore/Services/Interfaces/IItemService.cs b/Backend/ERPCore/Services/Interfaces/IItemService.cs index cb28706..c438075 100644 --- a/Backend/ERPCore/Services/Interfaces/IItemService.cs +++ b/Backend/ERPCore/Services/Interfaces/IItemService.cs @@ -24,4 +24,8 @@ public interface IItemService Task SetStatusAsync(int itemId, EntityStatus status, CancellationToken ct = default); Task UpdateReorderAsync(int itemId, UpdateReorderRequest request, CancellationToken ct = default); + + /// Barcode/RFID scan lookup — item barcode/SKU, or a batch/serial barcode/no + /// (optionally scoped to first). Null when nothing matches. + Task ScanAsync(string code, int? itemId, CancellationToken ct = default); } diff --git a/Backend/ERPCore/Services/Interfaces/INavPermissionService.cs b/Backend/ERPCore/Services/Interfaces/INavPermissionService.cs new file mode 100644 index 0000000..e5f9b70 --- /dev/null +++ b/Backend/ERPCore/Services/Interfaces/INavPermissionService.cs @@ -0,0 +1,30 @@ +using ERPCore.Domain.Enums; + +namespace ERPCore.Services.Interfaces; + +/// +/// Resolves whether a role can reach a given nav module — the same +/// RolePermission data /auth/me already reduces to navCodes +/// (), reused here to gate the API itself instead +/// of only the sidebar (docs/02-SECURITY.md AR-01). +/// +public interface INavPermissionService +{ + /// + /// True when is granted itself, + /// or any sub-nav item nested under it (code prefixed "{navCode}."). Does not + /// special-case Admin — callers (e.g. ) + /// decide whether Admin bypasses this entirely. + /// + Task HasAccessAsync(string? roleCode, string navCode, CancellationToken ct = default); + + /// + /// True when 's grant on (exact + /// code match — no sub-nav prefix expansion, unlike , since + /// an action applies to one specific module's permission row) includes + /// in its RolePermission.Actions bitmask. False if the + /// role has no permission row for that exact nav code at all. Does not special-case + /// Admin — see . + /// + Task HasActionAsync(string? roleCode, string navCode, RolePermissionAction action, CancellationToken ct = default); +} diff --git a/Backend/ERPCore/Services/Interfaces/INotificationService.cs b/Backend/ERPCore/Services/Interfaces/INotificationService.cs new file mode 100644 index 0000000..1b84875 --- /dev/null +++ b/Backend/ERPCore/Services/Interfaces/INotificationService.cs @@ -0,0 +1,23 @@ +using ERPCore.Dtos.Notifications; + +namespace ERPCore.Services.Interfaces; + +public interface INotificationService +{ + /// + /// Raises a module event as a broadcast notification to all active users, + /// but only when the module's InApp channel is enabled in NotificationConfig. + /// No-op (and no row written) when the channel is disabled. + /// + Task RaiseAsync( + string moduleKey, + string title, + string message, + string? relatedEntityType = null, + int? relatedEntityId = null, + CancellationToken ct = default); + + Task GetFeedAsync(int userId, int take = 20, CancellationToken ct = default); + + Task MarkAllReadAsync(int userId, CancellationToken ct = default); +} diff --git a/Backend/ERPCore/Services/Interfaces/INumberSequenceService.cs b/Backend/ERPCore/Services/Interfaces/INumberSequenceService.cs index 5be5af5..a8a37f9 100644 --- a/Backend/ERPCore/Services/Interfaces/INumberSequenceService.cs +++ b/Backend/ERPCore/Services/Interfaces/INumberSequenceService.cs @@ -1,15 +1,23 @@ namespace ERPCore.Services.Interfaces; /// -/// Issues gap-controlled, per-year document numbers (FR-X-03). Call inside the -/// document's UoW transaction so the reserved number rolls back with the document -/// on failure. +/// Issues gap-controlled, per-branch, per-year document numbers (FR-X-03, +/// docs/BRANCH_ISOLATION_PLAN.md §5). Call inside the document's UoW transaction so the +/// reserved number rolls back with the document on failure. /// public interface INumberSequenceService { /// - /// Reserve and return the next number for in the - /// current year, formatted e.g. PO-2026-00042. + /// Reserve and return the next number for in + /// for the current year, formatted e.g. + /// PO-BR-001-2026-00042. + /// + Task NextAsync(string docType, int branchId, CancellationToken ct = default); + + /// + /// Convenience overload for document types that don't yet carry an explicit branch + /// (e.g. HRM/production/day-end documents, still out of scope for branch isolation — + /// docs/BRANCH_ISOLATION_PLAN.md). Resolves to the deployment's default branch. /// Task NextAsync(string docType, CancellationToken ct = default); } diff --git a/Backend/ERPCore/Services/Interfaces/IPurchaseOrderService.cs b/Backend/ERPCore/Services/Interfaces/IPurchaseOrderService.cs index a93bca2..32f1c7d 100644 --- a/Backend/ERPCore/Services/Interfaces/IPurchaseOrderService.cs +++ b/Backend/ERPCore/Services/Interfaces/IPurchaseOrderService.cs @@ -14,10 +14,23 @@ public interface IPurchaseOrderService Task?> GetAsync(int poId, CancellationToken ct = default); Task> CreateAsync(CreatePurchaseOrderRequest request, CancellationToken ct = default); Task> UpdateAsync(int poId, UpdatePurchaseOrderRequest request, uint expectedRowVersion, CancellationToken ct = default); + + /// + /// PendingApproval → Approved. 409 PO_NOT_PENDING_APPROVAL if the PO isn't awaiting + /// approval; 403 PO_APPROVAL_FORBIDDEN if the caller isn't an Admin or is the PO's + /// own creator (self-approval is blocked). + /// Task ApproveAsync(int poId, CancellationToken ct = default); + + /// + /// PendingApproval → Draft, so the requester can revise and resubmit. Same + /// caller restrictions as . + /// + Task RejectAsync(int poId, string? reason, CancellationToken ct = default); + Task CancelAsync(int poId, string? reason, CancellationToken ct = default); - /// Submit a Draft PO (Draft → Approved). 409 PO_NOT_EDITABLE if not Draft. + /// Submit a Draft PO (Draft → PendingApproval). 409 PO_NOT_EDITABLE if not Draft. Task SubmitAsync(int poId, CancellationToken ct = default); /// Delete a PO — permitted only while Draft, else 409 PO_NOT_EDITABLE. diff --git a/Backend/ERPCore/Services/Interfaces/ISalesDomainService.cs b/Backend/ERPCore/Services/Interfaces/ISalesDomainService.cs index 69ffe56..1477ed4 100644 --- a/Backend/ERPCore/Services/Interfaces/ISalesDomainService.cs +++ b/Backend/ERPCore/Services/Interfaces/ISalesDomainService.cs @@ -28,6 +28,16 @@ public interface ISalesDomainService bool allowManualOverride, CancellationToken ct = default); + /// + /// supplied (non-null) is an explicit override, used + /// as-is. Null resolves from the item's assigned TaxRateId — its + /// at this moment — or 0 if the item has + /// no tax rate assigned. This is what makes Item.TaxRate (formerly the cosmetic + /// TaxClass label) actually drive tax instead of every line needing a hand-typed + /// percentage. + /// + Task ResolveLineTaxPctAsync(int itemId, decimal? requestedTaxPct, CancellationToken ct = default); + SalesLineComputation ComputeLine( decimal qty, decimal freeQty, diff --git a/Backend/ERPCore/Services/Interfaces/ISupportTicketService.cs b/Backend/ERPCore/Services/Interfaces/ISupportTicketService.cs new file mode 100644 index 0000000..130d065 --- /dev/null +++ b/Backend/ERPCore/Services/Interfaces/ISupportTicketService.cs @@ -0,0 +1,20 @@ +using ERPCore.Common.Http; +using ERPCore.Domain.Enums; +using ERPCore.Dtos.Support; + +namespace ERPCore.Services.Interfaces; + +public interface ISupportTicketService +{ + Task> CreateAsync(int userId, CreateSupportTicketRequest request, CancellationToken ct = default); + + /// Admins see every ticket; other users see only their own. + Task> GetListAsync(int userId, bool isAdmin, CancellationToken ct = default); + + Task> GetByIdAsync(int ticketId, int userId, bool isAdmin, CancellationToken ct = default); + + Task> AddMessageAsync(int ticketId, int userId, bool isAdmin, AddSupportTicketMessageRequest request, uint expectedRowVersion, CancellationToken ct = default); + + /// Admin-only status transition. + Task> UpdateStatusAsync(int ticketId, int userId, bool isAdmin, UpdateSupportTicketStatusRequest request, uint expectedRowVersion, CancellationToken ct = default); +} diff --git a/Backend/ERPCore/Services/Interfaces/ITaxRateService.cs b/Backend/ERPCore/Services/Interfaces/ITaxRateService.cs new file mode 100644 index 0000000..0127bd4 --- /dev/null +++ b/Backend/ERPCore/Services/Interfaces/ITaxRateService.cs @@ -0,0 +1,16 @@ +using ERPCore.Common.Http; +using ERPCore.Domain.Enums; +using ERPCore.Dtos.Common; +using ERPCore.Dtos.TaxRates; + +namespace ERPCore.Services.Interfaces; + +/// Tax rate master business logic — see . +public interface ITaxRateService +{ + Task> ListAsync(PageQuery query, EntityStatus? status, CancellationToken ct = default); + Task?> GetAsync(int taxRateId, CancellationToken ct = default); + Task> CreateAsync(CreateTaxRateRequest request, CancellationToken ct = default); + Task> UpdateAsync(int taxRateId, UpdateTaxRateRequest request, uint expectedRowVersion, CancellationToken ct = default); + Task SetStatusAsync(int taxRateId, EntityStatus status, CancellationToken ct = default); +} diff --git a/Backend/ERPCore/Services/Interfaces/IUomService.cs b/Backend/ERPCore/Services/Interfaces/IUomService.cs index bb846f6..932abcd 100644 --- a/Backend/ERPCore/Services/Interfaces/IUomService.cs +++ b/Backend/ERPCore/Services/Interfaces/IUomService.cs @@ -1,3 +1,4 @@ +using ERPCore.Domain.Enums; using ERPCore.Dtos.Common; using ERPCore.Dtos.Uoms; @@ -6,6 +7,7 @@ namespace ERPCore.Services.Interfaces; /// UOM master business logic (docs/11-BACKEND-PHASE1.md §2.2). public interface IUomService { - Task> ListAsync(PageQuery query, CancellationToken ct = default); + Task> ListAsync(PageQuery query, EntityStatus? status, CancellationToken ct = default); Task CreateAsync(CreateUomRequest request, CancellationToken ct = default); + Task SetStatusAsync(int uomId, EntityStatus status, CancellationToken ct = default); } diff --git a/Backend/ERPCore/Services/Interfaces/IUserManagementService.cs b/Backend/ERPCore/Services/Interfaces/IUserManagementService.cs index 74a34d5..9ebad23 100644 --- a/Backend/ERPCore/Services/Interfaces/IUserManagementService.cs +++ b/Backend/ERPCore/Services/Interfaces/IUserManagementService.cs @@ -1,4 +1,5 @@ using ERPCore.Domain.Enums; +using ERPCore.Dtos.Auth; using ERPCore.Dtos.Common; using ERPCore.Dtos.Users; @@ -28,4 +29,12 @@ public interface IUserManagementService /// AuthHex UserType options for the create-user form's select. Task> ListUserTypesAsync(CancellationToken ct = default); + + /// + /// Admin-only escape hatch: permanently deletes a stale AuthHex identity by email/mobile/NIC/ + /// username so that identifier stops blocking new registrations (AuthHex's own duplicate + /// check has no concept of "deleted" — see docs/PROGRESS.md's AuthHex dedupe notes). Does not + /// touch ERPCore's local `users` table at all — only AuthHex's separate identity store. + /// + Task PurgeAuthHexIdentityAsync(PurgeAuthHexIdentityRequest request, CancellationToken ct = default); } diff --git a/Backend/ERPCore/Services/Interfaces/IWarehouseService.cs b/Backend/ERPCore/Services/Interfaces/IWarehouseService.cs index 331f1db..bf4997e 100644 --- a/Backend/ERPCore/Services/Interfaces/IWarehouseService.cs +++ b/Backend/ERPCore/Services/Interfaces/IWarehouseService.cs @@ -9,6 +9,8 @@ public interface IWarehouseService Task> ListAsync(PageQuery query, int? branchId, CancellationToken ct = default); Task GetAsync(int warehouseId, CancellationToken ct = default); Task CreateAsync(CreateWarehouseRequest request, CancellationToken ct = default); + Task UpdateAsync(int warehouseId, UpdateWarehouseRequest request, CancellationToken ct = default); + Task DeleteAsync(int warehouseId, CancellationToken ct = default); Task> ListBinsAsync(int warehouseId, CancellationToken ct = default); Task CreateBinAsync(int warehouseId, CreateBinRequest request, CancellationToken ct = default); diff --git a/Backend/ERPCore/Services/ItemService.cs b/Backend/ERPCore/Services/ItemService.cs index a2e3520..829ddba 100644 --- a/Backend/ERPCore/Services/ItemService.cs +++ b/Backend/ERPCore/Services/ItemService.cs @@ -30,11 +30,15 @@ public sealed class ItemService : IItemService private readonly IRepository _subCategories; private readonly IRepository _brands; private readonly IRepository _uoms; + private readonly IRepository _taxRates; private readonly IRepository _vendors; private readonly IRepository _warehouses; private readonly IRepository _stockLayers; private readonly IRepository _stockLedger; + private readonly IRepository _batches; + private readonly IRepository _serials; private readonly IProductConfigService _config; + private readonly INotificationService _notifications; private readonly IUnitOfWork _uow; public ItemService( @@ -43,11 +47,15 @@ public sealed class ItemService : IItemService IRepository subCategories, IRepository brands, IRepository uoms, + IRepository taxRates, IRepository vendors, IRepository warehouses, IRepository stockLayers, IRepository stockLedger, + IRepository batches, + IRepository serials, IProductConfigService config, + INotificationService notifications, IUnitOfWork uow) { _items = items; @@ -55,11 +63,15 @@ public sealed class ItemService : IItemService _subCategories = subCategories; _brands = brands; _uoms = uoms; + _taxRates = taxRates; _vendors = vendors; _warehouses = warehouses; _stockLayers = stockLayers; _stockLedger = stockLedger; + _batches = batches; + _serials = serials; _config = config; + _notifications = notifications; _uow = uow; } @@ -86,10 +98,11 @@ public sealed class ItemService : IItemService .Select(i => new ItemListItemDto( i.ItemId, i.Sku, i.Name, i.CategoryId, i.SubCategoryId, i.BrandId, i.BaseUomId, i.DefaultVendorId, - i.StockNature, i.TrackingMode, i.Warranty, i.WarrantyPeriodMonths, i.TaxClass, + i.StockNature, i.TrackingMode, i.Warranty, i.WarrantyPeriodMonths, + i.TaxRateId, i.TaxRate == null ? null : i.TaxRate.Name, i.TaxRate == null ? null : i.TaxRate.Percentage, i.SellingMinPrice, i.SellingMaxPrice, i.SellingFlatPrice, i.ContentQty, i.ContentUnit, i.ContentBaseQty, i.ContentBaseUnit, - i.Status)) + i.Status, i.Barcode)) .ToListAsync(ct); return PagedResponse.Create(rows, query.Page, query.PageSize, total); @@ -99,6 +112,7 @@ public sealed class ItemService : IItemService { var item = await _items.Query().AsNoTracking() .Include(i => i.ReorderSettings) + .Include(i => i.TaxRate) .FirstOrDefaultAsync(i => i.ItemId == itemId, ct); return item is null ? null : new ETagged(ToDetail(item), item.RowVersion); @@ -109,10 +123,14 @@ public sealed class ItemService : IItemService if (await _items.Query().AnyAsync(i => i.Sku == request.Sku, ct)) throw new DomainException(ErrorCodes.SkuDuplicate, $"An item with SKU '{request.Sku}' already exists.", 400); + var barcode = NormalizeBarcode(request.Barcode); + if (barcode is not null && await _items.Query().AnyAsync(i => i.Barcode == barcode, ct)) + throw new DomainException(ErrorCodes.Validation, $"An item with barcode '{barcode}' already exists.", 422); + var config = (await _config.GetAsync(ct)).Value; await ValidateReferencesAsync( request.CategoryId, request.SubCategoryId, request.BrandId, - request.BaseUomId, request.DefaultVendorId, config, ct); + request.BaseUomId, request.DefaultVendorId, request.TaxRateId, config, ct); ValidateFeatureConfiguration(request, config); ItemContent.ValidatePair(request.ContentQty, request.ContentUnit); @@ -133,7 +151,7 @@ public sealed class ItemService : IItemService TrackingMode = request.TrackingMode, Warranty = request.Warranty, WarrantyPeriodMonths = warrantyPeriodMonths, - TaxClass = request.TaxClass, + TaxRateId = request.TaxRateId, SellingMinPrice = request.SellingMinPrice, SellingMaxPrice = request.SellingMaxPrice, SellingFlatPrice = request.SellingFlatPrice, @@ -141,12 +159,17 @@ public sealed class ItemService : IItemService ContentUnit = request.ContentUnit, ContentBaseQty = contentBaseQty, ContentBaseUnit = contentBaseUnit, + Barcode = barcode, Status = EntityStatus.Active, CreatedAt = DateTime.UtcNow }; await _items.AddAsync(item, ct); await _uow.SaveChangesAsync(ct); + if (item.TaxRateId is not null) + item.TaxRate = await _taxRates.Query().AsNoTracking().FirstAsync(t => t.TaxRateId == item.TaxRateId, ct); + + await _notifications.RaiseAsync("item.created", "Item Created", $"Item {item.Sku} ({item.Name}) was created.", nameof(Item), item.ItemId, ct); return new ETagged(ToDetail(item), item.RowVersion); } @@ -156,6 +179,7 @@ public sealed class ItemService : IItemService { var item = await _items.Query() .Include(i => i.ReorderSettings) + .Include(i => i.TaxRate) .FirstOrDefaultAsync(i => i.ItemId == itemId, ct) ?? throw new NotFoundException($"Item {itemId} was not found."); @@ -166,10 +190,15 @@ public sealed class ItemService : IItemService && await _items.Query().AnyAsync(i => i.Sku == request.Sku && i.ItemId != itemId, ct)) throw new DomainException(ErrorCodes.SkuDuplicate, $"An item with SKU '{request.Sku}' already exists.", 400); + var barcode = NormalizeBarcode(request.Barcode); + if (barcode is not null && !string.Equals(item.Barcode, barcode, StringComparison.Ordinal) + && await _items.Query().AnyAsync(i => i.Barcode == barcode && i.ItemId != itemId, ct)) + throw new DomainException(ErrorCodes.Validation, $"An item with barcode '{barcode}' already exists.", 422); + var config = (await _config.GetAsync(ct)).Value; await ValidateReferencesAsync( request.CategoryId, request.SubCategoryId, request.BrandId, - request.BaseUomId, request.DefaultVendorId, config, ct); + request.BaseUomId, request.DefaultVendorId, request.TaxRateId, config, ct); ValidateFeatureConfiguration(request, config); // The base UOM is the sole meaning of every quantity recorded against this item — @@ -197,7 +226,7 @@ public sealed class ItemService : IItemService item.TrackingMode = request.TrackingMode; item.Warranty = request.Warranty; item.WarrantyPeriodMonths = warrantyPeriodMonths; - item.TaxClass = request.TaxClass; + item.TaxRateId = request.TaxRateId; item.SellingMinPrice = request.SellingMinPrice; item.SellingMaxPrice = request.SellingMaxPrice; item.SellingFlatPrice = request.SellingFlatPrice; @@ -205,9 +234,14 @@ public sealed class ItemService : IItemService item.ContentUnit = request.ContentUnit; item.ContentBaseQty = contentBaseQty; item.ContentBaseUnit = contentBaseUnit; + item.Barcode = barcode; item.UpdatedAt = DateTime.UtcNow; await SaveGuardingConcurrencyAsync(ct); + item.TaxRate = item.TaxRateId is null + ? null + : await _taxRates.Query().AsNoTracking().FirstAsync(t => t.TaxRateId == item.TaxRateId, ct); + await _notifications.RaiseAsync("item.updated", "Item Updated", $"Item {item.Sku} ({item.Name}) was updated.", nameof(Item), item.ItemId, ct); return new ETagged(ToDetail(item), item.RowVersion); } @@ -285,7 +319,7 @@ public sealed class ItemService : IItemService /// it is advisory and honoured by the frontend only (docs/11 §2.8). /// private async Task ValidateReferencesAsync( - int categoryId, int? subCategoryId, int? brandId, int baseUomId, int? defaultVendorId, + int categoryId, int? subCategoryId, int? brandId, int baseUomId, int? defaultVendorId, int? taxRateId, ProductConfigDto config, CancellationToken ct) { if (!await _categories.Query().AnyAsync(c => c.CategoryId == categoryId, ct)) @@ -339,6 +373,16 @@ public sealed class ItemService : IItemService if (vendor.Status != EntityStatus.Active) throw new DomainException(ErrorCodes.Validation, $"Vendor {defaultVendorId} is inactive.", 422); } + + if (taxRateId is not null) + { + var taxRate = await _taxRates.Query().AsNoTracking() + .FirstOrDefaultAsync(t => t.TaxRateId == taxRateId, ct); + if (taxRate is null) + throw new DomainException(ErrorCodes.Validation, $"Tax rate {taxRateId} does not exist.", 422); + if (taxRate.Status != EntityStatus.Active) + throw new DomainException(ErrorCodes.Validation, $"Tax rate {taxRateId} is inactive.", 422); + } } private static void ValidateFeatureConfiguration(CreateItemRequest request, ProductConfigDto config) @@ -410,13 +454,67 @@ public sealed class ItemService : IItemService } } + /// Trims and blank-collapses a barcode, mirroring Sku.Trim() — a stray + /// space or an empty string would otherwise save as a value that never matches a real + /// scan, or collide with another item's blank barcode under the unique index. + private static string? NormalizeBarcode(string? barcode) + { + var trimmed = barcode?.Trim(); + return string.IsNullOrEmpty(trimmed) ? null : trimmed; + } + + public async Task ScanAsync(string code, int? itemId, CancellationToken ct = default) + { + code = code.Trim(); + if (code.Length == 0) + throw new DomainException(ErrorCodes.Validation, "code is required.", 422); + + if (itemId is not null) + { + var batchForItem = await _batches.Query().AsNoTracking().Include(b => b.Item) + .FirstOrDefaultAsync(b => b.ItemId == itemId && (b.Barcode == code || b.BatchNo == code), ct); + if (batchForItem is not null) return ToScanResult(batchForItem); + + var serialForItem = await _serials.Query().AsNoTracking().Include(s => s.Item) + .FirstOrDefaultAsync(s => s.ItemId == itemId && (s.Barcode == code || s.SerialNo == code), ct); + if (serialForItem is not null) return ToScanResult(serialForItem); + } + + var item = await _items.Query().AsNoTracking() + .FirstOrDefaultAsync(i => i.Barcode == code || i.Sku == code, ct); + if (item is not null) return ToScanResult(item); + + var serial = await _serials.Query().AsNoTracking().Include(s => s.Item) + .FirstOrDefaultAsync(s => s.Barcode == code || s.SerialNo == code, ct); + if (serial is not null) return ToScanResult(serial); + + var batch = await _batches.Query().AsNoTracking().Include(b => b.Item) + .FirstOrDefaultAsync(b => b.Barcode == code || b.BatchNo == code, ct); + if (batch is not null) return ToScanResult(batch); + + return null; + } + + private static ItemScanResultDto ToScanResult(Item i) => new( + i.ItemId, i.Sku, i.Name, i.TrackingMode, i.BaseUomId, "Item", + null, null, null, null, null, null); + + private static ItemScanResultDto ToScanResult(Batch b) => new( + b.Item!.ItemId, b.Item.Sku, b.Item.Name, b.Item.TrackingMode, b.Item.BaseUomId, "Batch", + b.BatchId, b.BatchNo, b.ExpiryDate, null, null, null); + + private static ItemScanResultDto ToScanResult(Serial s) => new( + s.Item!.ItemId, s.Item.Sku, s.Item.Name, s.Item.TrackingMode, s.Item.BaseUomId, "Serial", + null, null, null, s.SerialId, s.SerialNo, s.Status); + private static ItemDetailDto ToDetail(Item i) => new( i.ItemId, i.Sku, i.Name, i.Description, i.CategoryId, i.SubCategoryId, i.BrandId, i.BaseUomId, i.DefaultVendorId, - i.StockNature, i.TrackingMode, i.Warranty, i.WarrantyPeriodMonths, i.TaxClass, + i.StockNature, i.TrackingMode, i.Warranty, i.WarrantyPeriodMonths, + i.TaxRateId, i.TaxRate?.Name, i.TaxRate?.Percentage, i.SellingMinPrice, i.SellingMaxPrice, i.SellingFlatPrice, i.ContentQty, i.ContentUnit, i.ContentBaseQty, i.ContentBaseUnit, - i.Status, + i.Status, i.Barcode, i.ReorderSettings .OrderBy(r => r.WarehouseId) .Select(r => new ItemReorderDto(r.WarehouseId, r.ReorderPoint, r.ReorderQty)) diff --git a/Backend/ERPCore/Services/NavPermissionService.cs b/Backend/ERPCore/Services/NavPermissionService.cs new file mode 100644 index 0000000..4bf1d0e --- /dev/null +++ b/Backend/ERPCore/Services/NavPermissionService.cs @@ -0,0 +1,113 @@ +using ERPCore.Domain.Entities; +using ERPCore.Domain.Enums; +using ERPCore.Repositories.Interfaces; +using ERPCore.Services.Interfaces; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Caching.Memory; + +namespace ERPCore.Services; + +/// +/// See . A role's permitted nav-code set changes +/// rarely (an admin editing Roles → Permissions) but is looked up on every gated +/// request, so it's cached per role code for a short window rather than re-querying +/// RolePermission every call — a Roles→Permissions edit takes up to +/// to take effect for already-issued tokens of that role. +/// +public sealed class NavPermissionService : INavPermissionService +{ + private static readonly TimeSpan CacheTtl = TimeSpan.FromMinutes(2); + + private readonly IRepository _roles; + private readonly IRepository _rolePermissions; + private readonly IMemoryCache _cache; + + public NavPermissionService(IRepository roles, IRepository rolePermissions, IMemoryCache cache) + { + _roles = roles; + _rolePermissions = rolePermissions; + _cache = cache; + } + + public async Task HasAccessAsync(string? roleCode, string navCode, CancellationToken ct = default) + { + if (string.IsNullOrWhiteSpace(roleCode)) return false; + + var codes = await GetNavCodesAsync(roleCode.Trim(), ct); + return codes.Contains(navCode) || codes.Any(c => c.StartsWith(navCode + ".", StringComparison.OrdinalIgnoreCase)); + } + + public async Task HasActionAsync(string? roleCode, string navCode, RolePermissionAction action, CancellationToken ct = default) + { + if (string.IsNullOrWhiteSpace(roleCode)) return false; + + var actionsByCode = await GetActionsByNavCodeAsync(roleCode.Trim(), ct); + return actionsByCode.TryGetValue(navCode, out var granted) && granted.HasFlag(action); + } + + private async Task> GetNavCodesAsync(string roleCode, CancellationToken ct) + { + var cacheKey = $"nav-permission-codes:{roleCode.ToLowerInvariant()}"; + if (_cache.TryGetValue(cacheKey, out HashSet? cached) && cached is not null) + return cached; + + // Same shape as RoleService.GetMeAsync's navCodes computation — mirrored rather + // than shared because that method also carries the unauthenticated/no-role + // early-return branches this lookup doesn't need. + var role = await _roles.Query().AsNoTracking() + .FirstOrDefaultAsync(r => r.Code.ToLower() == roleCode.ToLower(), ct); + + var codes = role is null + ? new HashSet(StringComparer.OrdinalIgnoreCase) + : (await _rolePermissions.Query().AsNoTracking() + .Where(rp => rp.RoleId == role.RoleId) + .Include(rp => rp.Permission!).ThenInclude(p => p.NavItem) + .Include(rp => rp.Permission!).ThenInclude(p => p.SubNavItem) + .Select(rp => rp.Permission!) + .ToListAsync(ct)) + .Select(p => p.NavItem?.Code ?? p.SubNavItem?.Code) + .Where(c => c is not null) + .Select(c => c!) + .ToHashSet(StringComparer.OrdinalIgnoreCase); + + _cache.Set(cacheKey, codes, CacheTtl); + return codes; + } + + private async Task> GetActionsByNavCodeAsync(string roleCode, CancellationToken ct) + { + var cacheKey = $"nav-permission-actions:{roleCode.ToLowerInvariant()}"; + if (_cache.TryGetValue(cacheKey, out Dictionary? cached) && cached is not null) + return cached; + + var role = await _roles.Query().AsNoTracking() + .FirstOrDefaultAsync(r => r.Code.ToLower() == roleCode.ToLower(), ct); + + var actionsByCode = new Dictionary(StringComparer.OrdinalIgnoreCase); + if (role is not null) + { + var rows = await _rolePermissions.Query().AsNoTracking() + .Where(rp => rp.RoleId == role.RoleId) + .Include(rp => rp.Permission!).ThenInclude(p => p.NavItem) + .Include(rp => rp.Permission!).ThenInclude(p => p.SubNavItem) + .Select(rp => new { rp.Actions, rp.Permission!.NavItem, rp.Permission!.SubNavItem }) + .ToListAsync(ct); + + foreach (var row in rows) + { + var code = row.NavItem?.Code ?? row.SubNavItem?.Code; + if (code is null) continue; + + // A role could in principle hold two permission rows resolving to the same + // code (shouldn't happen given one Permission per NavItem/SubNavItem, but + // OR rather than overwrite so a duplicate never silently narrows access). + actionsByCode[code] = actionsByCode.TryGetValue(code, out var existing) + ? existing | row.Actions + : row.Actions; + } + } + + _cache.Set(cacheKey, actionsByCode, CacheTtl); + return actionsByCode; + } +} diff --git a/Backend/ERPCore/Services/NotificationService.cs b/Backend/ERPCore/Services/NotificationService.cs new file mode 100644 index 0000000..70708c9 --- /dev/null +++ b/Backend/ERPCore/Services/NotificationService.cs @@ -0,0 +1,111 @@ +using ERPCore.Domain.Entities; +using ERPCore.Domain.Enums; +using ERPCore.Domain.Notifications; +using ERPCore.Dtos.Notifications; +using ERPCore.Infra.UoW; +using ERPCore.Repositories.Interfaces; +using ERPCore.Services.Interfaces; +using Microsoft.EntityFrameworkCore; + +namespace ERPCore.Services; + +public sealed class NotificationService : INotificationService +{ + private readonly IRepository _notifications; + private readonly IRepository _recipients; + private readonly IRepository _users; + private readonly INotificationConfigService _config; + private readonly IUnitOfWork _uow; + + public NotificationService( + IRepository notifications, + IRepository recipients, + IRepository users, + INotificationConfigService config, + IUnitOfWork uow) + { + _notifications = notifications; + _recipients = recipients; + _users = users; + _config = config; + _uow = uow; + } + + public async Task RaiseAsync( + string moduleKey, + string title, + string message, + string? relatedEntityType = null, + int? relatedEntityId = null, + CancellationToken ct = default) + { + var channels = await _config.ResolveEnabledChannelsAsync(moduleKey, ct); + if (!channels.Contains(NotificationChannel.InApp)) return; + + var activeUserIds = await _users.Query().AsNoTracking() + .Where(u => u.Status == EntityStatus.Active) + .Select(u => u.UserId) + .ToListAsync(ct); + + if (activeUserIds.Count == 0) return; + + var notification = new Notification + { + ModuleKey = moduleKey, + Title = title, + Message = message, + RelatedEntityType = relatedEntityType, + RelatedEntityId = relatedEntityId, + CreatedAt = DateTime.UtcNow + }; + notification.Recipients = activeUserIds + .Select(userId => new NotificationRecipient { UserId = userId }) + .ToList(); + + await _notifications.AddAsync(notification, ct); + await _uow.SaveChangesAsync(ct); + } + + public async Task GetFeedAsync(int userId, int take = 20, CancellationToken ct = default) + { + var query = _recipients.Query().AsNoTracking() + .Where(r => r.UserId == userId); + + var unreadCount = await query.CountAsync(r => !r.IsRead, ct); + + var items = await query + .Include(r => r.Notification) + .OrderByDescending(r => r.Notification!.CreatedAt) + .Take(take) + .Select(r => new NotificationDto( + r.Notification!.NotificationId, + r.Notification.ModuleKey, + r.Notification.Title, + r.Notification.Message, + r.Notification.RelatedEntityType, + r.Notification.RelatedEntityId, + r.Notification.CreatedAt, + r.IsRead)) + .ToListAsync(ct); + + return new NotificationFeedDto(items, unreadCount); + } + + public async Task MarkAllReadAsync(int userId, CancellationToken ct = default) + { + var unread = await _recipients.Query() + .Where(r => r.UserId == userId && !r.IsRead) + .ToListAsync(ct); + + if (unread.Count == 0) return; + + var now = DateTime.UtcNow; + foreach (var recipient in unread) + { + recipient.IsRead = true; + recipient.ReadAt = now; + } + + await _uow.SaveChangesAsync(ct); + } +} diff --git a/Backend/ERPCore/Services/NumberSequenceService.cs b/Backend/ERPCore/Services/NumberSequenceService.cs index c48d349..56fdeca 100644 --- a/Backend/ERPCore/Services/NumberSequenceService.cs +++ b/Backend/ERPCore/Services/NumberSequenceService.cs @@ -1,5 +1,7 @@ using System.Data; using ERPCore.Infra.Persistence; +using ERPCore.Repositories.Interfaces; +using ERPCore.Domain.Entities; using ERPCore.Services.Interfaces; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Storage; @@ -8,23 +10,42 @@ namespace ERPCore.Services; /// /// Atomic document-number issuer. Uses a single INSERT … ON CONFLICT … DO UPDATE -/// … RETURNING so concurrent issues for the same (docType, year) cannot get the -/// same number (the row is locked for the duration of the upsert). Runs as a direct +/// … RETURNING so concurrent issues for the same (docType, branchId, year) cannot get +/// the same number (the row is locked for the duration of the upsert). Runs as a direct /// ADO.NET command enlisted in the DbContext's current transaction so it commits or /// rolls back with the document (FR-X-03). EF's SqlQuery is avoided here /// because it wraps the statement in a subquery, which PostgreSQL disallows for a -/// data-modifying statement. +/// data-modifying statement. Numbering is per-branch (docs/BRANCH_ISOLATION_PLAN.md §5): +/// the sequence key is (doc_type, branch_id, year) and the format includes the branch code, +/// e.g. PO-BR-001-2026-00042. /// public sealed class NumberSequenceService : INumberSequenceService { private readonly ErpDbContext _db; + private readonly IRepository _branches; + private readonly IBranchConfigService _branchConfig; - public NumberSequenceService(ErpDbContext db) => _db = db; + public NumberSequenceService(ErpDbContext db, IRepository branches, IBranchConfigService branchConfig) + { + _db = db; + _branches = branches; + _branchConfig = branchConfig; + } public async Task NextAsync(string docType, CancellationToken ct = default) + { + var defaultBranchId = await _branchConfig.ResolveDefaultBranchIdAsync(ct); + return await NextAsync(docType, defaultBranchId, ct); + } + + public async Task NextAsync(string docType, int branchId, CancellationToken ct = default) { var year = DateTime.UtcNow.Year; + var branchCode = await _branches.Query().AsNoTracking() + .Where(b => b.BranchId == branchId).Select(b => b.Code).FirstOrDefaultAsync(ct) + ?? throw new InvalidOperationException($"Branch {branchId} was not found — cannot issue a document number."); + var conn = _db.Database.GetDbConnection(); if (conn.State != ConnectionState.Open) await conn.OpenAsync(ct); @@ -32,20 +53,21 @@ public sealed class NumberSequenceService : INumberSequenceService await using var cmd = conn.CreateCommand(); cmd.Transaction = _db.Database.CurrentTransaction?.GetDbTransaction(); cmd.CommandText = """ - INSERT INTO number_sequences (doc_type, year, last_number) - VALUES (@docType, @year, 1) - ON CONFLICT (doc_type, year) + INSERT INTO number_sequences (doc_type, branch_id, year, last_number) + VALUES (@docType, @branchId, @year, 1) + ON CONFLICT (doc_type, branch_id, year) DO UPDATE SET last_number = number_sequences.last_number + 1 RETURNING last_number; """; AddParam(cmd, "docType", docType); + AddParam(cmd, "branchId", branchId); AddParam(cmd, "year", year); var result = await cmd.ExecuteScalarAsync(ct) ?? throw new InvalidOperationException($"Failed to issue a document number for '{docType}'."); var next = Convert.ToInt64(result); - return $"{docType}-{year}-{next:D5}"; + return $"{docType}-{branchCode}-{year}-{next:D5}"; } private static void AddParam(IDbCommand cmd, string name, object value) diff --git a/Backend/ERPCore/Services/PurchaseInvoiceService.cs b/Backend/ERPCore/Services/PurchaseInvoiceService.cs index 946db05..4d2b6c7 100644 --- a/Backend/ERPCore/Services/PurchaseInvoiceService.cs +++ b/Backend/ERPCore/Services/PurchaseInvoiceService.cs @@ -90,14 +90,17 @@ public sealed class PurchaseInvoiceService : IPurchaseInvoiceService var grns = await LoadAndValidateGrnsAsync(request.VendorId, request.GrnIds, excludingPurchaseInvoiceId: null, ct); + var branchId = grns[0].BranchId; + var invoice = await _uow.ExecuteInTransactionAsync(async token => { var entity = new PurchaseInvoice { - DocNo = await _numbers.NextAsync(DocumentTypes.PurchaseInvoice, token), + DocNo = await _numbers.NextAsync(DocumentTypes.PurchaseInvoice, branchId, token), VendorInvoiceNo = vendorInvoiceNo, VendorInvoiceDate = request.VendorInvoiceDate, VendorId = request.VendorId, + BranchId = branchId, VendorSnapshotName = vendor.Name, VendorSnapshotTaxNo = vendor.TaxReg, Status = PurchaseInvoiceStatus.Draft, @@ -142,6 +145,7 @@ public sealed class PurchaseInvoiceService : IPurchaseInvoiceService if (line.Grn is not null && !newGrnIds.Contains(line.Grn.GrnId)) line.Grn.PurchaseInvoiceId = null; invoice.VendorId = request.VendorId; + invoice.BranchId = grns[0].BranchId; invoice.VendorInvoiceNo = vendorInvoiceNo; invoice.VendorInvoiceDate = request.VendorInvoiceDate; invoice.VendorSnapshotName = vendor.Name; @@ -265,6 +269,12 @@ public sealed class PurchaseInvoiceService : IPurchaseInvoiceService throw new DomainException(ErrorCodes.GrnAlreadyInvoiced, $"GRN {grn.DocNo} is already linked to another purchase invoice.", 409); } + // A purchase invoice consolidates GRNs into one branch-scoped document — reject a + // mix (docs/BRANCH_ISOLATION_PLAN.md "Purchase Invoice (AP)"). + var branchIds = grns.Select(g => g.BranchId).Distinct().ToList(); + if (branchIds.Count > 1) + throw new DomainException(ErrorCodes.GrnBranchMismatch, "Selected GRNs belong to different branches and cannot be consolidated onto one purchase invoice.", 409); + return grns; } @@ -290,11 +300,11 @@ public sealed class PurchaseInvoiceService : IPurchaseInvoiceService x.Subtotal, x.VatTotal, x.GrandTotal, x.PaidAmount, x.BalanceAmount); private static PurchaseInvoiceSummaryDto MapSummary(PurchaseInvoice x) => new( - x.PurchaseInvoiceId, x.DocNo, x.VendorInvoiceNo, x.VendorInvoiceDate, x.VendorId, + x.PurchaseInvoiceId, x.DocNo, x.VendorInvoiceNo, x.VendorInvoiceDate, x.VendorId, x.BranchId, x.VendorSnapshotName, x.Status, x.Lines.Count, MapTotals(x), x.CreatedAt, x.GlJournalNo); private static PurchaseInvoiceDto MapInvoice(PurchaseInvoice x) => new( - x.PurchaseInvoiceId, x.DocNo, x.VendorInvoiceNo, x.VendorInvoiceDate, x.VendorId, + x.PurchaseInvoiceId, x.DocNo, x.VendorInvoiceNo, x.VendorInvoiceDate, x.VendorId, x.BranchId, x.VendorSnapshotName, x.VendorSnapshotTaxNo, x.Status, x.Lines.Count, x.CreatedBy, x.CreatedAt, x.UpdatedAt, x.GlJournalNo, x.GlPostedAt, MapTotals(x), x.Lines.OrderBy(l => l.PurchaseInvoiceLineId).Select(l => new PurchaseInvoiceLineDto( diff --git a/Backend/ERPCore/Services/PurchaseOrderService.cs b/Backend/ERPCore/Services/PurchaseOrderService.cs index e19aabd..a83e845 100644 --- a/Backend/ERPCore/Services/PurchaseOrderService.cs +++ b/Backend/ERPCore/Services/PurchaseOrderService.cs @@ -14,9 +14,10 @@ using Microsoft.EntityFrameworkCore; namespace ERPCore.Services; /// -/// Purchase-order service. Phase 1 auto-approves on creation (FR-PROC-04), -/// PO is freely editable while open (FR-PROC-05), totals are computed server-side -/// (02-SECURITY C.2), and cancel is blocked once any receipt exists. +/// Purchase-order service. Issuing a PO (create non-draft, or submit a Draft) routes it +/// through PendingApproval → Approved (FR-PROC-04); a Draft is freely editable +/// (FR-PROC-05); totals are computed server-side (02-SECURITY C.2); cancel is blocked +/// once any receipt exists. /// public sealed class PurchaseOrderService : IPurchaseOrderService { @@ -30,12 +31,15 @@ public sealed class PurchaseOrderService : IPurchaseOrderService private readonly IRepository _warehouses; private readonly INumberSequenceService _numbers; private readonly ICurrentUser _currentUser; + private readonly INotificationService _notifications; + private readonly IBranchConfigService _branchConfig; private readonly IUnitOfWork _uow; public PurchaseOrderService( IRepository pos, IRepository vendors, IRepository requisitions, IRepository items, IRepository uoms, IRepository warehouses, - INumberSequenceService numbers, ICurrentUser currentUser, IUnitOfWork uow) + INumberSequenceService numbers, ICurrentUser currentUser, INotificationService notifications, + IBranchConfigService branchConfig, IUnitOfWork uow) { _pos = pos; _vendors = vendors; @@ -45,6 +49,8 @@ public sealed class PurchaseOrderService : IPurchaseOrderService _warehouses = warehouses; _numbers = numbers; _currentUser = currentUser; + _notifications = notifications; + _branchConfig = branchConfig; _uow = uow; } @@ -66,7 +72,7 @@ public sealed class PurchaseOrderService : IPurchaseOrderService .ToListAsync(ct); var summaries = rows.Select(p => new PurchaseOrderSummaryDto( - p.PoId, p.DocNo, p.VendorId, p.Status, p.ApprovalRequired, p.CreatedAt, ComputeTotals(p.Lines))).ToList(); + p.PoId, p.DocNo, p.VendorId, p.BranchId, p.Status, p.ApprovalRequired, p.CreatedBy, p.CreatedAt, ComputeTotals(p.Lines))).ToList(); return PagedResponse.Create(summaries, query.Page, query.PageSize, total); } @@ -82,20 +88,22 @@ public sealed class PurchaseOrderService : IPurchaseOrderService public async Task> CreateAsync(CreatePurchaseOrderRequest request, CancellationToken ct = default) { await ValidateReferencesAsync(request.VendorId, request.RequisitionId, request.Lines, ct); + var branchId = await _branchConfig.ResolveBranchIdAsync(request.BranchId, ct); + await EnsureLinesInBranchAsync(branchId, request.Lines.Select(l => l.WarehouseId), ct); var actor = _currentUser.AuditUserId; var po = await _uow.ExecuteInTransactionAsync(async token => { - var docNo = await _numbers.NextAsync(DocumentTypes.PurchaseOrder, token); + var docNo = await _numbers.NextAsync(DocumentTypes.PurchaseOrder, branchId, token); var entity = new PurchaseOrder { DocNo = docNo, VendorId = request.VendorId, + BranchId = branchId, RequisitionId = request.RequisitionId, - // Phase 1: approvalRequired defaults off → auto-approved on creation (FR-PROC-04), - // unless the caller explicitly saves a Draft (editable/deletable until submitted). - ApprovalRequired = false, - Status = request.SaveAsDraft ? PurchaseOrderStatus.Draft : PurchaseOrderStatus.Approved, + // Not a Draft ⇒ issued immediately, same as submitting one (FR-PROC-04). + ApprovalRequired = !request.SaveAsDraft, + Status = request.SaveAsDraft ? PurchaseOrderStatus.Draft : PurchaseOrderStatus.PendingApproval, CreatedBy = actor, CreatedAt = DateTime.UtcNow, Lines = request.Lines.Select(ToLine).ToList() @@ -104,6 +112,10 @@ public sealed class PurchaseOrderService : IPurchaseOrderService return entity; }, ct); + await _notifications.RaiseAsync("purchase.order.created", "Purchase Order Created", $"Purchase order {po.DocNo} was created.", nameof(PurchaseOrder), po.PoId, ct); + if (po.Status == PurchaseOrderStatus.PendingApproval) + await _notifications.RaiseAsync("purchase.order.pending_approval", "Purchase Order Awaiting Approval", $"Purchase order {po.DocNo} is awaiting approval.", nameof(PurchaseOrder), po.PoId, ct); + return new ETagged(Map(po), po.RowVersion); } @@ -122,6 +134,7 @@ public sealed class PurchaseOrderService : IPurchaseOrderService throw new DomainException(ErrorCodes.PoNotEditable, $"Purchase order {poId} is {po.Status} and cannot be edited.", 409); await ValidateReferencesAsync(request.VendorId, request.RequisitionId, request.Lines, ct); + await EnsureLinesInBranchAsync(po.BranchId, request.Lines.Select(l => l.WarehouseId), ct); po.VendorId = request.VendorId; po.RequisitionId = request.RequisitionId; @@ -145,22 +158,52 @@ public sealed class PurchaseOrderService : IPurchaseOrderService } public async Task ApproveAsync(int poId, CancellationToken ct = default) + { + var po = await LoadForApprovalDecisionAsync(poId, ct); + + po.Status = PurchaseOrderStatus.Approved; + po.ApprovedBy = _currentUser.AuditUserId; + po.ApprovedAt = DateTime.UtcNow; + po.UpdatedAt = po.ApprovedAt; + await _uow.SaveChangesAsync(ct); + await _notifications.RaiseAsync("purchase.order.approved", "Purchase Order Approved", $"Purchase order {po.DocNo} was approved.", nameof(PurchaseOrder), po.PoId, ct); + + return Map(po); + } + + public async Task RejectAsync(int poId, string? reason, CancellationToken ct = default) + { + var po = await LoadForApprovalDecisionAsync(poId, ct); + + // Back to Draft, not Cancelled — a reject is "revise and resubmit", not "abandon". + po.Status = PurchaseOrderStatus.Draft; + po.UpdatedAt = DateTime.UtcNow; + await _uow.SaveChangesAsync(ct); + var suffix = string.IsNullOrWhiteSpace(reason) ? "." : $": {reason}"; + await _notifications.RaiseAsync("purchase.order.rejected", "Purchase Order Rejected", $"Purchase order {po.DocNo} was rejected{suffix}", nameof(PurchaseOrder), po.PoId, ct); + + return Map(po); + } + + /// Shared load + gate for Approve/Reject: must be PendingApproval, and the + /// caller must be an Admin who isn't the PO's own creator (self-approval is blocked). + private async Task LoadForApprovalDecisionAsync(int poId, CancellationToken ct) { var po = await _pos.Query() .Include(p => p.Lines) .FirstOrDefaultAsync(p => p.PoId == poId, ct) ?? throw new NotFoundException($"Purchase order {poId} was not found."); - // Phase 1 no-op: POs are already Approved on creation. Kept for the future - // approval workflow (PendingApproval → Approved) — FR-PROC-04. - if (po.Status == PurchaseOrderStatus.PendingApproval) - { - po.Status = PurchaseOrderStatus.Approved; - po.UpdatedAt = DateTime.UtcNow; - await _uow.SaveChangesAsync(ct); - } + if (po.Status != PurchaseOrderStatus.PendingApproval) + throw new DomainException(ErrorCodes.PoNotPendingApproval, $"Purchase order {poId} is {po.Status} and is not awaiting approval.", 409); - return Map(po); + if (!_currentUser.IsAdmin) + throw new DomainException(ErrorCodes.PoApprovalForbidden, "Only an Admin may approve or reject a purchase order.", 403); + + if (po.CreatedBy == _currentUser.AuditUserId) + throw new DomainException(ErrorCodes.PoApprovalForbidden, "You cannot approve or reject your own purchase order.", 403); + + return po; } public async Task CancelAsync(int poId, string? reason, CancellationToken ct = default) @@ -193,10 +236,11 @@ public sealed class PurchaseOrderService : IPurchaseOrderService if (po.Status != PurchaseOrderStatus.Draft) throw new DomainException(ErrorCodes.PoNotEditable, $"Purchase order {poId} is {po.Status} and cannot be submitted.", 409); - // Phase 1: no value gate, so a submitted draft goes straight to Approved (FR-PROC-04). - po.Status = PurchaseOrderStatus.Approved; + po.Status = PurchaseOrderStatus.PendingApproval; + po.ApprovalRequired = true; po.UpdatedAt = DateTime.UtcNow; await _uow.SaveChangesAsync(ct); + await _notifications.RaiseAsync("purchase.order.pending_approval", "Purchase Order Awaiting Approval", $"Purchase order {po.DocNo} is awaiting approval.", nameof(PurchaseOrder), po.PoId, ct); return Map(po); } @@ -260,6 +304,20 @@ public sealed class PurchaseOrderService : IPurchaseOrderService await EnsureAllExistAsync(_warehouses.Query().Select(w => w.WarehouseId), lines.Select(l => l.WarehouseId), "Warehouse", ct); } + /// A PO is constrained to one branch (docs/BRANCH_ISOLATION_PLAN.md — Open + /// Question #1, decided as (a)): every line's warehouse must belong to the PO's branch. + private async Task EnsureLinesInBranchAsync(int branchId, IEnumerable warehouseIds, CancellationToken ct) + { + var ids = warehouseIds.Distinct().ToList(); + var mismatched = await _warehouses.Query().AsNoTracking() + .Where(w => ids.Contains(w.WarehouseId) && w.BranchId != branchId) + .Select(w => w.WarehouseId) + .ToListAsync(ct); + if (mismatched.Count > 0) + throw new DomainException(ErrorCodes.Validation, + $"Warehouse(s) {string.Join(", ", mismatched)} do not belong to this purchase order's branch.", 422); + } + private static async Task EnsureAllExistAsync( IQueryable keySource, IEnumerable requested, string label, CancellationToken ct) { @@ -271,8 +329,8 @@ public sealed class PurchaseOrderService : IPurchaseOrderService } private static PurchaseOrderDto Map(PurchaseOrder p) => new( - p.PoId, p.DocNo, p.VendorId, p.RequisitionId, p.Status, p.ApprovalRequired, - p.CreatedBy, p.CreatedAt, p.UpdatedAt, ComputeTotals(p.Lines), + p.PoId, p.DocNo, p.VendorId, p.BranchId, p.RequisitionId, p.Status, p.ApprovalRequired, + p.CreatedBy, p.ApprovedBy, p.ApprovedAt, p.CreatedAt, p.UpdatedAt, ComputeTotals(p.Lines), p.Lines.OrderBy(l => l.PoLineId).Select(l => new PoLineDto( l.PoLineId, l.ItemId, l.WarehouseId, l.Qty, l.UnitPrice, l.Tax, l.QtyReceived)).ToList()); } diff --git a/Backend/ERPCore/Services/PurchaseReturnService.cs b/Backend/ERPCore/Services/PurchaseReturnService.cs index 21a5600..d2d2ca7 100644 --- a/Backend/ERPCore/Services/PurchaseReturnService.cs +++ b/Backend/ERPCore/Services/PurchaseReturnService.cs @@ -15,11 +15,15 @@ namespace ERPCore.Services; /// /// Purchase-return service (FR-PROC-08). Auto-posts with a mandatory Return reason -/// code and generates an outbound stock movement via the shared -/// (FIFO consume, row-locked; over-return beyond -/// available → STOCK_NEGATIVE_BLOCKED). Single UoW transaction. Also posts a real GL -/// journal entry reversing the Inventory/Clearing lines the original -/// posted — reuses Grn's own account config since it's reversing that posting. +/// code. A line referencing a Rejected GRN line consumes specifically that +/// line's own FIFO layer(s) — up to whatever quantity is still sitting there — so the +/// stock a GRN reject quarantined is only ever released back to the vendor through a +/// real, auditable document (§3.4); every other line (no GRN line, or one that isn't +/// Rejected) still uses the shared against general on-hand +/// (FIFO consume, row-locked; over-return beyond available → STOCK_NEGATIVE_BLOCKED). +/// Single UoW transaction. Also posts a real GL journal entry reversing the +/// Inventory/Clearing lines the original posted — reuses +/// Grn's own account config since it's reversing that posting. /// public sealed class PurchaseReturnService : IPurchaseReturnService { @@ -29,10 +33,13 @@ public sealed class PurchaseReturnService : IPurchaseReturnService private readonly IRepository _items; private readonly IRepository _reasonCodes; private readonly IRepository _grnLines; + private readonly IRepository _layers; private readonly IRepository _ledger; private readonly IStockMutator _mutator; + private readonly IFifoCostingService _fifo; private readonly INumberSequenceService _numbers; private readonly ICurrentUser _currentUser; + private readonly INotificationService _notifications; private readonly IUnitOfWork _uow; private readonly IGeneralLedgerService _gl; private readonly string _glInventoryAccountCode; @@ -41,8 +48,9 @@ public sealed class PurchaseReturnService : IPurchaseReturnService public PurchaseReturnService( IRepository returns, IRepository vendors, IRepository warehouses, IRepository items, IRepository reasonCodes, IRepository grnLines, - IRepository ledger, IStockMutator mutator, INumberSequenceService numbers, - ICurrentUser currentUser, IUnitOfWork uow, IGeneralLedgerService gl, IConfiguration configuration) + IRepository layers, IRepository ledger, IStockMutator mutator, IFifoCostingService fifo, + INumberSequenceService numbers, ICurrentUser currentUser, INotificationService notifications, + IUnitOfWork uow, IGeneralLedgerService gl, IConfiguration configuration) { _returns = returns; _vendors = vendors; @@ -50,10 +58,13 @@ public sealed class PurchaseReturnService : IPurchaseReturnService _items = items; _reasonCodes = reasonCodes; _grnLines = grnLines; + _layers = layers; _ledger = ledger; _mutator = mutator; + _fifo = fifo; _numbers = numbers; _currentUser = currentUser; + _notifications = notifications; _uow = uow; _gl = gl; _glInventoryAccountCode = configuration["Grn:GlInventoryAccountCode"] ?? string.Empty; @@ -116,6 +127,11 @@ public sealed class PurchaseReturnService : IPurchaseReturnService if (reason.Context != ReasonContext.Return) throw new DomainException(ErrorCodes.Validation, $"Reason code {request.ReasonCodeId} is not a Return reason.", 422); + // Lines that reference a Rejected GRN line are resolved against that line's own + // layer(s) below, not the generic mutator — track which by GrnLineId so the two + // paths don't double-handle the same line. + var rejectedGrnLineIds = new HashSet(); + foreach (var line in request.Lines) { if (!await _items.Query().AnyAsync(i => i.ItemId == line.ItemId, ct)) @@ -126,11 +142,25 @@ public sealed class PurchaseReturnService : IPurchaseReturnService ?? throw new DomainException(ErrorCodes.Validation, $"GRN line {line.GrnLineId} does not exist.", 422); if (grnLine.ItemId != line.ItemId) throw new DomainException(ErrorCodes.Validation, $"GRN line {line.GrnLineId} is for a different item.", 422); + + if (grnLine.HoldStatus == HoldStatus.Rejected) + { + var remaining = await _layers.Query().AsNoTracking() + .Where(l => l.GrnLineId == line.GrnLineId).SumAsync(l => (decimal?)l.QtyRemaining, ct) ?? 0m; + if (line.Qty > remaining) + throw new DomainException(ErrorCodes.ReturnQtyExceedsRejected, + $"GRN line {line.GrnLineId} has {remaining} rejected unit(s) left to return, but {line.Qty} was requested.", 422); + rejectedGrnLineIds.Add(line.GrnLineId.Value); + } } } var now = DateTime.UtcNow; - var deltas = request.Lines.Select(l => new StockDelta(l.ItemId, null, null, -l.Qty)).ToList(); + var actor = _currentUser.AuditUserId; + var deltas = request.Lines + .Where(l => l.GrnLineId is null || !rejectedGrnLineIds.Contains(l.GrnLineId.Value)) + .Select(l => new StockDelta(l.ItemId, null, null, -l.Qty)).ToList(); + var rejectedLines = request.Lines.Where(l => l.GrnLineId is not null && rejectedGrnLineIds.Contains(l.GrnLineId.Value)).ToList(); var (entity, ledgerEntries) = await _uow.ExecuteInTransactionAsync(async token => { @@ -154,7 +184,38 @@ public sealed class PurchaseReturnService : IPurchaseReturnService await _returns.AddAsync(ret, token); await _uow.SaveChangesAsync(token); // flush for a valid ledger sourceDocId - var refs = await _mutator.ApplyAsync(request.WarehouseId, DocumentTypes.PurchaseReturn, ret.ReturnId, now, deltas, token); + var refs = new List(await _mutator.ApplyAsync(request.WarehouseId, DocumentTypes.PurchaseReturn, ret.ReturnId, now, deltas, token)); + + // Rejected-GRN-line returns: consume oldest-first from that exact line's own + // layer(s) only — never the item's general on-hand — so cost and quarantine + // status stay tied to the receipt that was actually rejected. + var balances = new Dictionary(); + foreach (var line in rejectedLines) + { + var layers = await _layers.Query() + .Where(l => l.GrnLineId == line.GrnLineId && l.QtyRemaining > 0) + .OrderBy(l => l.ReceiptDate).ThenBy(l => l.LayerId) + .ToListAsync(token); + + if (!balances.TryGetValue(line.ItemId, out var bal)) + bal = await _fifo.GetOnHandAsync(line.ItemId, request.WarehouseId, token); + + var remaining = line.Qty; + foreach (var layer in layers) + { + if (remaining <= 0) break; + var take = Math.Min(remaining, layer.QtyRemaining); + layer.QtyRemaining -= take; + remaining -= take; + bal -= take; + + var entry = await _fifo.PostLedgerAsync( + layer.ItemId, layer.WarehouseId, null, layer.BatchId, null, actor, + Direction.Out, take, layer.UnitCost, bal, DocumentTypes.PurchaseReturn, ret.ReturnId, now, token); + refs.Add(entry); + } + balances[line.ItemId] = bal; + } var totalValue = refs.Sum(r => r.Value); if (totalValue > 0) @@ -180,6 +241,8 @@ public sealed class PurchaseReturnService : IPurchaseReturnService return (ret, refs); }, ct); + await _notifications.RaiseAsync("purchase.return.created", "Purchase Return Created", $"Purchase return {entity.DocNo} was created.", nameof(PurchaseReturn), entity.ReturnId, ct); + // Map ledger ids after commit so they are populated. return ToDto(entity, ledgerEntries.Select(r => r.LedgerId).ToList()); } diff --git a/Backend/ERPCore/Services/RequisitionService.cs b/Backend/ERPCore/Services/RequisitionService.cs index d8086a6..9ea01bc 100644 --- a/Backend/ERPCore/Services/RequisitionService.cs +++ b/Backend/ERPCore/Services/RequisitionService.cs @@ -18,16 +18,18 @@ public sealed class RequisitionService : IRequisitionService private readonly IRepository _items; private readonly INumberSequenceService _numbers; private readonly ICurrentUser _currentUser; + private readonly IBranchConfigService _branchConfig; private readonly IUnitOfWork _uow; public RequisitionService( IRepository requisitions, IRepository items, - INumberSequenceService numbers, ICurrentUser currentUser, IUnitOfWork uow) + INumberSequenceService numbers, ICurrentUser currentUser, IBranchConfigService branchConfig, IUnitOfWork uow) { _requisitions = requisitions; _items = items; _numbers = numbers; _currentUser = currentUser; + _branchConfig = branchConfig; _uow = uow; } @@ -46,7 +48,7 @@ public sealed class RequisitionService : IRequisitionService var rows = await q.OrderByDescending(r => r.RequisitionId) .Skip(query.Skip).Take(query.PageSize) .Select(r => new RequisitionSummaryDto( - r.RequisitionId, r.DocNo, r.Status, r.RequestedBy, r.CreatedAt, r.Lines.Count)) + r.RequisitionId, r.DocNo, r.Status, r.RequestedBy, r.BranchId, r.CreatedAt, r.Lines.Count)) .ToListAsync(ct); return PagedResponse.Create(rows, query.Page, query.PageSize, total); @@ -64,14 +66,16 @@ public sealed class RequisitionService : IRequisitionService { await EnsureItemsExistAsync(request.Lines.Select(l => l.ItemId), ct); var actor = _currentUser.AuditUserId; + var branchId = await _branchConfig.ResolveBranchIdAsync(request.BranchId, ct); var req = await _uow.ExecuteInTransactionAsync(async token => { - var docNo = await _numbers.NextAsync(DocumentTypes.Requisition, token); + var docNo = await _numbers.NextAsync(DocumentTypes.Requisition, branchId, token); var entity = new Requisition { DocNo = docNo, RequestedBy = actor, + BranchId = branchId, Status = RequisitionStatus.Draft, CreatedAt = DateTime.UtcNow, Lines = request.Lines.Select(l => new RequisitionLine @@ -115,7 +119,7 @@ public sealed class RequisitionService : IRequisitionService } private static RequisitionDto Map(Requisition r) => new( - r.RequisitionId, r.DocNo, r.Status, r.RequestedBy, r.CreatedAt, + r.RequisitionId, r.DocNo, r.Status, r.RequestedBy, r.BranchId, r.CreatedAt, r.Lines.OrderBy(l => l.ReqLineId) .Select(l => new RequisitionLineDto(l.ReqLineId, l.ItemId, l.Qty, l.RequiredBy)) .ToList()); diff --git a/Backend/ERPCore/Services/RfqService.cs b/Backend/ERPCore/Services/RfqService.cs index 2072565..785a887 100644 --- a/Backend/ERPCore/Services/RfqService.cs +++ b/Backend/ERPCore/Services/RfqService.cs @@ -51,7 +51,7 @@ public sealed class RfqService : IRfqService var rows = await q.OrderByDescending(r => r.RfqId) .Skip(query.Skip).Take(query.PageSize) .Select(r => new RfqSummaryDto( - r.RfqId, r.DocNo, r.RequisitionId, r.Status, + r.RfqId, r.DocNo, r.RequisitionId, r.BranchId, r.Status, r.Lines.Count, // Correlated subquery: there is no Rfq.Quotations navigation to count. _quotations.Query().Count(qt => qt.RfqId == r.RfqId))) @@ -70,19 +70,27 @@ public sealed class RfqService : IRfqService public async Task CreateAsync(CreateRfqRequest request, CancellationToken ct = default) { - if (!await _requisitions.Query().AnyAsync(r => r.RequisitionId == request.RequisitionId, ct)) - throw new DomainException(ErrorCodes.Validation, $"Requisition {request.RequisitionId} does not exist.", 422); + var requisitionBranchId = await _requisitions.Query().AsNoTracking() + .Where(r => r.RequisitionId == request.RequisitionId) + .Select(r => (int?)r.BranchId) + .FirstOrDefaultAsync(ct) + ?? throw new DomainException(ErrorCodes.Validation, $"Requisition {request.RequisitionId} does not exist.", 422); await EnsureItemsExistAsync(request.Lines.Select(l => l.ItemId), ct); await EnsureVendorsExistAsync(request.VendorIds, ct); var rfq = await _uow.ExecuteInTransactionAsync(async token => { - var docNo = await _numbers.NextAsync(DocumentTypes.Rfq, token); + // An RFQ is raised from a Requisition and inherits its branch — a PO's branch + // span is constrained to one branch (docs/BRANCH_ISOLATION_PLAN.md §1), and + // keeping the RFQ on the same branch as its source requisition keeps that chain + // consistent end to end. + var docNo = await _numbers.NextAsync(DocumentTypes.Rfq, requisitionBranchId, token); var entity = new Rfq { DocNo = docNo, RequisitionId = request.RequisitionId, + BranchId = requisitionBranchId, Status = RfqStatus.Open, CreatedAt = DateTime.UtcNow, Lines = request.Lines.Select(l => new RfqLine { ItemId = l.ItemId, Qty = l.Qty }).ToList() @@ -178,6 +186,6 @@ public sealed class RfqService : IRfqService } private static RfqDto MapRfq(Rfq r) => new( - r.RfqId, r.DocNo, r.RequisitionId, r.Status, + r.RfqId, r.DocNo, r.RequisitionId, r.BranchId, r.Status, r.Lines.OrderBy(l => l.RfqLineId).Select(l => new RfqLineDto(l.RfqLineId, l.ItemId, l.Qty)).ToList()); } diff --git a/Backend/ERPCore/Services/RoleService.cs b/Backend/ERPCore/Services/RoleService.cs index 5092a46..4197088 100644 --- a/Backend/ERPCore/Services/RoleService.cs +++ b/Backend/ERPCore/Services/RoleService.cs @@ -158,13 +158,15 @@ public sealed class RoleService : IRoleService var granted = await _rolePermissions.Query().AsNoTracking() .Where(rp => rp.RoleId == roleId) .Include(rp => rp.Permission) - .Select(rp => rp.Permission!) + .Select(rp => new { rp.Actions, rp.Permission!.NavItemId, rp.Permission!.SubNavItemId }) .ToListAsync(ct); return new RolePermissionsDto( roleId, granted.Where(p => p.NavItemId is not null).Select(p => p.NavItemId!.Value).ToList(), - granted.Where(p => p.SubNavItemId is not null).Select(p => p.SubNavItemId!.Value).ToList()); + granted.Where(p => p.SubNavItemId is not null).Select(p => p.SubNavItemId!.Value).ToList(), + granted.Where(p => p.NavItemId is not null).ToDictionary(p => p.NavItemId!.Value, p => p.Actions), + granted.Where(p => p.SubNavItemId is not null).ToDictionary(p => p.SubNavItemId!.Value, p => p.Actions)); } public async Task AssignPermissionsAsync(int roleId, AssignRolePermissionsRequest request, CancellationToken ct = default) @@ -177,14 +179,22 @@ public sealed class RoleService : IRoleService var navIds = request.NavItemIds.Distinct().ToList(); var subNavIds = request.SubNavItemIds.Distinct().ToList(); - var permissionIds = await _permissions.Query().AsNoTracking() + var permissions = await _permissions.Query().AsNoTracking() .Where(p => (p.NavItemId != null && navIds.Contains(p.NavItemId.Value)) || (p.SubNavItemId != null && subNavIds.Contains(p.SubNavItemId.Value))) - .Select(p => p.PermissionId) .ToListAsync(ct); - foreach (var permissionId in permissionIds) - await _rolePermissions.AddAsync(new RolePermission { RoleId = roleId, PermissionId = permissionId }, ct); + foreach (var permission in permissions) + { + var actions = permission.NavItemId is int navId && request.NavItemActions.TryGetValue(navId, out var navActions) + ? navActions + : permission.SubNavItemId is int subNavId && request.SubNavItemActions.TryGetValue(subNavId, out var subNavActions) + ? subNavActions + : RolePermissionAction.All; + + await _rolePermissions.AddAsync( + new RolePermission { RoleId = roleId, PermissionId = permission.PermissionId, Actions = actions }, ct); + } await _uow.SaveChangesAsync(ct); @@ -204,9 +214,10 @@ public sealed class RoleService : IRoleService var branchId = employee?.BranchId; var branchName = employee?.Branch?.Name; var branchingEnabled = await _branchConfig.IsBranchingEnabledAsync(ct); + var warehouseBranchingEnabled = await _branchConfig.IsWarehouseBranchingEnabledAsync(ct); if (string.IsNullOrWhiteSpace(roleCode)) - return new MeResponseDto(null, null, Array.Empty(), false, branchId, branchName, branchingEnabled); + return new MeResponseDto(null, null, Array.Empty(), false, branchId, branchName, branchingEnabled, warehouseBranchingEnabled); // AuthHex mints the RoleCode claim independently of ERPCore's stored casing // (e.g. token "ADMIN" vs seeded "Admin"), so match case-insensitively — an @@ -216,7 +227,7 @@ public sealed class RoleService : IRoleService var role = await _roles.Query().AsNoTracking() .FirstOrDefaultAsync(r => r.Code.ToLower() == normalized.ToLower(), ct); if (role is null) - return new MeResponseDto(roleCode, null, Array.Empty(), isAdmin, branchId, branchName, branchingEnabled); + return new MeResponseDto(roleCode, null, Array.Empty(), isAdmin, branchId, branchName, branchingEnabled, warehouseBranchingEnabled); var permissions = await _rolePermissions.Query().AsNoTracking() .Where(rp => rp.RoleId == role.RoleId) @@ -232,7 +243,7 @@ public sealed class RoleService : IRoleService .Distinct() .ToList(); - return new MeResponseDto(role.Code, role.Name, navCodes, isAdmin, branchId, branchName, branchingEnabled); + return new MeResponseDto(role.Code, role.Name, navCodes, isAdmin, branchId, branchName, branchingEnabled, warehouseBranchingEnabled); } private static RoleDto Map(Role r) => new( diff --git a/Backend/ERPCore/Services/SalesDayEndService.cs b/Backend/ERPCore/Services/SalesDayEndService.cs index b2112e3..41c635b 100644 --- a/Backend/ERPCore/Services/SalesDayEndService.cs +++ b/Backend/ERPCore/Services/SalesDayEndService.cs @@ -20,10 +20,12 @@ namespace ERPCore.Services; /// rung up individually through the day with no GL impact of their own; /// is the single point where that day's sales become real accounting entries — one consolidated /// journal entry per cashier per day, mirroring how posts per receipt. -/// Every document is treated as a cash sale (Debit Cash for GrandTotal): SalesSlip's -/// PaidAmount/BalanceAmount fields exist for a future partial-payment flow but nothing -/// sets them today (SalesSlipService.CreateAsync always leaves PaidAmount at 0), so -/// they aren't a usable signal here — see docs/14-BACKEND-SALES-API.md if that changes. +/// Each slip's / (set at +/// ring-up time, SalesSlipService.Recalculate) drive the GL split here: Cash is debited only for +/// what was actually collected (PaidTotal), and any remainder (BalanceTotal) goes to Accounts +/// Receivable instead — a slip fully paid at ring-up (the default when PaidAmount is omitted) +/// behaves exactly as before partial payment existed. Bundle sales have no PaidAmount field of +/// their own and are always counted as fully paid, same as every document was before this existed. /// A bundle sale's net revenue is always exactly BundlePrice (GrandTotal - TaxTotal /// by construction, docs/15) regardless of whether the bundle sold at a discount or a premium to /// its component subtotal, so it folds into Subtotal/DiscountTotal the same way a slip's net @@ -47,6 +49,7 @@ public sealed class SalesDayEndService : ISalesDayEndService private readonly string _glTaxPayableAccountCode; private readonly string _glCogsAccountCode; private readonly string _glInventoryAccountCode; + private readonly string _glAccountsReceivableCode; public SalesDayEndService( IRepository dayEnds, IRepository slips, IRepository bundles, @@ -69,6 +72,7 @@ public sealed class SalesDayEndService : ISalesDayEndService _glTaxPayableAccountCode = configuration["SalesDayEnd:GlTaxPayableAccountCode"] ?? string.Empty; _glCogsAccountCode = configuration["SalesDayEnd:GlCogsAccountCode"] ?? string.Empty; _glInventoryAccountCode = configuration["SalesDayEnd:GlInventoryAccountCode"] ?? string.Empty; + _glAccountsReceivableCode = configuration["SalesDayEnd:GlAccountsReceivableCode"] ?? string.Empty; } public async Task PreviewAsync(int cashierUserId, DateOnly businessDate, CancellationToken ct = default) @@ -92,6 +96,7 @@ public sealed class SalesDayEndService : ISalesDayEndService return new SalesDayEndPreviewDto( cashierUserId, businessDate, true, existing.SlipCount, existing.BundleCount, existing.Subtotal, existing.DiscountTotal, existing.TaxTotal, existing.GrandTotal, + existing.PaidTotal, existing.BalanceTotal, closedSlipNumbers, closedBundleNumbers, Array.Empty(), Array.Empty(), invoiceSummary); } @@ -108,10 +113,15 @@ public sealed class SalesDayEndService : ISalesDayEndService var discountTotal = postedSlips.Sum(x => x.DiscountTotal); var taxTotal = postedSlips.Sum(x => x.TaxTotal) + postedBundles.Sum(x => x.TaxTotal); var grandTotal = postedSlips.Sum(x => x.GrandTotal) + postedBundles.Sum(x => x.GrandTotal); + // Bundle sales have no PaidAmount field — always counted fully paid, same as every + // document before partial payment existed. + var paidTotal = postedSlips.Sum(x => x.PaidAmount) + postedBundles.Sum(x => x.GrandTotal); + var balanceTotal = postedSlips.Sum(x => x.BalanceAmount); return new SalesDayEndPreviewDto( cashierUserId, businessDate, false, postedSlips.Count, postedBundles.Count, subtotal, discountTotal, taxTotal, grandTotal, + paidTotal, balanceTotal, postedSlips.OrderBy(x => x.SlipNo).Select(x => x.SlipNo).ToList(), postedBundles.OrderBy(x => x.BundleNo).Select(x => x.BundleNo).ToList(), draftSlips.OrderBy(x => x.SlipNo).Select(x => new DraftSlipBlockingCloseDto(x.SalesSlipId, x.SlipNo, x.GrandTotal)).ToList(), @@ -155,6 +165,8 @@ public sealed class SalesDayEndService : ISalesDayEndService var discountTotal = postedSlips.Sum(x => x.DiscountTotal); var taxTotal = postedSlips.Sum(x => x.TaxTotal) + postedBundles.Sum(x => x.TaxTotal); var grandTotal = postedSlips.Sum(x => x.GrandTotal) + postedBundles.Sum(x => x.GrandTotal); + var paidTotal = postedSlips.Sum(x => x.PaidAmount) + postedBundles.Sum(x => x.GrandTotal); + var balanceTotal = postedSlips.Sum(x => x.BalanceAmount); var slipIds = postedSlips.Select(x => x.SalesSlipId).ToList(); var bundleIds = postedBundles.Select(x => x.BundleSaleId).ToList(); @@ -185,6 +197,8 @@ public sealed class SalesDayEndService : ISalesDayEndService DiscountTotal = discountTotal, TaxTotal = taxTotal, GrandTotal = grandTotal, + PaidTotal = paidTotal, + BalanceTotal = balanceTotal, CostOfGoodsSold = cogs, ClosedBy = _currentUser.AuditUserId, ClosedAt = now @@ -196,7 +210,10 @@ public sealed class SalesDayEndService : ISalesDayEndService var glLines = new List(); if (grandTotal > 0) { - glLines.Add(new GlJournalEntryLineRequest(_glCashAccountCode, grandTotal, 0m, $"Day-end {businessDate:yyyy-MM-dd} cashier {request.CashierUserId} — cash collected")); + if (paidTotal > 0) + glLines.Add(new GlJournalEntryLineRequest(_glCashAccountCode, paidTotal, 0m, $"Day-end {businessDate:yyyy-MM-dd} cashier {request.CashierUserId} — cash collected")); + if (balanceTotal > 0) + glLines.Add(new GlJournalEntryLineRequest(_glAccountsReceivableCode, balanceTotal, 0m, $"Day-end {businessDate:yyyy-MM-dd} cashier {request.CashierUserId} — sold on account")); if (discountTotal > 0) glLines.Add(new GlJournalEntryLineRequest(_glSalesDiscountAccountCode, discountTotal, 0m, "Sales discount")); glLines.Add(new GlJournalEntryLineRequest(_glSalesRevenueAccountCode, 0m, subtotal, "Sales revenue")); @@ -244,7 +261,7 @@ public sealed class SalesDayEndService : ISalesDayEndService var total = await q.CountAsync(ct); var rows = await q.OrderByDescending(x => x.SalesDayEndId).Skip(query.Skip).Take(query.PageSize).ToListAsync(ct); var items = rows.Select(x => new SalesDayEndSummaryDto( - x.SalesDayEndId, x.DocNo, x.CashierUserId, x.BusinessDate, x.SlipCount, x.BundleCount, x.GrandTotal, x.GlJournalNo, x.ClosedAt)).ToList(); + x.SalesDayEndId, x.DocNo, x.CashierUserId, x.BusinessDate, x.SlipCount, x.BundleCount, x.GrandTotal, x.PaidTotal, x.BalanceTotal, x.GlJournalNo, x.ClosedAt)).ToList(); return PagedResponse.Create(items, query.Page, query.PageSize, total); } @@ -339,6 +356,7 @@ public sealed class SalesDayEndService : ISalesDayEndService return new SalesDayEndDto( entity.SalesDayEndId, entity.DocNo, entity.CashierUserId, entity.BusinessDate, entity.SlipCount, entity.BundleCount, entity.Subtotal, entity.DiscountTotal, entity.TaxTotal, entity.GrandTotal, + entity.PaidTotal, entity.BalanceTotal, entity.CostOfGoodsSold, entity.GlJournalNo, entity.GlPostedAt, entity.ClosedBy, entity.ClosedAt, slipNumbers, bundleNumbers, breakdown, invoiceSummary); } diff --git a/Backend/ERPCore/Services/SalesDomainService.cs b/Backend/ERPCore/Services/SalesDomainService.cs index 646ba12..6c85d1b 100644 --- a/Backend/ERPCore/Services/SalesDomainService.cs +++ b/Backend/ERPCore/Services/SalesDomainService.cs @@ -13,6 +13,7 @@ public sealed class SalesDomainService : ISalesDomainService private readonly IRepository _warehouses; private readonly IRepository _users; private readonly IRepository _items; + private readonly IRepository _taxRates; private readonly ISalesPricingService _pricing; public SalesDomainService( @@ -20,12 +21,14 @@ public sealed class SalesDomainService : ISalesDomainService IRepository warehouses, IRepository users, IRepository items, + IRepository taxRates, ISalesPricingService pricing) { _customers = customers; _warehouses = warehouses; _users = users; _items = items; + _taxRates = taxRates; _pricing = pricing; } @@ -64,6 +67,22 @@ public sealed class SalesDomainService : ISalesDomainService public Task ResolveLinePriceAsync(int itemId, int warehouseId, decimal? requestedUnitPrice, bool allowManualOverride, CancellationToken ct = default) => _pricing.ResolveAsync(itemId, warehouseId, requestedUnitPrice, allowManualOverride, ct); + public async Task ResolveLineTaxPctAsync(int itemId, decimal? requestedTaxPct, CancellationToken ct = default) + { + if (requestedTaxPct is not null) return requestedTaxPct.Value; + + var taxRateId = await _items.Query().AsNoTracking() + .Where(x => x.ItemId == itemId) + .Select(x => x.TaxRateId) + .FirstAsync(ct); + if (taxRateId is null) return 0m; + + return await _taxRates.Query().AsNoTracking() + .Where(t => t.TaxRateId == taxRateId) + .Select(t => t.Percentage) + .FirstAsync(ct); + } + public SalesLineComputation ComputeLine( decimal qty, decimal freeQty, diff --git a/Backend/ERPCore/Services/SalesInvoiceService.cs b/Backend/ERPCore/Services/SalesInvoiceService.cs index 99a817f..461f40f 100644 --- a/Backend/ERPCore/Services/SalesInvoiceService.cs +++ b/Backend/ERPCore/Services/SalesInvoiceService.cs @@ -164,8 +164,9 @@ public sealed class SalesInvoiceService : ISalesInvoiceService var resolved = await _sales.ResolveLinePriceAsync(r.ItemId, r.WarehouseId, r.UnitPrice, r.AllowManualPriceOverride, ct); var unitPrice = resolved.UnitPrice; var priceSource = resolved.PriceSource; + var taxPct = await _sales.ResolveLineTaxPctAsync(r.ItemId, r.TaxPct, ct); - var calc = _sales.ComputeLine(r.Qty, r.FreeQty, unitPrice, r.DiscountMode, r.DiscountPct, r.DiscountValue, r.DiscountAmount, r.TaxPct, r.IsFreeIssue); + var calc = _sales.ComputeLine(r.Qty, r.FreeQty, unitPrice, r.DiscountMode, r.DiscountPct, r.DiscountValue, r.DiscountAmount, taxPct, r.IsFreeIssue); lines.Add(new SalesInvoiceLine { @@ -182,7 +183,7 @@ public sealed class SalesInvoiceService : ISalesInvoiceService DiscountMode = r.DiscountMode, NetUnitPrice = calc.NetUnitPrice, LineTotal = calc.LineTotal, - TaxPct = r.TaxPct, + TaxPct = taxPct, TaxAmount = calc.TaxAmount, IsFreeIssue = r.IsFreeIssue, ParentLineId = r.ParentLineId diff --git a/Backend/ERPCore/Services/SalesMappingService.cs b/Backend/ERPCore/Services/SalesMappingService.cs index 4a799c9..bb1d866 100644 --- a/Backend/ERPCore/Services/SalesMappingService.cs +++ b/Backend/ERPCore/Services/SalesMappingService.cs @@ -48,5 +48,6 @@ public sealed class SalesMappingService : ISalesMappingService slip.Lines.Select(l => new SalesSlipLineDto( l.SalesSlipLineId, l.ItemId, l.Description, l.Qty, l.FreeQty, l.WarehouseId, l.UnitPrice, l.BaseCost, l.PriceSource, l.DiscountPct, l.DiscountAmount, l.DiscountMode, - l.NetUnitPrice, l.LineTotal, l.TaxPct, l.TaxAmount, l.IsFreeIssue, l.ParentLineId)).ToList()); + l.NetUnitPrice, l.LineTotal, l.TaxPct, l.TaxAmount, l.IsFreeIssue, l.ParentLineId, + l.BatchId, l.SerialId)).ToList()); } diff --git a/Backend/ERPCore/Services/SalesPostingService.cs b/Backend/ERPCore/Services/SalesPostingService.cs index 2bc867c..4fbd1b2 100644 --- a/Backend/ERPCore/Services/SalesPostingService.cs +++ b/Backend/ERPCore/Services/SalesPostingService.cs @@ -19,6 +19,7 @@ public sealed class SalesPostingService : ISalesPostingService private readonly IRepository _slips; private readonly IRepository _bundles; private readonly IRepository _items; + private readonly IRepository _serials; private readonly IFifoCostingService _fifo; private readonly ISalesDomainService _sales; private readonly ICurrentUser _currentUser; @@ -36,6 +37,7 @@ public sealed class SalesPostingService : ISalesPostingService IRepository slips, IRepository bundles, IRepository items, + IRepository serials, IFifoCostingService fifo, ISalesDomainService sales, ICurrentUser currentUser, @@ -47,6 +49,7 @@ public sealed class SalesPostingService : ISalesPostingService _slips = slips; _bundles = bundles; _items = items; + _serials = serials; _fifo = fifo; _sales = sales; _currentUser = currentUser; @@ -157,7 +160,7 @@ public sealed class SalesPostingService : ISalesPostingService notFoundMessage: $"Sales invoice {salesInvoiceId} was not found.", statusSelector: x => x.Status, ensureDraftMessage: x => $"Sales invoice {x.SalesInvoiceId} is {x.Status} and cannot be posted.", - getLines: x => x.Lines.Select(l => new PostingLine(l.ItemId, l.WarehouseId, l.Qty + l.FreeQty, l.Qty, l.FreeQty)), + getLines: x => x.Lines.Select(l => new PostingLine(l.ItemId, l.WarehouseId, l.Qty + l.FreeQty, l.Qty, l.FreeQty, null, null)), setPosted: x => x.Status = SalesInvoiceStatus.Posted, setUpdated: x => x.UpdatedAt = DateTime.UtcNow, sourceDocType: DocumentTypes.SalesInvoice, @@ -214,7 +217,7 @@ public sealed class SalesPostingService : ISalesPostingService notFoundMessage: $"Sales slip {salesSlipId} was not found.", statusSelector: x => x.Status, ensureDraftMessage: x => $"Sales slip {x.SalesSlipId} is {x.Status} and cannot be posted.", - getLines: x => x.Lines.Select(l => new PostingLine(l.ItemId, l.WarehouseId, l.Qty + l.FreeQty, l.Qty, l.FreeQty)), + getLines: x => x.Lines.Select(l => new PostingLine(l.ItemId, l.WarehouseId, l.Qty + l.FreeQty, l.Qty, l.FreeQty, l.BatchId, l.SerialId)), setPosted: x => x.Status = SalesSlipStatus.Posted, setUpdated: x => x.UpdatedAt = DateTime.UtcNow, sourceDocType: DocumentTypes.SalesSlip, @@ -227,7 +230,7 @@ public sealed class SalesPostingService : ISalesPostingService notFoundMessage: $"Bundle sale {bundleSaleId} was not found.", statusSelector: x => x.Status, ensureDraftMessage: x => $"Bundle sale {x.BundleSaleId} is {x.Status} and cannot be posted.", - getLines: x => x.Lines.Where(l => l.IncludeInBundle).Select(l => new PostingLine(l.ItemId, l.WarehouseId, l.Qty, l.Qty, 0m)), + getLines: x => x.Lines.Where(l => l.IncludeInBundle).Select(l => new PostingLine(l.ItemId, l.WarehouseId, l.Qty, l.Qty, 0m, null, null)), setPosted: x => x.Status = BundleSaleStatus.Posted, setUpdated: x => x.UpdatedAt = DateTime.UtcNow, sourceDocType: DocumentTypes.BundleSale, @@ -268,11 +271,19 @@ public sealed class SalesPostingService : ISalesPostingService // Line quantities are already a count of the item's base UOM — sales documents // carry no unit of their own — so this is the quantity FIFO consumes verbatim. - var consumed = await _fifo.ConsumeAsync(line.ItemId, line.WarehouseId, null, line.Qty, token); + var consumed = await _fifo.ConsumeAsync(line.ItemId, line.WarehouseId, line.BatchId, line.Qty, token); var cost = consumed.Count == 0 ? 0m : consumed.Sum(x => x.Qty * x.UnitCost) / consumed.Sum(x => x.Qty); totalCogs += cost * line.Qty; - await _fifo.PostLedgerAsync(line.ItemId, line.WarehouseId, null, null, null, _currentUser.AuditUserId, + await _fifo.PostLedgerAsync(line.ItemId, line.WarehouseId, null, line.BatchId, line.SerialId, _currentUser.AuditUserId, Direction.Out, line.Qty, cost, 0m, sourceDocType, getDocId(doc), DateTime.UtcNow, token); + + // ConsumeAsync has no serial parameter — closing the loop on a serial-pinned + // line means flipping the serial's own status once its stock is actually gone. + if (line.SerialId.HasValue) + { + var serial = await _serials.Query().FirstOrDefaultAsync(s => s.SerialId == line.SerialId, token); + if (serial is not null) serial.Status = "Sold"; + } } setPosted(doc); @@ -282,5 +293,5 @@ public sealed class SalesPostingService : ISalesPostingService }, ct); } - private sealed record PostingLine(int ItemId, int WarehouseId, decimal Qty, decimal PaidQty, decimal FreeQty); + private sealed record PostingLine(int ItemId, int WarehouseId, decimal Qty, decimal PaidQty, decimal FreeQty, int? BatchId, int? SerialId); } diff --git a/Backend/ERPCore/Services/SalesSlipService.cs b/Backend/ERPCore/Services/SalesSlipService.cs index dcc9e8b..24a46e5 100644 --- a/Backend/ERPCore/Services/SalesSlipService.cs +++ b/Backend/ERPCore/Services/SalesSlipService.cs @@ -23,19 +23,23 @@ public sealed class SalesSlipService : ISalesSlipService private readonly IRepository _uoms; private readonly IRepository _warehouses; private readonly IRepository _users; + private readonly IRepository _batches; + private readonly IRepository _serials; private readonly ISalesDomainService _sales; private readonly ISalesPostingService _posting; private readonly ISalesMappingService _mapping; private readonly ISalesDocumentWorkflowService _workflow; private readonly ICurrentUser _currentUser; private readonly INumberSequenceService _numbers; + private readonly INotificationService _notifications; private readonly IUnitOfWork _uow; public SalesSlipService( IRepository slips, IRepository dayEnds, IRepository customers, IRepository items, - IRepository uoms, IRepository warehouses, IRepository users, ISalesDomainService sales, ISalesPostingService posting, ISalesMappingService mapping, + IRepository uoms, IRepository warehouses, IRepository users, IRepository batches, IRepository serials, + ISalesDomainService sales, ISalesPostingService posting, ISalesMappingService mapping, ISalesDocumentWorkflowService workflow, - ICurrentUser currentUser, INumberSequenceService numbers, IUnitOfWork uow) + ICurrentUser currentUser, INumberSequenceService numbers, INotificationService notifications, IUnitOfWork uow) { _slips = slips; _dayEnds = dayEnds; @@ -44,12 +48,15 @@ public sealed class SalesSlipService : ISalesSlipService _uoms = uoms; _warehouses = warehouses; _users = users; + _batches = batches; + _serials = serials; _sales = sales; _posting = posting; _mapping = mapping; _workflow = workflow; _currentUser = currentUser; _numbers = numbers; + _notifications = notifications; _uow = uow; } @@ -135,11 +142,13 @@ public sealed class SalesSlipService : ISalesSlipService CreatedAt = DateTime.UtcNow, Lines = lines }; - Recalculate(entity); + Recalculate(entity, request.PaidAmount); await _slips.AddAsync(entity, token); return entity; }, ct); + await _notifications.RaiseAsync("sale.create", "Sale Created", $"Sales slip {slip.SlipNo} was created.", nameof(SalesSlip), slip.SalesSlipId, ct); + return new ETagged(_mapping.MapSlip(slip), slip.RowVersion); } @@ -154,7 +163,7 @@ public sealed class SalesSlipService : ISalesSlipService slip.CustomerSnapshotName = await _customers.Query().Where(x => x.CustomerId == request.CustomerId).Select(x => x.DisplayName ?? x.Name).FirstAsync(ct); slip.Lines.Clear(); foreach (var line in await BuildLinesAsync(request.WarehouseId, request.Lines, ct)) slip.Lines.Add(line); - Recalculate(slip); + Recalculate(slip, request.PaidAmount); slip.UpdatedAt = DateTime.UtcNow; await _uow.SaveChangesAsync(ct); return new ETagged(_mapping.MapSlip(slip), slip.RowVersion); @@ -165,6 +174,7 @@ public sealed class SalesSlipService : ISalesSlipService await _posting.PostSlipAsync(salesSlipId, ct); var slip = await _slips.Query().AsNoTracking().Include(x => x.Lines) .FirstAsync(x => x.SalesSlipId == salesSlipId, ct); + await _notifications.RaiseAsync("sale.posted", "Sale Posted", $"Sales slip {slip.SlipNo} was posted.", nameof(SalesSlip), slip.SalesSlipId, ct); return _mapping.MapSlip(slip); } @@ -190,8 +200,14 @@ public sealed class SalesSlipService : ISalesSlipService var resolved = await _sales.ResolveLinePriceAsync(r.ItemId, r.WarehouseId, r.UnitPrice, r.AllowManualPriceOverride, ct); var unitPrice = resolved.UnitPrice; var priceSource = resolved.PriceSource; + var taxPct = await _sales.ResolveLineTaxPctAsync(r.ItemId, r.TaxPct, ct); - var calc = _sales.ComputeLine(r.Qty, r.FreeQty, unitPrice, r.DiscountMode, r.DiscountPct, r.DiscountValue, r.DiscountAmount, r.TaxPct, r.IsFreeIssue); + var calc = _sales.ComputeLine(r.Qty, r.FreeQty, unitPrice, r.DiscountMode, r.DiscountPct, r.DiscountValue, r.DiscountAmount, taxPct, r.IsFreeIssue); + + if (r.BatchId is not null && !await _batches.Query().AnyAsync(b => b.BatchId == r.BatchId && b.ItemId == r.ItemId, ct)) + throw new DomainException(ErrorCodes.Validation, $"Batch {r.BatchId} does not belong to item {r.ItemId}.", 422); + if (r.SerialId is not null && !await _serials.Query().AnyAsync(s => s.SerialId == r.SerialId && s.ItemId == r.ItemId, ct)) + throw new DomainException(ErrorCodes.Validation, $"Serial {r.SerialId} does not belong to item {r.ItemId}.", 422); lines.Add(new SalesSlipLine { @@ -200,6 +216,8 @@ public sealed class SalesSlipService : ISalesSlipService Qty = r.Qty, FreeQty = r.FreeQty, WarehouseId = r.WarehouseId, + BatchId = r.BatchId, + SerialId = r.SerialId, UnitPrice = unitPrice, BaseCost = unitPrice, PriceSource = priceSource, @@ -208,7 +226,7 @@ public sealed class SalesSlipService : ISalesSlipService DiscountAmount = calc.DiscountTotal, NetUnitPrice = calc.NetUnitPrice, LineTotal = calc.LineTotal, - TaxPct = r.TaxPct, + TaxPct = taxPct, TaxAmount = calc.TaxAmount, IsFreeIssue = r.IsFreeIssue, ParentLineId = r.ParentLineId @@ -217,14 +235,27 @@ public sealed class SalesSlipService : ISalesSlipService return lines; } - private static void Recalculate(SalesSlip slip) + /// + /// null defaults to fully paid (PaidAmount == + /// GrandTotal, BalanceAmount == 0) — the behavior every slip had before partial payment + /// existed, so omitting it is a no-op change. Must be clamped against the just-recomputed + /// GrandTotal, not the request's own line totals, since GrandTotal is only known after + /// lines are summed here. + /// + private static void Recalculate(SalesSlip slip, decimal? requestedPaidAmount) { slip.Subtotal = slip.Lines.Sum(x => x.Qty * x.UnitPrice); slip.DiscountTotal = slip.Lines.Sum(x => x.DiscountAmount); slip.TaxTotal = slip.Lines.Sum(x => x.TaxAmount); slip.GrandTotal = slip.Lines.Sum(x => x.LineTotal) + slip.TaxTotal; - slip.PaidAmount = 0m; - slip.BalanceAmount = slip.GrandTotal - slip.PaidAmount; + + var paid = requestedPaidAmount ?? slip.GrandTotal; + if (paid < 0 || paid > slip.GrandTotal) + throw new DomainException(ErrorCodes.SalesSlipPaidAmountInvalid, + $"paidAmount must be between 0 and the slip's total {slip.GrandTotal}.", 400); + + slip.PaidAmount = paid; + slip.BalanceAmount = slip.GrandTotal - paid; } private SalesSlipSummaryDto MapSummary(SalesSlip x) => new( @@ -280,7 +311,7 @@ public sealed class SalesSlipService : ISalesSlipService x.CreatedAt, x.UpdatedAt, summary, - x.Lines.Select(l => new SalesSlipLineDto(l.SalesSlipLineId, l.ItemId, l.Description, l.Qty, l.FreeQty, l.WarehouseId, l.UnitPrice, l.BaseCost, l.PriceSource, l.DiscountPct, l.DiscountAmount, l.DiscountMode, l.NetUnitPrice, l.LineTotal, l.TaxPct, l.TaxAmount, l.IsFreeIssue, l.ParentLineId)).ToList()); + x.Lines.Select(l => new SalesSlipLineDto(l.SalesSlipLineId, l.ItemId, l.Description, l.Qty, l.FreeQty, l.WarehouseId, l.UnitPrice, l.BaseCost, l.PriceSource, l.DiscountPct, l.DiscountAmount, l.DiscountMode, l.NetUnitPrice, l.LineTotal, l.TaxPct, l.TaxAmount, l.IsFreeIssue, l.ParentLineId, l.BatchId, l.SerialId)).ToList()); } private SalesSlipDto Map(SalesSlip x) => _mapping.MapSlip(x); diff --git a/Backend/ERPCore/Services/Stock/FifoCostingService.cs b/Backend/ERPCore/Services/Stock/FifoCostingService.cs index c2f5d23..5eecbea 100644 --- a/Backend/ERPCore/Services/Stock/FifoCostingService.cs +++ b/Backend/ERPCore/Services/Stock/FifoCostingService.cs @@ -3,6 +3,7 @@ using ERPCore.Domain.Enums; using ERPCore.Dtos.Stock; using ERPCore.Infra.Persistence; using ERPCore.Repositories.Interfaces; +using ERPCore.Services.Gl; using ERPCore.Services.Interfaces; using ERPCore.System.Errors; using Microsoft.EntityFrameworkCore; @@ -19,23 +20,26 @@ public sealed class FifoCostingService : IFifoCostingService public const string BaseCurrency = "LKR"; public const string Method = "FIFO"; - // Phase-1 placeholder GL accounts (data only, no posting — FR-STK-13). - private const string InventoryAccount = "1300"; - private const string ClearingAccount = "2100"; - private readonly IRepository _layers; private readonly IRepository _ledger; private readonly IRepository _journal; private readonly ErpDbContext _db; + private readonly IGeneralLedgerService _gl; + private readonly string _glInventoryAccountCode; + private readonly string _glClearingAccountCode; public FifoCostingService( IRepository layers, IRepository ledger, - IRepository journal, ErpDbContext db) + IRepository journal, ErpDbContext db, + IGeneralLedgerService gl, IConfiguration configuration) { _layers = layers; _ledger = ledger; _journal = journal; _db = db; + _gl = gl; + _glInventoryAccountCode = configuration["Fifo:GlInventoryAccountCode"] ?? string.Empty; + _glClearingAccountCode = configuration["Fifo:GlClearingAccountCode"] ?? string.Empty; } public async Task CreateInboundLayerAsync( @@ -73,8 +77,10 @@ public sealed class FifoCostingService : IFifoCostingService } // Row-lock the issuable open layers oldest-first (SELECT … FOR UPDATE, NFR-02). - // Excludes on-hold (grn line) and expired-batch stock. No LINQ is composed on - // top of the raw SQL so the FOR UPDATE reaches the database intact. + // Excludes on-hold and rejected (grn line) and expired-batch stock — rejected stock + // sits quarantined until a Purchase Return consumes it directly (see + // PurchaseReturnService), never through this general-issue path. No LINQ is + // composed on top of the raw SQL so the FOR UPDATE reaches the database intact. // {batchId}::bigint casts give Npgsql an explicit type for the (possibly null) // parameter — without it a null batch filter fails with 42P18. var layers = await _db.StockLayers @@ -82,7 +88,7 @@ public sealed class FifoCostingService : IFifoCostingService SELECT * FROM stock_layers sl WHERE sl."ItemId" = {itemId} AND sl."WarehouseId" = {warehouseId} AND sl."QtyRemaining" > 0 AND ({batchId}::bigint IS NULL OR sl."BatchId" = {batchId}::bigint) - AND NOT EXISTS (SELECT 1 FROM grn_lines gl WHERE gl."GrnLineId" = sl."GrnLineId" AND gl."HoldStatus" = 'OnHold') + AND NOT EXISTS (SELECT 1 FROM grn_lines gl WHERE gl."GrnLineId" = sl."GrnLineId" AND gl."HoldStatus" IN ('OnHold', 'Rejected')) AND NOT EXISTS (SELECT 1 FROM batches b WHERE b."BatchId" = sl."BatchId" AND b."ExpiryDate" < {today}) ORDER BY sl."ReceiptDate", sl."LayerId" FOR UPDATE @@ -95,7 +101,7 @@ public sealed class FifoCostingService : IFifoCostingService var heldExists = await _db.StockLayers.AsNoTracking().AnyAsync(l => l.ItemId == itemId && l.WarehouseId == warehouseId && l.QtyRemaining > 0 && (batchId == null || l.BatchId == batchId) - && l.GrnLine != null && l.GrnLine.HoldStatus == HoldStatus.OnHold, ct); + && l.GrnLine != null && (l.GrnLine.HoldStatus == HoldStatus.OnHold || l.GrnLine.HoldStatus == HoldStatus.Rejected), ct); if (heldExists) throw new DomainException(ErrorCodes.OnHoldNotIssuable, $"Stock for item {itemId} at warehouse {warehouseId} is on inspection hold and cannot be issued.", 409); @@ -145,11 +151,12 @@ public sealed class FifoCostingService : IFifoCostingService }; await _ledger.AddAsync(entry, ct); - // GL-ready journal entry per movement (FR-STK-13; data only, no posting). // Inbound debits Inventory / credits Clearing; outbound reverses. var (debit, credit) = direction == Direction.In - ? (InventoryAccount, ClearingAccount) - : (ClearingAccount, InventoryAccount); + ? (_glInventoryAccountCode, _glClearingAccountCode) + : (_glClearingAccountCode, _glInventoryAccountCode); + + // Local read-only stub kept for the journal-entries listing endpoint (FR-STK-13). await _journal.AddAsync(new JournalEntryStub { SourceDocType = sourceDocType, @@ -159,6 +166,24 @@ public sealed class FifoCostingService : IFifoCostingService Amount = entry.Value }, ct); + if (entry.Value != 0) + { + var period = await _gl.GetPeriodByDateAsync(DateOnly.FromDateTime(createdAt), ct); + await _gl.PostJournalEntryAsync(new GlJournalEntryRequest + { + PeriodId = period.PeriodId, + EntryDate = DateOnly.FromDateTime(createdAt), + SourceModule = "STOCK", + Reference = $"{sourceDocType}#{sourceDocId}", + Narration = $"{sourceDocType} {sourceDocId} — {direction} {qtyBase} @ {unitCost}", + Lines = new List + { + new(debit, entry.Value, 0m), + new(credit, 0m, entry.Value) + } + }, ct); + } + return entry; } diff --git a/Backend/ERPCore/Services/Stock/StockService.cs b/Backend/ERPCore/Services/Stock/StockService.cs index fa686cb..c3766f5 100644 --- a/Backend/ERPCore/Services/Stock/StockService.cs +++ b/Backend/ERPCore/Services/Stock/StockService.cs @@ -42,10 +42,12 @@ public sealed class StockService : IStockService { var onHand = await _fifo.GetOnHandAsync(itemId, warehouseId, ct); - // On-hold stock is on-hand but not issuable — sourced from GRN lines still OnHold. + // On-hold stock is on-hand but not issuable — GRN lines still OnHold (pending + // inspection) or Rejected (quarantined pending a Purchase Return); both are + // excluded from FifoCostingService.ConsumeAsync the same way. var onHold = await _layers.Query().AsNoTracking() .Where(l => l.ItemId == itemId && l.WarehouseId == warehouseId - && l.GrnLine != null && l.GrnLine.HoldStatus == HoldStatus.OnHold) + && l.GrnLine != null && (l.GrnLine.HoldStatus == HoldStatus.OnHold || l.GrnLine.HoldStatus == HoldStatus.Rejected)) .SumAsync(l => (decimal?)l.QtyRemaining, ct) ?? 0m; // Outbound in-transit: dispatched from this warehouse, not yet received at the @@ -99,7 +101,7 @@ public sealed class StockService : IStockService var onHold = (await _layers.Query().AsNoTracking() .Where(l => itemIds.Contains(l.ItemId) && warehouseIds.Contains(l.WarehouseId) - && l.GrnLine != null && l.GrnLine.HoldStatus == HoldStatus.OnHold) + && l.GrnLine != null && (l.GrnLine.HoldStatus == HoldStatus.OnHold || l.GrnLine.HoldStatus == HoldStatus.Rejected)) .GroupBy(l => new { l.ItemId, l.WarehouseId }) .Select(g => new { g.Key.ItemId, g.Key.WarehouseId, Qty = g.Sum(x => x.QtyRemaining) }) .ToListAsync(ct)) diff --git a/Backend/ERPCore/Services/SupportTicketService.cs b/Backend/ERPCore/Services/SupportTicketService.cs new file mode 100644 index 0000000..b146427 --- /dev/null +++ b/Backend/ERPCore/Services/SupportTicketService.cs @@ -0,0 +1,207 @@ +using ERPCore.Common.Http; +using ERPCore.Domain.Entities; +using ERPCore.Domain.Enums; +using ERPCore.Dtos.Support; +using ERPCore.Infra.UoW; +using ERPCore.Repositories.Interfaces; +using ERPCore.Services.Interfaces; +using ERPCore.System.Errors; +using Microsoft.EntityFrameworkCore; + +namespace ERPCore.Services; + +public sealed class SupportTicketService : ISupportTicketService +{ + private readonly IRepository _tickets; + private readonly IRepository _messages; + private readonly IRepository _users; + private readonly IUnitOfWork _uow; + + public SupportTicketService( + IRepository tickets, + IRepository messages, + IRepository users, + IUnitOfWork uow) + { + _tickets = tickets; + _messages = messages; + _users = users; + _uow = uow; + } + + public async Task> CreateAsync(int userId, CreateSupportTicketRequest request, CancellationToken ct = default) + { + var now = DateTime.UtcNow; + var ticket = new SupportTicket + { + Subject = request.Subject.Trim(), + Status = TicketStatus.Open, + CreatedBy = userId, + CreatedAt = now, + }; + ticket.Messages.Add(new SupportTicketMessage + { + SenderUserId = userId, + IsFromAdmin = false, + Message = request.Message.Trim(), + CreatedAt = now, + }); + + await _tickets.AddAsync(ticket, ct); + await _uow.SaveChangesAsync(ct); + + return await GetByIdAsync(ticket.TicketId, userId, isAdmin: true, ct); + } + + public async Task> GetListAsync(int userId, bool isAdmin, CancellationToken ct = default) + { + var query = _tickets.Query().AsNoTracking(); + if (!isAdmin) query = query.Where(t => t.CreatedBy == userId); + + var tickets = await query + .OrderByDescending(t => t.UpdatedAt ?? t.CreatedAt) + .Select(t => new + { + t.TicketId, + t.Subject, + t.Status, + t.CreatedBy, + t.CreatedAt, + t.UpdatedBy, + t.UpdatedAt, + MessageCount = t.Messages.Count, + }) + .ToListAsync(ct); + + var names = await ResolveNamesAsync(tickets.Select(t => t.CreatedBy), ct); + + return tickets + .Select(t => new SupportTicketSummaryDto( + t.TicketId, + t.Subject, + t.Status, + t.CreatedBy, + names.GetValueOrDefault(t.CreatedBy, "Unknown"), + t.CreatedAt, + t.UpdatedBy, + t.UpdatedAt, + t.MessageCount)) + .ToList(); + } + + public async Task> GetByIdAsync(int ticketId, int userId, bool isAdmin, CancellationToken ct = default) + { + var ticket = await _tickets.Query().AsNoTracking() + .Include(t => t.Messages) + .FirstOrDefaultAsync(t => t.TicketId == ticketId, ct) + ?? throw new NotFoundException($"Support ticket {ticketId} was not found."); + + if (!isAdmin && ticket.CreatedBy != userId) + throw new DomainException("FORBIDDEN", "You do not have access to this ticket.", 403); + + var names = await ResolveNamesAsync( + ticket.Messages.Select(m => m.SenderUserId) + .Append(ticket.CreatedBy) + .Concat(ticket.UpdatedBy is int updatedBy ? new[] { updatedBy } : Array.Empty()), + ct); + + var messages = ticket.Messages + .OrderBy(m => m.CreatedAt) + .Select(m => new SupportTicketMessageDto( + m.MessageId, + m.SenderUserId, + names.GetValueOrDefault(m.SenderUserId, "Unknown"), + m.IsFromAdmin, + m.Message, + m.CreatedAt)) + .ToList(); + + var dto = new SupportTicketDto( + ticket.TicketId, + ticket.Subject, + ticket.Status, + ticket.CreatedBy, + names.GetValueOrDefault(ticket.CreatedBy, "Unknown"), + ticket.CreatedAt, + ticket.UpdatedBy, + ticket.UpdatedBy is int u ? names.GetValueOrDefault(u, "Unknown") : null, + ticket.UpdatedAt, + messages); + + return new ETagged(dto, ticket.RowVersion); + } + + public async Task> AddMessageAsync(int ticketId, int userId, bool isAdmin, AddSupportTicketMessageRequest request, uint expectedRowVersion, CancellationToken ct = default) + { + var ticket = await _tickets.Query() + .FirstOrDefaultAsync(t => t.TicketId == ticketId, ct) + ?? throw new NotFoundException($"Support ticket {ticketId} was not found."); + + if (!isAdmin && ticket.CreatedBy != userId) + throw new DomainException("FORBIDDEN", "You do not have access to this ticket.", 403); + + if (ticket.RowVersion != expectedRowVersion) + throw new DomainException(ErrorCodes.ConcurrencyConflict, "This ticket was modified by another request.", 412); + + var now = DateTime.UtcNow; + await _messages.AddAsync(new SupportTicketMessage + { + TicketId = ticketId, + SenderUserId = userId, + IsFromAdmin = isAdmin, + Message = request.Message.Trim(), + CreatedAt = now, + }, ct); + + ticket.UpdatedBy = userId; + ticket.UpdatedAt = now; + if (isAdmin && ticket.Status == TicketStatus.Open) ticket.Status = TicketStatus.InProgress; + + try + { + await _uow.SaveChangesAsync(ct); + } + catch (DbUpdateConcurrencyException) + { + throw new DomainException(ErrorCodes.ConcurrencyConflict, "This ticket was modified by another request.", 412); + } + + return await GetByIdAsync(ticketId, userId, isAdmin, ct); + } + + public async Task> UpdateStatusAsync(int ticketId, int userId, bool isAdmin, UpdateSupportTicketStatusRequest request, uint expectedRowVersion, CancellationToken ct = default) + { + if (!isAdmin) + throw new DomainException("FORBIDDEN", "Only an administrator can change a ticket's status.", 403); + + var ticket = await _tickets.Query() + .FirstOrDefaultAsync(t => t.TicketId == ticketId, ct) + ?? throw new NotFoundException($"Support ticket {ticketId} was not found."); + + if (ticket.RowVersion != expectedRowVersion) + throw new DomainException(ErrorCodes.ConcurrencyConflict, "This ticket was modified by another request.", 412); + + ticket.Status = request.Status; + ticket.UpdatedBy = userId; + ticket.UpdatedAt = DateTime.UtcNow; + + try + { + await _uow.SaveChangesAsync(ct); + } + catch (DbUpdateConcurrencyException) + { + throw new DomainException(ErrorCodes.ConcurrencyConflict, "This ticket was modified by another request.", 412); + } + + return await GetByIdAsync(ticketId, ticket.CreatedBy, isAdmin: true, ct); + } + + private async Task> ResolveNamesAsync(IEnumerable userIds, CancellationToken ct) + { + var ids = userIds.Distinct().ToList(); + return await _users.Query().AsNoTracking() + .Where(u => ids.Contains(u.UserId)) + .ToDictionaryAsync(u => u.UserId, u => u.DisplayName, ct); + } +} diff --git a/Backend/ERPCore/Services/TaxRateService.cs b/Backend/ERPCore/Services/TaxRateService.cs new file mode 100644 index 0000000..8eb9523 --- /dev/null +++ b/Backend/ERPCore/Services/TaxRateService.cs @@ -0,0 +1,117 @@ +using ERPCore.Common.Http; +using ERPCore.Domain.Entities; +using ERPCore.Domain.Enums; +using ERPCore.Dtos.Common; +using ERPCore.Dtos.TaxRates; +using ERPCore.Infra.UoW; +using ERPCore.Repositories.Interfaces; +using ERPCore.Services.Interfaces; +using ERPCore.System.Errors; +using Microsoft.EntityFrameworkCore; + +namespace ERPCore.Services; + +/// Tax rate master service — see . +public sealed class TaxRateService : ITaxRateService +{ + private readonly IRepository _taxRates; + private readonly IUnitOfWork _uow; + + public TaxRateService(IRepository taxRates, IUnitOfWork uow) + { + _taxRates = taxRates; + _uow = uow; + } + + public async Task> ListAsync(PageQuery query, EntityStatus? status, CancellationToken ct = default) + { + var q = _taxRates.Query().AsNoTracking(); + if (!string.IsNullOrWhiteSpace(query.Q)) + { + var term = query.Q.Trim(); + q = q.Where(t => EF.Functions.ILike(t.Code, $"%{term}%") || EF.Functions.ILike(t.Name, $"%{term}%")); + } + if (status is not null) q = q.Where(t => t.Status == status); + + var total = await q.CountAsync(ct); + var rows = await q.OrderBy(t => t.Name) + .Skip(query.Skip).Take(query.PageSize) + .Select(t => new TaxRateDto(t.TaxRateId, t.Code, t.Name, t.Percentage, t.Status, t.CreatedAt, t.UpdatedAt)) + .ToListAsync(ct); + + return PagedResponse.Create(rows, query.Page, query.PageSize, total); + } + + public async Task?> GetAsync(int taxRateId, CancellationToken ct = default) + { + var rate = await _taxRates.Query().AsNoTracking().FirstOrDefaultAsync(t => t.TaxRateId == taxRateId, ct); + return rate is null ? null : new ETagged(Map(rate), rate.RowVersion); + } + + public async Task> CreateAsync(CreateTaxRateRequest request, CancellationToken ct = default) + { + var code = request.Code.Trim().ToUpperInvariant(); + if (await _taxRates.Query().AnyAsync(t => t.Code == code, ct)) + throw new ConflictException($"A tax rate with code '{code}' already exists."); + + var rate = new TaxRate + { + Code = code, + Name = request.Name.Trim(), + Percentage = request.Percentage, + Status = EntityStatus.Active, + CreatedAt = DateTime.UtcNow + }; + + await _taxRates.AddAsync(rate, ct); + await _uow.SaveChangesAsync(ct); + + return new ETagged(Map(rate), rate.RowVersion); + } + + public async Task> UpdateAsync( + int taxRateId, UpdateTaxRateRequest request, uint expectedRowVersion, CancellationToken ct = default) + { + var rate = await _taxRates.GetByIdAsync(taxRateId, ct) + ?? throw new NotFoundException($"Tax rate {taxRateId} was not found."); + + if (rate.RowVersion != expectedRowVersion) + throw new DomainException(ErrorCodes.ConcurrencyConflict, "The tax rate was modified by another request.", 412); + + var code = request.Code.Trim().ToUpperInvariant(); + if (!string.Equals(rate.Code, code, StringComparison.Ordinal) + && await _taxRates.Query().AnyAsync(t => t.Code == code && t.TaxRateId != taxRateId, ct)) + throw new ConflictException($"A tax rate with code '{code}' already exists."); + + // Existing lines never recompute from this — SalesSlipLine.TaxPct etc. are snapshots + // taken at line-creation time — so changing Percentage here only affects documents + // created from now on, never rewrites history. + rate.Code = code; + rate.Name = request.Name.Trim(); + rate.Percentage = request.Percentage; + rate.UpdatedAt = DateTime.UtcNow; + + try + { + await _uow.SaveChangesAsync(ct); + } + catch (DbUpdateConcurrencyException) + { + throw new DomainException(ErrorCodes.ConcurrencyConflict, "The tax rate was modified by another request.", 412); + } + + return new ETagged(Map(rate), rate.RowVersion); + } + + public async Task SetStatusAsync(int taxRateId, EntityStatus status, CancellationToken ct = default) + { + var rate = await _taxRates.GetByIdAsync(taxRateId, ct) + ?? throw new NotFoundException($"Tax rate {taxRateId} was not found."); + + rate.Status = status; + rate.UpdatedAt = DateTime.UtcNow; + await _uow.SaveChangesAsync(ct); + } + + private static TaxRateDto Map(TaxRate t) => new(t.TaxRateId, t.Code, t.Name, t.Percentage, t.Status, t.CreatedAt, t.UpdatedAt); +} diff --git a/Backend/ERPCore/Services/TransferService.cs b/Backend/ERPCore/Services/TransferService.cs index 79496be..97c16b5 100644 --- a/Backend/ERPCore/Services/TransferService.cs +++ b/Backend/ERPCore/Services/TransferService.cs @@ -35,12 +35,13 @@ public sealed class TransferService : ITransferService private readonly INumberSequenceService _numbers; private readonly ICurrentUser _currentUser; private readonly IBranchConfigService _branchConfig; + private readonly INotificationService _notifications; private readonly IUnitOfWork _uow; public TransferService( IRepository transfers, IRepository warehouses, IRepository items, IFifoCostingService fifo, INumberSequenceService numbers, ICurrentUser currentUser, - IBranchConfigService branchConfig, IUnitOfWork uow) + IBranchConfigService branchConfig, INotificationService notifications, IUnitOfWork uow) { _transfers = transfers; _warehouses = warehouses; @@ -49,6 +50,7 @@ public sealed class TransferService : ITransferService _numbers = numbers; _currentUser = currentUser; _branchConfig = branchConfig; + _notifications = notifications; _uow = uow; } @@ -123,6 +125,8 @@ public sealed class TransferService : ITransferService return entity; }, ct); + await _notifications.RaiseAsync("stock.transfer.created", "Stock Transfer Created", $"Stock transfer {transfer.DocNo} was created.", nameof(StockTransfer), transfer.TransferId, ct); + return Map(transfer); } diff --git a/Backend/ERPCore/Services/UomService.cs b/Backend/ERPCore/Services/UomService.cs index 4507a31..3a7f192 100644 --- a/Backend/ERPCore/Services/UomService.cs +++ b/Backend/ERPCore/Services/UomService.cs @@ -1,4 +1,5 @@ using ERPCore.Domain.Entities; +using ERPCore.Domain.Enums; using ERPCore.Dtos.Common; using ERPCore.Dtos.Uoms; using ERPCore.Infra.UoW; @@ -20,7 +21,7 @@ public sealed class UomService : IUomService _uow = uow; } - public async Task> ListAsync(PageQuery query, CancellationToken ct = default) + public async Task> ListAsync(PageQuery query, EntityStatus? status, CancellationToken ct = default) { var q = _uoms.Query().AsNoTracking(); if (!string.IsNullOrWhiteSpace(query.Q)) @@ -28,11 +29,12 @@ public sealed class UomService : IUomService var term = query.Q.Trim(); q = q.Where(u => EF.Functions.ILike(u.Name, $"%{term}%")); } + if (status is not null) q = q.Where(u => u.Status == status); var total = await q.CountAsync(ct); var rows = await q.OrderBy(u => u.Name) .Skip(query.Skip).Take(query.PageSize) - .Select(u => new UomDto(u.UomId, u.Name)) + .Select(u => new UomDto(u.UomId, u.Name, u.Status, u.CreatedAt, u.UpdatedAt)) .ToListAsync(ct); return PagedResponse.Create(rows, query.Page, query.PageSize, total); @@ -44,10 +46,20 @@ public sealed class UomService : IUomService if (await _uoms.Query().AnyAsync(u => u.Name == name, ct)) throw new ConflictException($"A UOM named '{name}' already exists."); - var uom = new Uom { Name = name }; + var uom = new Uom { Name = name, Status = EntityStatus.Active, CreatedAt = DateTime.UtcNow }; await _uoms.AddAsync(uom, ct); await _uow.SaveChangesAsync(ct); - return new UomDto(uom.UomId, uom.Name); + return new UomDto(uom.UomId, uom.Name, uom.Status, uom.CreatedAt, uom.UpdatedAt); + } + + public async Task SetStatusAsync(int uomId, EntityStatus status, CancellationToken ct = default) + { + var uom = await _uoms.GetByIdAsync(uomId, ct) + ?? throw new NotFoundException($"UOM {uomId} was not found."); + + uom.Status = status; + uom.UpdatedAt = DateTime.UtcNow; + await _uow.SaveChangesAsync(ct); } } diff --git a/Backend/ERPCore/Services/UserManagementService.cs b/Backend/ERPCore/Services/UserManagementService.cs index 6cba9e0..31e60de 100644 --- a/Backend/ERPCore/Services/UserManagementService.cs +++ b/Backend/ERPCore/Services/UserManagementService.cs @@ -189,6 +189,15 @@ public sealed class UserManagementService : IUserManagementService return userTypes.Select(t => new UserTypeOptionDto(t.UserTypeId, t.Code, t.Description)).ToList(); } + public Task PurgeAuthHexIdentityAsync(PurgeAuthHexIdentityRequest request, CancellationToken ct = default) + { + if (string.IsNullOrWhiteSpace(request.Email) && string.IsNullOrWhiteSpace(request.MobileNumber) + && string.IsNullOrWhiteSpace(request.Nic) && string.IsNullOrWhiteSpace(request.UserName)) + throw new DomainException(ErrorCodes.Validation, "At least one identifier (email, mobileNumber, nic, userName) is required.", 422); + + return _authHex.DeleteUserAsync(request.Email, request.MobileNumber, request.Nic, request.UserName, ct); + } + private static ManagedUserDto Map(User u) => new( u.UserId, u.Username, u.DisplayName, u.Email, u.Status, u.RoleId, u.Role?.Code, u.Role?.Name); } diff --git a/Backend/ERPCore/Services/VendorService.cs b/Backend/ERPCore/Services/VendorService.cs index cbe0306..19f0b27 100644 --- a/Backend/ERPCore/Services/VendorService.cs +++ b/Backend/ERPCore/Services/VendorService.cs @@ -14,11 +14,13 @@ namespace ERPCore.Services; public sealed class VendorService : IVendorService { private readonly IRepository _vendors; + private readonly IBranchConfigService _branchConfig; private readonly IUnitOfWork _uow; - public VendorService(IRepository vendors, IUnitOfWork uow) + public VendorService(IRepository vendors, IBranchConfigService branchConfig, IUnitOfWork uow) { _vendors = vendors; + _branchConfig = branchConfig; _uow = uow; } @@ -53,6 +55,7 @@ public sealed class VendorService : IVendorService if (await _vendors.Query().AnyAsync(v => v.Code == code, ct)) throw new ConflictException($"A vendor with code '{code}' already exists."); + var branchId = await _branchConfig.ResolveBranchIdAsync(request.BranchId, ct); var vendor = new Vendor { Code = code, @@ -61,6 +64,7 @@ public sealed class VendorService : IVendorService TaxReg = request.TaxReg, Currency = request.Currency.Trim().ToUpperInvariant(), Status = EntityStatus.Active, + BranchId = branchId, CreatedAt = DateTime.UtcNow }; @@ -84,11 +88,14 @@ public sealed class VendorService : IVendorService && await _vendors.Query().AnyAsync(v => v.Code == code && v.VendorId != vendorId, ct)) throw new ConflictException($"A vendor with code '{code}' already exists."); + var branchId = await _branchConfig.ResolveBranchIdAsync(request.BranchId, ct); + vendor.Code = code; vendor.Name = request.Name.Trim(); vendor.Terms = request.Terms; vendor.TaxReg = request.TaxReg; vendor.Currency = request.Currency.Trim().ToUpperInvariant(); + vendor.BranchId = branchId; vendor.UpdatedAt = DateTime.UtcNow; try @@ -114,5 +121,5 @@ public sealed class VendorService : IVendorService } private static VendorDto Map(Vendor v) => new( - v.VendorId, v.Code, v.Name, v.Terms, v.TaxReg, v.Currency, v.Status, v.CreatedAt, v.UpdatedAt); + v.VendorId, v.Code, v.Name, v.Terms, v.TaxReg, v.Currency, v.Status, v.BranchId, v.CreatedAt, v.UpdatedAt); } diff --git a/Backend/ERPCore/Services/WarehouseService.cs b/Backend/ERPCore/Services/WarehouseService.cs index 7a82f9e..dcea79e 100644 --- a/Backend/ERPCore/Services/WarehouseService.cs +++ b/Backend/ERPCore/Services/WarehouseService.cs @@ -41,7 +41,7 @@ public sealed class WarehouseService : IWarehouseService var total = await q.CountAsync(ct); var rows = await q.OrderBy(w => w.Code) .Skip(query.Skip).Take(query.PageSize) - .Select(w => new WarehouseDto(w.WarehouseId, w.Code, w.Name, w.BranchId, w.Branch != null ? w.Branch.Name : null)) + .Select(w => new WarehouseDto(w.WarehouseId, w.Code, w.Name, w.Address, w.Phone, w.BranchId, w.Branch != null ? w.Branch.Name : null)) .ToListAsync(ct); return PagedResponse.Create(rows, query.Page, query.PageSize, total); @@ -51,7 +51,7 @@ public sealed class WarehouseService : IWarehouseService { var w = await _warehouses.Query().AsNoTracking().Include(x => x.Branch) .FirstOrDefaultAsync(x => x.WarehouseId == warehouseId, ct); - return w is null ? null : new WarehouseDto(w.WarehouseId, w.Code, w.Name, w.BranchId, w.Branch?.Name); + return w is null ? null : new WarehouseDto(w.WarehouseId, w.Code, w.Name, w.Address, w.Phone, w.BranchId, w.Branch?.Name); } public async Task CreateAsync(CreateWarehouseRequest request, CancellationToken ct = default) @@ -60,14 +60,60 @@ public sealed class WarehouseService : IWarehouseService if (await _warehouses.Query().AnyAsync(w => w.Code == code, ct)) throw new ConflictException($"A warehouse with code '{code}' already exists."); - var branchId = await _branchConfig.ResolveBranchIdAsync(request.BranchId, ct); - var warehouse = new Warehouse { Code = code, Name = request.Name.Trim(), BranchId = branchId }; + var branchId = await _branchConfig.ResolveWarehouseBranchIdAsync(request.BranchId, ct); + var warehouse = new Warehouse + { + Code = code, + Name = request.Name.Trim(), + Address = string.IsNullOrWhiteSpace(request.Address) ? null : request.Address.Trim(), + Phone = string.IsNullOrWhiteSpace(request.Phone) ? null : request.Phone.Trim(), + BranchId = branchId, + }; await _warehouses.AddAsync(warehouse, ct); await _uow.SaveChangesAsync(ct); var branchName = await _branches.Query().AsNoTracking() .Where(b => b.BranchId == warehouse.BranchId).Select(b => b.Name).FirstOrDefaultAsync(ct); - return new WarehouseDto(warehouse.WarehouseId, warehouse.Code, warehouse.Name, warehouse.BranchId, branchName); + return new WarehouseDto(warehouse.WarehouseId, warehouse.Code, warehouse.Name, warehouse.Address, warehouse.Phone, warehouse.BranchId, branchName); + } + + public async Task UpdateAsync(int warehouseId, UpdateWarehouseRequest request, CancellationToken ct = default) + { + var warehouse = await _warehouses.GetByIdAsync(warehouseId, ct) + ?? throw new NotFoundException($"Warehouse {warehouseId} was not found."); + + var code = request.Code.Trim(); + if (await _warehouses.Query().AnyAsync(w => w.WarehouseId != warehouseId && w.Code == code, ct)) + throw new ConflictException($"A warehouse with code '{code}' already exists."); + + var branchId = await _branchConfig.ResolveWarehouseBranchIdAsync(request.BranchId, ct); + + warehouse.Code = code; + warehouse.Name = request.Name.Trim(); + warehouse.Address = string.IsNullOrWhiteSpace(request.Address) ? null : request.Address.Trim(); + warehouse.Phone = string.IsNullOrWhiteSpace(request.Phone) ? null : request.Phone.Trim(); + warehouse.BranchId = branchId; + await _uow.SaveChangesAsync(ct); + + var branchName = await _branches.Query().AsNoTracking() + .Where(b => b.BranchId == warehouse.BranchId).Select(b => b.Name).FirstOrDefaultAsync(ct); + return new WarehouseDto(warehouse.WarehouseId, warehouse.Code, warehouse.Name, warehouse.Address, warehouse.Phone, warehouse.BranchId, branchName); + } + + public async Task DeleteAsync(int warehouseId, CancellationToken ct = default) + { + var warehouse = await _warehouses.GetByIdAsync(warehouseId, ct) + ?? throw new NotFoundException($"Warehouse {warehouseId} was not found."); + + _warehouses.Remove(warehouse); + try + { + await _uow.SaveChangesAsync(ct); + } + catch (DbUpdateException) + { + throw new DomainException(ErrorCodes.MasterInUse, "This warehouse is referenced by other records (bins, stock, or documents) and cannot be deleted.", 409); + } } public async Task> ListBinsAsync(int warehouseId, CancellationToken ct = default) diff --git a/Backend/ERPCore/System/Errors/ErrorCodes.cs b/Backend/ERPCore/System/Errors/ErrorCodes.cs index 58f8182..d09c3ad 100644 --- a/Backend/ERPCore/System/Errors/ErrorCodes.cs +++ b/Backend/ERPCore/System/Errors/ErrorCodes.cs @@ -17,6 +17,9 @@ public static class ErrorCodes public const string SkuDuplicate = "SKU_DUPLICATE"; public const string MasterInUse = "MASTER_IN_USE"; public const string PoNotEditable = "PO_NOT_EDITABLE"; + public const string PoNotPendingApproval = "PO_NOT_PENDING_APPROVAL"; + public const string PoApprovalForbidden = "PO_APPROVAL_FORBIDDEN"; + public const string ReturnQtyExceedsRejected = "RETURN_QTY_EXCEEDS_REJECTED"; public const string OverReceiptTolerance = "OVER_RECEIPT_TOLERANCE"; public const string StockNegativeBlocked = "STOCK_NEGATIVE_BLOCKED"; public const string ExpiredBatchBlocked = "EXPIRED_BATCH_BLOCKED"; @@ -79,10 +82,14 @@ public static class ErrorCodes public const string SalesInvoicePaymentExceedsBalance = "SALES_INVOICE_PAYMENT_EXCEEDS_BALANCE"; public const string SalesInvoiceBankAccountNotFound = "SALES_INVOICE_BANK_ACCOUNT_NOT_FOUND"; + // Sales slip partial payment (PaidAmount at ring-up time, not installments after the fact) + public const string SalesSlipPaidAmountInvalid = "SALES_SLIP_PAID_AMOUNT_INVALID"; + // Purchase invoices (consolidate Confirmed GRNs; vendor payments now tracked here, not on the GRN) public const string GrnAlreadyInvoiced = "GRN_ALREADY_INVOICED"; public const string GrnVendorMismatch = "GRN_VENDOR_MISMATCH"; public const string GrnNotConfirmed = "GRN_NOT_CONFIRMED"; + public const string GrnBranchMismatch = "GRN_BRANCH_MISMATCH"; public const string PurchaseInvoiceNotEditable = "PURCHASE_INVOICE_NOT_EDITABLE"; public const string DuplicateVendorInvoiceNo = "DUPLICATE_VENDOR_INVOICE_NO"; public const string PurchaseInvoiceNotPayable = "PURCHASE_INVOICE_NOT_PAYABLE"; diff --git a/Backend/ERPCore/appsettings.Development.json b/Backend/ERPCore/appsettings.Development.json index 16c2ab2..a74bfab 100644 --- a/Backend/ERPCore/appsettings.Development.json +++ b/Backend/ERPCore/appsettings.Development.json @@ -6,7 +6,7 @@ } }, "ConnectionStrings": { - "DefaultConnection": "Host=127.0.0.1;Port=5433;Database=ERPCoreTest;Username=postgres;Password=post@hexdive" + "DefaultConnection": "Host=localhost;Port=5433;Database=ERPCoreTest;Username=postgres;Password=post@hexdive" }, "AuthHex": { "BaseUrl": "http://localhost:5011" diff --git a/Backend/ERPCore/appsettings.Production.json b/Backend/ERPCore/appsettings.Production.json index f2762ae..a1b8a7a 100644 --- a/Backend/ERPCore/appsettings.Production.json +++ b/Backend/ERPCore/appsettings.Production.json @@ -1,7 +1,4 @@ { - "ConnectionStrings": { - "DefaultConnection": "" - }, "Jwt": { "SigningKey": "" }, diff --git a/Backend/ERPCore/appsettings.json b/Backend/ERPCore/appsettings.json index 10ea3d1..d66d083 100644 --- a/Backend/ERPCore/appsettings.json +++ b/Backend/ERPCore/appsettings.json @@ -38,7 +38,8 @@ "GlSalesDiscountAccountCode": "4100", "GlTaxPayableAccountCode": "2100", "GlCogsAccountCode": "5000", - "GlInventoryAccountCode": "1100" + "GlInventoryAccountCode": "1100", + "GlAccountsReceivableCode": "1300" }, "Adjustment": { "GlInventoryAccountCode": "1100", @@ -52,5 +53,9 @@ "GlClearingAccountCode": "2000", "GlAccountsPayableCode": "2200" }, + "Fifo": { + "GlInventoryAccountCode": "1100", + "GlClearingAccountCode": "2000" + }, "AllowedHosts": "*" } diff --git a/Frontend/erp-system/app/dashboard/accounts/bank-accounts/page.tsx b/Frontend/erp-system/app/dashboard/accounts/bank-accounts/page.tsx index 214ff90..7dd938c 100644 --- a/Frontend/erp-system/app/dashboard/accounts/bank-accounts/page.tsx +++ b/Frontend/erp-system/app/dashboard/accounts/bank-accounts/page.tsx @@ -161,11 +161,11 @@ export default function BankAccountsPage() { {a.accountName} {a.bankName ?? a.cashAccountTypeName ?? "—"} {a.accountNumber ?? "—"} - + {gl ? `${gl.accountCode} — ${gl.accountName}` : `#${a.glAccountId}`} {a.currencyCode} - {formatReportDate(a.createdAt)} + {formatReportDate(a.createdAt)} {p.payeeName ?? "—"} - {formatReportDate(p.issueDate)} + {formatReportDate(p.issueDate)} {p.amount !== null ? formatAmount(p.amount) : "—"} diff --git a/Frontend/erp-system/app/dashboard/accounts/cheque-books/page.tsx b/Frontend/erp-system/app/dashboard/accounts/cheque-books/page.tsx index 8dcfa5a..f58d7c4 100644 --- a/Frontend/erp-system/app/dashboard/accounts/cheque-books/page.tsx +++ b/Frontend/erp-system/app/dashboard/accounts/cheque-books/page.tsx @@ -142,15 +142,15 @@ export default function ChequeBooksPage() { onClick={() => router.push(`/dashboard/accounts/cheque-books/${encodeURIComponent(b.chequeBookNo)}`)} > {b.chequeBookNo} - + {bank ? bank.accountName : `#${b.bankAccountId}`} - {branchesById.get(b.branchId)?.name ?? `#${b.branchId}`} + {branchesById.get(b.branchId)?.name ?? `#${b.branchId}`} {b.startChequeNo} – {b.endChequeNo} {b.totalLeaves} - {formatReportDate(b.receivedDate)} + {formatReportDate(b.receivedDate)} {b.status} diff --git a/Frontend/erp-system/app/dashboard/accounts/received-cheques/page.tsx b/Frontend/erp-system/app/dashboard/accounts/received-cheques/page.tsx index 499b1c7..50f4c86 100644 --- a/Frontend/erp-system/app/dashboard/accounts/received-cheques/page.tsx +++ b/Frontend/erp-system/app/dashboard/accounts/received-cheques/page.tsx @@ -146,12 +146,12 @@ export default function ReceivedChequesPage() { > {c.chequeNo} {c.receivedFromName} - {c.receivedFromType} - + {c.receivedFromType} + {c.branchId ? (branchesById.get(c.branchId)?.name ?? `#${c.branchId}`) : "—"} {formatAmount(c.amount)} - {formatReportDate(c.receivedDate)} + {formatReportDate(c.receivedDate)} {c.status} diff --git a/Frontend/erp-system/app/dashboard/help/page.tsx b/Frontend/erp-system/app/dashboard/help/page.tsx new file mode 100644 index 0000000..d47b2cc --- /dev/null +++ b/Frontend/erp-system/app/dashboard/help/page.tsx @@ -0,0 +1,387 @@ +"use client" + +import { useEffect, useMemo, useState } from "react" +import Link from "next/link" +import { + CheckCircle2, + ChevronLeft, + ChevronRight, + Clock, + HelpCircle, + Inbox, + Plus, + Search, + X, +} from "lucide-react" + +import { supportTicketsApi } from "@/lib/api/support-tickets" +import { errorMessage } from "@/lib/error-map" +import { cn } from "@/lib/utils" +import { SupportTicketSummary } from "@/types/support" + +import { useAuth } from "@/components/auth/AuthProvider" +import { Badge } from "@/components/ui/badge" +import { Button } from "@/components/ui/button" +import { Input } from "@/components/ui/input" +import { Textarea } from "@/components/ui/textarea" +import { Field, FieldError, FieldGroup, FieldLabel } from "@/components/ui/field" +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog" +import { Skeleton } from "@/components/ui/skeleton" +import { StatCard } from "@/components/ui/stat-card" +import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table" +import { toast } from "@/components/ui/toast" + +const PAGE_SIZE_OPTIONS = [5, 10, 25, 50] + +const statusStyles: Record = { + Open: "border-transparent bg-primary/10 text-primary", + InProgress: "border-transparent bg-warning/10 text-warning", + Resolved: "border-success/40 text-success", +} + +const statusLabels: Record = { + Open: "Open", + InProgress: "In Progress", + Resolved: "Resolved", +} + +export default function HelpPage() { + const { isAdmin } = useAuth() + + const [tickets, setTickets] = useState(null) + const [error, setError] = useState(null) + const [page, setPage] = useState(1) + const [pageSize, setPageSize] = useState(5) + const [search, setSearch] = useState("") + const [debouncedSearch, setDebouncedSearch] = useState("") + + const [open, setOpen] = useState(false) + const [subject, setSubject] = useState("") + const [message, setMessage] = useState("") + const [errors, setErrors] = useState>({}) + const [submitting, setSubmitting] = useState(false) + + function load() { + supportTicketsApi + .list() + .then(setTickets) + .catch((err) => setError(errorMessage(err))) + } + + useEffect(load, []) + + useEffect(() => { + const t = setTimeout(() => { + setPage(1) + setDebouncedSearch(search.trim()) + }, 300) + return () => clearTimeout(t) + }, [search]) + + const stats = useMemo(() => { + if (!tickets) return null + return { + total: tickets.length, + open: tickets.filter((t) => t.status === "Open").length, + inProgress: tickets.filter((t) => t.status === "InProgress").length, + resolved: tickets.filter((t) => t.status === "Resolved").length, + } + }, [tickets]) + + const filtered = useMemo(() => { + if (!tickets) return [] + const term = debouncedSearch.toLowerCase() + if (!term) return tickets + return tickets.filter( + (t) => t.subject.toLowerCase().includes(term) || t.createdByName.toLowerCase().includes(term) + ) + }, [tickets, debouncedSearch]) + + const totalItems = filtered.length + const totalPages = Math.max(1, Math.ceil(totalItems / pageSize)) + const pageItems = filtered.slice((page - 1) * pageSize, (page - 1) * pageSize + pageSize) + + async function handleCreate() { + const nextErrors: Record = {} + if (!subject.trim()) nextErrors.subject = "Subject is required" + if (!message.trim()) nextErrors.message = "Please describe your issue" + setErrors(nextErrors) + if (Object.keys(nextErrors).length > 0) return + + setSubmitting(true) + try { + await supportTicketsApi.create({ subject, message }) + toast.success("Ticket submitted", "Support will get back to you here.") + setOpen(false) + setSubject("") + setMessage("") + setErrors({}) + load() + } catch (err) { + toast.error("Could not submit ticket", errorMessage(err)) + } finally { + setSubmitting(false) + } + } + + const loading = !tickets && !error + + return ( +
+
+
+
+

Help & Support

+ {tickets && ( + + {tickets.length} + + )} +
+

+ {isAdmin + ? "All support tickets submitted by users across the system." + : "Raise a ticket and track its status here."} +

+
+ + {!isAdmin && ( + + + + New Ticket + + } + /> + + + New support ticket + Describe the issue and an admin will follow up here. + + + + Subject + setSubject(e.target.value)} + placeholder="Can't confirm a GRN" + aria-invalid={!!errors.subject} + /> + + + + Message +