diff --git a/Backend/ERPCore/Domain/Entities/Grn.cs b/Backend/ERPCore/Domain/Entities/Grn.cs
index 920d3d6..e742923 100644
--- a/Backend/ERPCore/Domain/Entities/Grn.cs
+++ b/Backend/ERPCore/Domain/Entities/Grn.cs
@@ -22,6 +22,11 @@ public class Grn
public int WarehouseId { get; set; }
public Warehouse? Warehouse { get; set; }
+ /// Owning branch, set explicitly at creation — warehouses are shared across
+ /// branches, so branch scope can no longer be derived from .
+ public int BranchId { get; set; }
+ public Branch? Branch { get; set; }
+
public GrnStatus Status { get; set; } = GrnStatus.Draft;
public int CreatedBy { get; set; }
diff --git a/Backend/ERPCore/Domain/Entities/SalesInvoice.cs b/Backend/ERPCore/Domain/Entities/SalesInvoice.cs
index 8e35c72..60f25cc 100644
--- a/Backend/ERPCore/Domain/Entities/SalesInvoice.cs
+++ b/Backend/ERPCore/Domain/Entities/SalesInvoice.cs
@@ -17,6 +17,11 @@ public class SalesInvoice
public int WarehouseId { get; set; }
public Warehouse? Warehouse { get; set; }
+ /// Owning branch, set explicitly at creation — warehouses are shared across
+ /// branches, so branch scope can no longer be derived from .
+ public int BranchId { get; set; }
+ public Branch? Branch { get; set; }
+
public SalesInvoiceType InvoiceType { get; set; } = SalesInvoiceType.B2C;
public SalesInvoiceStatus Status { get; set; } = SalesInvoiceStatus.Draft;
diff --git a/Backend/ERPCore/Domain/Entities/StockAdjustment.cs b/Backend/ERPCore/Domain/Entities/StockAdjustment.cs
index a59e2c8..bcece95 100644
--- a/Backend/ERPCore/Domain/Entities/StockAdjustment.cs
+++ b/Backend/ERPCore/Domain/Entities/StockAdjustment.cs
@@ -19,6 +19,11 @@ public class StockAdjustment
public int ReasonCodeId { get; set; }
public ReasonCode? ReasonCode { get; set; }
+ /// Owning branch, set explicitly at creation — warehouses are shared across
+ /// branches, so branch scope can no longer be derived from .
+ public int BranchId { get; set; }
+ public Branch? Branch { get; set; }
+
public AdjustmentStatus Status { get; set; } = AdjustmentStatus.Posted;
public int CreatedBy { get; set; }
diff --git a/Backend/ERPCore/Domain/Entities/StockCount.cs b/Backend/ERPCore/Domain/Entities/StockCount.cs
index 2a2a118..0bc47a5 100644
--- a/Backend/ERPCore/Domain/Entities/StockCount.cs
+++ b/Backend/ERPCore/Domain/Entities/StockCount.cs
@@ -16,6 +16,11 @@ public class StockCount
public int WarehouseId { get; set; }
public Warehouse? Warehouse { get; set; }
+ /// Owning branch, set explicitly at creation — warehouses are shared across
+ /// branches, so branch scope can no longer be derived from .
+ public int BranchId { get; set; }
+ public Branch? Branch { get; set; }
+
public CountType CountType { get; set; }
public CountStatus Status { get; set; } = CountStatus.Draft;
diff --git a/Backend/ERPCore/Domain/Entities/StockTransfer.cs b/Backend/ERPCore/Domain/Entities/StockTransfer.cs
index 0a17c89..ffd6058 100644
--- a/Backend/ERPCore/Domain/Entities/StockTransfer.cs
+++ b/Backend/ERPCore/Domain/Entities/StockTransfer.cs
@@ -19,6 +19,11 @@ public class StockTransfer
public int DestWarehouseId { get; set; }
public Warehouse? DestWarehouse { get; set; }
+ /// Owning branch, set explicitly at creation — warehouses are shared across
+ /// branches, so branch scope can no longer be derived from src/dest warehouse.
+ public int BranchId { get; set; }
+ public Branch? Branch { get; set; }
+
public TransferStatus Status { get; set; } = TransferStatus.Draft;
public int CreatedBy { get; set; }
diff --git a/Backend/ERPCore/Dtos/Grn/GrnDtos.cs b/Backend/ERPCore/Dtos/Grn/GrnDtos.cs
index 9d6c7e8..6cb0c87 100644
--- a/Backend/ERPCore/Dtos/Grn/GrnDtos.cs
+++ b/Backend/ERPCore/Dtos/Grn/GrnDtos.cs
@@ -15,13 +15,13 @@ public sealed record GrnLineDto(
HoldStatus HoldStatus, int? BatchId, IReadOnlyList WarrantyNumbers);
public sealed record GrnDto(
- int GrnId, string DocNo, int? PoId, int VendorId, int WarehouseId, GrnStatus Status,
+ int GrnId, string DocNo, int? PoId, int VendorId, int WarehouseId, int BranchId, GrnStatus Status,
int CreatedBy, DateTime CreatedAt, DateTime? PostedAt, string? GlJournalNo,
int? PurchaseInvoiceId, string? PurchaseInvoiceNo, IReadOnlyList Lines);
/// Row shape for GET /grns — line count instead of the lines themselves.
public sealed record GrnSummaryDto(
- int GrnId, string DocNo, int? PoId, int VendorId, int WarehouseId, GrnStatus Status,
+ int GrnId, string DocNo, int? PoId, int VendorId, int WarehouseId, int BranchId, GrnStatus Status,
int CreatedBy, DateTime CreatedAt, DateTime? PostedAt, int LineCount,
int? PurchaseInvoiceId, string? PurchaseInvoiceNo);
@@ -81,6 +81,9 @@ public sealed class CreateGrnRequest
/// Required for a direct receipt (no PO); ignored otherwise (vendor derives from the PO).
public int? VendorId { get; set; }
[Required] public int WarehouseId { get; set; }
+ /// Owning branch for this GRN — warehouses are shared, so this is what actually
+ /// scopes the document (resolved via IBranchConfigService; required when branching is enabled).
+ [Required] public int BranchId { get; set; }
[Required, MinLength(1)] public List Lines { get; set; } = new();
}
diff --git a/Backend/ERPCore/Dtos/Sales/SalesInvoiceDtos.cs b/Backend/ERPCore/Dtos/Sales/SalesInvoiceDtos.cs
index 3e7dbcc..cd037f8 100644
--- a/Backend/ERPCore/Dtos/Sales/SalesInvoiceDtos.cs
+++ b/Backend/ERPCore/Dtos/Sales/SalesInvoiceDtos.cs
@@ -15,14 +15,14 @@ public sealed record SalesInvoiceTotalsDto(
public sealed record SalesInvoiceDto(
int SalesInvoiceId, string InvoiceNo, DateTime InvoiceDate, int CustomerId,
- string CustomerSnapshotName, string? CustomerSnapshotTaxNo, int WarehouseId,
+ string CustomerSnapshotName, string? CustomerSnapshotTaxNo, int WarehouseId, int BranchId,
SalesInvoiceType InvoiceType, SalesInvoiceStatus Status, int CreatedBy, DateTime CreatedAt,
DateTime? UpdatedAt, string? GlJournalNo, DateTime? GlPostedAt,
SalesInvoiceTotalsDto Totals, IReadOnlyList Lines);
public sealed record SalesInvoiceSummaryDto(
int SalesInvoiceId, string InvoiceNo, DateTime InvoiceDate, int CustomerId,
- string CustomerSnapshotName, int WarehouseId, SalesInvoiceType InvoiceType,
+ string CustomerSnapshotName, int WarehouseId, int BranchId, SalesInvoiceType InvoiceType,
SalesInvoiceStatus Status, SalesInvoiceTotalsDto Totals, DateTime CreatedAt, string? GlJournalNo);
public sealed record SalesInvoicePaymentDto(
@@ -65,6 +65,9 @@ public sealed class CreateSalesInvoiceRequest
{
[Required] public int CustomerId { get; set; }
[Required] public int WarehouseId { get; set; }
+ /// Owning branch — warehouses are shared, so this is what actually scopes the
+ /// document (resolved via IBranchConfigService).
+ [Required] public int BranchId { get; set; }
[Required, EnumDataType(typeof(SalesInvoiceType))] public SalesInvoiceType InvoiceType { get; set; } = SalesInvoiceType.B2C;
[Required, MinLength(1)] public List Lines { get; set; } = new();
}
@@ -73,6 +76,9 @@ public sealed class UpdateSalesInvoiceRequest
{
[Required] public int CustomerId { get; set; }
[Required] public int WarehouseId { get; set; }
+ /// Owning branch — warehouses are shared, so this is what actually scopes the
+ /// document (resolved via IBranchConfigService).
+ [Required] public int BranchId { get; set; }
[Required, EnumDataType(typeof(SalesInvoiceType))] public SalesInvoiceType InvoiceType { get; set; } = SalesInvoiceType.B2C;
[Required, MinLength(1)] public List Lines { get; set; } = new();
}
diff --git a/Backend/ERPCore/Dtos/Stock/AdjustmentDtos.cs b/Backend/ERPCore/Dtos/Stock/AdjustmentDtos.cs
index ab51be2..0163c66 100644
--- a/Backend/ERPCore/Dtos/Stock/AdjustmentDtos.cs
+++ b/Backend/ERPCore/Dtos/Stock/AdjustmentDtos.cs
@@ -8,13 +8,13 @@ namespace ERPCore.Dtos.Stock;
public sealed record AdjustmentLineDto(int AdjLineId, int ItemId, int? BinId, int? BatchId, decimal QtyDelta);
public sealed record AdjustmentDto(
- int AdjustmentId, string DocNo, int WarehouseId, int ReasonCodeId, AdjustmentStatus Status,
+ int AdjustmentId, string DocNo, int WarehouseId, int BranchId, int ReasonCodeId, AdjustmentStatus Status,
int CreatedBy, DateTime CreatedAt, string? GlJournalNo, DateTime? GlPostedAt,
IReadOnlyList Lines, IReadOnlyList LedgerRefs);
/// Row shape for GET /stock-adjustments — no lines/ledgerRefs (those need a per-row query).
public sealed record AdjustmentSummaryDto(
- int AdjustmentId, string DocNo, int WarehouseId, int ReasonCodeId, AdjustmentStatus Status,
+ int AdjustmentId, string DocNo, int WarehouseId, int BranchId, int ReasonCodeId, AdjustmentStatus Status,
int CreatedBy, DateTime CreatedAt, int LineCount, string? GlJournalNo);
// Requests ----------------------------------------------------------------------
@@ -31,6 +31,9 @@ public sealed class CreateAdjustmentLineInput
public sealed class CreateAdjustmentRequest
{
[Required] public int WarehouseId { get; set; }
+ /// Owning branch — warehouses are shared, so this is what actually scopes the
+ /// document (resolved via IBranchConfigService).
+ [Required] public int BranchId { get; set; }
/// Nullable so an omitted value is a distinct REASON_CODE_REQUIRED error, not 0.
public int? ReasonCodeId { get; set; }
[Required, MinLength(1)] public List Lines { get; set; } = new();
diff --git a/Backend/ERPCore/Dtos/Stock/CountDtos.cs b/Backend/ERPCore/Dtos/Stock/CountDtos.cs
index 209187f..f330163 100644
--- a/Backend/ERPCore/Dtos/Stock/CountDtos.cs
+++ b/Backend/ERPCore/Dtos/Stock/CountDtos.cs
@@ -8,12 +8,12 @@ namespace ERPCore.Dtos.Stock;
public sealed record CountLineDto(int CountLineId, int ItemId, int? BinId, decimal SystemQty, decimal? CountedQty, decimal? Variance);
public sealed record CountDto(
- int CountId, string DocNo, int WarehouseId, CountType CountType, CountStatus Status,
+ int CountId, string DocNo, int WarehouseId, int BranchId, CountType CountType, CountStatus Status,
int CreatedBy, DateTime CreatedAt, IReadOnlyList Lines);
/// Row shape for GET /stock-counts — line count instead of the lines themselves.
public sealed record CountSummaryDto(
- int CountId, string DocNo, int WarehouseId, CountType CountType, CountStatus Status,
+ int CountId, string DocNo, int WarehouseId, int BranchId, CountType CountType, CountStatus Status,
int CreatedBy, DateTime CreatedAt, int LineCount);
public sealed record CountPostResultDto(int CountId, CountStatus Status, int? AdjustmentId, string? GlJournalNo, IReadOnlyList LedgerRefs);
@@ -23,6 +23,9 @@ public sealed record CountPostResultDto(int CountId, CountStatus Status, int? Ad
public sealed class CreateCountRequest
{
[Required] public int WarehouseId { get; set; }
+ /// Owning branch — warehouses are shared, so this is what actually scopes the
+ /// document (resolved via IBranchConfigService).
+ [Required] public int BranchId { get; set; }
[Required, EnumDataType(typeof(CountType))] public CountType CountType { get; set; }
[Required, MinLength(1)] public List ItemIds { get; set; } = new();
}
diff --git a/Backend/ERPCore/Dtos/Stock/TransferDtos.cs b/Backend/ERPCore/Dtos/Stock/TransferDtos.cs
index 5d4d1d7..08cf57f 100644
--- a/Backend/ERPCore/Dtos/Stock/TransferDtos.cs
+++ b/Backend/ERPCore/Dtos/Stock/TransferDtos.cs
@@ -9,12 +9,12 @@ public sealed record TransferLineDto(
int TransferLineId, int ItemId, int? SrcBinId, int? DestBinId, int? BatchId, decimal Qty, decimal QtyReceived);
public sealed record TransferDto(
- int TransferId, string DocNo, int SrcWarehouseId, int DestWarehouseId,
+ int TransferId, string DocNo, int SrcWarehouseId, int DestWarehouseId, int BranchId,
TransferStatus Status, int CreatedBy, DateTime CreatedAt, IReadOnlyList Lines);
/// Row shape for GET /stock-transfers — line count instead of the lines themselves.
public sealed record TransferSummaryDto(
- int TransferId, string DocNo, int SrcWarehouseId, int DestWarehouseId,
+ int TransferId, string DocNo, int SrcWarehouseId, int DestWarehouseId, int BranchId,
TransferStatus Status, int CreatedBy, DateTime CreatedAt, int LineCount);
public sealed record ConsumedLayerDto(int LayerId, decimal QtyConsumed, decimal UnitCost);
@@ -42,6 +42,9 @@ public sealed class CreateTransferRequest
{
[Required] public int SrcWarehouseId { get; set; }
[Required] public int DestWarehouseId { get; set; }
+ /// Owning branch for this transfer — warehouses are shared, so this is what
+ /// actually scopes the document (resolved via IBranchConfigService).
+ [Required] public int BranchId { get; set; }
[Required, MinLength(1)] public List Lines { get; set; } = new();
}
diff --git a/Backend/ERPCore/Infra/Persistence/Configurations/GrnConfiguration.cs b/Backend/ERPCore/Infra/Persistence/Configurations/GrnConfiguration.cs
index 537922d..b1c7a27 100644
--- a/Backend/ERPCore/Infra/Persistence/Configurations/GrnConfiguration.cs
+++ b/Backend/ERPCore/Infra/Persistence/Configurations/GrnConfiguration.cs
@@ -22,11 +22,13 @@ public sealed class GrnConfiguration : IEntityTypeConfiguration
builder.HasOne(g => g.PurchaseOrder).WithMany().HasForeignKey(g => g.PoId).OnDelete(DeleteBehavior.Restrict);
builder.HasOne(g => g.Vendor).WithMany().HasForeignKey(g => g.VendorId).OnDelete(DeleteBehavior.Restrict);
builder.HasOne(g => g.Warehouse).WithMany().HasForeignKey(g => g.WarehouseId).OnDelete(DeleteBehavior.Restrict);
+ builder.HasOne(g => g.Branch).WithMany().HasForeignKey(g => g.BranchId).OnDelete(DeleteBehavior.Restrict);
builder.HasOne(g => g.Creator).WithMany().HasForeignKey(g => g.CreatedBy).OnDelete(DeleteBehavior.Restrict);
builder.HasOne(g => g.PurchaseInvoice).WithMany().HasForeignKey(g => g.PurchaseInvoiceId).OnDelete(DeleteBehavior.Restrict);
builder.HasIndex(g => g.Status);
builder.HasIndex(g => g.PoId);
+ builder.HasIndex(g => g.BranchId);
}
}
diff --git a/Backend/ERPCore/Infra/Persistence/Configurations/SalesInvoiceConfiguration.cs b/Backend/ERPCore/Infra/Persistence/Configurations/SalesInvoiceConfiguration.cs
index 9bdf744..7f20c4b 100644
--- a/Backend/ERPCore/Infra/Persistence/Configurations/SalesInvoiceConfiguration.cs
+++ b/Backend/ERPCore/Infra/Persistence/Configurations/SalesInvoiceConfiguration.cs
@@ -30,6 +30,11 @@ public sealed class SalesInvoiceConfiguration : IEntityTypeConfiguration x.WarehouseId)
.OnDelete(DeleteBehavior.Restrict);
+ builder.HasOne(x => x.Branch)
+ .WithMany()
+ .HasForeignKey(x => x.BranchId)
+ .OnDelete(DeleteBehavior.Restrict);
+
builder.Property(x => x.InvoiceType)
.HasConversion().HasMaxLength(20).IsRequired()
.HasDefaultValue(SalesInvoiceType.B2C);
@@ -47,6 +52,7 @@ public sealed class SalesInvoiceConfiguration : IEntityTypeConfiguration x.Status);
builder.HasIndex(x => x.InvoiceDate);
+ builder.HasIndex(x => x.BranchId);
builder.HasMany(x => x.Lines)
.WithOne(x => x.SalesInvoice)
diff --git a/Backend/ERPCore/Infra/Persistence/Configurations/StockAdjustmentConfiguration.cs b/Backend/ERPCore/Infra/Persistence/Configurations/StockAdjustmentConfiguration.cs
index 3152fb8..1a05216 100644
--- a/Backend/ERPCore/Infra/Persistence/Configurations/StockAdjustmentConfiguration.cs
+++ b/Backend/ERPCore/Infra/Persistence/Configurations/StockAdjustmentConfiguration.cs
@@ -21,7 +21,10 @@ public sealed class StockAdjustmentConfiguration : IEntityTypeConfiguration a.Warehouse).WithMany().HasForeignKey(a => a.WarehouseId).OnDelete(DeleteBehavior.Restrict);
builder.HasOne(a => a.ReasonCode).WithMany().HasForeignKey(a => a.ReasonCodeId).OnDelete(DeleteBehavior.Restrict);
+ builder.HasOne(a => a.Branch).WithMany().HasForeignKey(a => a.BranchId).OnDelete(DeleteBehavior.Restrict);
builder.HasOne(a => a.Creator).WithMany().HasForeignKey(a => a.CreatedBy).OnDelete(DeleteBehavior.Restrict);
+
+ builder.HasIndex(a => a.BranchId);
}
}
diff --git a/Backend/ERPCore/Infra/Persistence/Configurations/StockCountConfiguration.cs b/Backend/ERPCore/Infra/Persistence/Configurations/StockCountConfiguration.cs
index fa44f42..1aa2979 100644
--- a/Backend/ERPCore/Infra/Persistence/Configurations/StockCountConfiguration.cs
+++ b/Backend/ERPCore/Infra/Persistence/Configurations/StockCountConfiguration.cs
@@ -20,9 +20,11 @@ public sealed class StockCountConfiguration : IEntityTypeConfiguration c.RowVersion).IsRowVersion();
builder.HasOne(c => c.Warehouse).WithMany().HasForeignKey(c => c.WarehouseId).OnDelete(DeleteBehavior.Restrict);
+ builder.HasOne(c => c.Branch).WithMany().HasForeignKey(c => c.BranchId).OnDelete(DeleteBehavior.Restrict);
builder.HasOne(c => c.Creator).WithMany().HasForeignKey(c => c.CreatedBy).OnDelete(DeleteBehavior.Restrict);
builder.HasIndex(c => c.Status);
+ builder.HasIndex(c => c.BranchId);
}
}
diff --git a/Backend/ERPCore/Infra/Persistence/Configurations/StockTransferConfiguration.cs b/Backend/ERPCore/Infra/Persistence/Configurations/StockTransferConfiguration.cs
index 2aae8bb..24f5440 100644
--- a/Backend/ERPCore/Infra/Persistence/Configurations/StockTransferConfiguration.cs
+++ b/Backend/ERPCore/Infra/Persistence/Configurations/StockTransferConfiguration.cs
@@ -20,9 +20,11 @@ public sealed class StockTransferConfiguration : IEntityTypeConfiguration t.SrcWarehouse).WithMany().HasForeignKey(t => t.SrcWarehouseId).OnDelete(DeleteBehavior.Restrict);
builder.HasOne(t => t.DestWarehouse).WithMany().HasForeignKey(t => t.DestWarehouseId).OnDelete(DeleteBehavior.Restrict);
+ builder.HasOne(t => t.Branch).WithMany().HasForeignKey(t => t.BranchId).OnDelete(DeleteBehavior.Restrict);
builder.HasOne(t => t.Creator).WithMany().HasForeignKey(t => t.CreatedBy).OnDelete(DeleteBehavior.Restrict);
builder.HasIndex(t => t.Status);
+ builder.HasIndex(t => t.BranchId);
}
}
diff --git a/Backend/ERPCore/Migrations/20260908101847_AddBranchIdToDocuments.Designer.cs b/Backend/ERPCore/Migrations/20260908101847_AddBranchIdToDocuments.Designer.cs
new file mode 100644
index 0000000..cfb2eca
--- /dev/null
+++ b/Backend/ERPCore/Migrations/20260908101847_AddBranchIdToDocuments.Designer.cs
@@ -0,0 +1,8004 @@
+//
+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("20260908101847_AddBranchIdToDocuments")]
+ partial class AddBranchIdToDocuments
+ {
+ ///
+ 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