[CLAUDE] Domain+App+Infra+FE-Admin+FE-User: S34 Plan 4 G-H2 Mig 35 schema foundation
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m30s
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m30s
Phase 10.2 G-H2 Cấu hình HRM — 4 catalog lookup foundation deploy (BE CRUD +
FE forms DEFER S35 cho clean handoff).
Mig 35 `AddHrmConfigs` — 4 table mới:
- LeaveTypes (Code unique + Name + DaysPerYear decimal(5,2) + IsPaid +
RequiresAttachment) — 5 sample seed (ANNUAL 12d + SICK 30d + MATERNITY 180d
+ COMPASSIONATE 3d + UNPAID 0d)
- Holidays (Year + Date UNIQUE composite + Name + IsRecurring + IsPaid) —
10 sample VN 2026 (Tết Dương + 5 Tết Nguyên đán placeholder + Giỗ tổ +
30/4 + 1/5 + 2/9 + Quốc khánh)
- ShiftPatterns (Code unique + Name + StartTime/EndTime TimeOnly + BreakMinutes +
WorkDays comma string) — 3 sample (HC 8-17 T2-T6 + CA1 6-14 T2-T7 + CA2 14-22)
- OtPolicies (Code unique + 3 Multiplier decimal(4,2) + 3 MaxHours int) —
1 sample STANDARD (1.5x/2.0x/3.0x weekday/weekend/holiday + 4h/40h/200h cap
Luật Lao động VN 2019)
Files:
- Domain/Hrm/{LeaveType,Holiday,ShiftPattern,OtPolicy}.cs (4 entity AuditableEntity)
- Infrastructure/Persistence/Configurations/{LeaveType,Holiday,ShiftPattern,OtPolicy}Configuration.cs (4 EF Config UNIQUE indexes)
- IApplicationDbContext + ApplicationDbContext +4 DbSet
- Migrations/20260527075940_AddHrmConfigs.{cs,Designer.cs} + Snapshot updated (3-file rule)
- DbInitializer.SeedHrmConfigsAsync ~120 LOC seed sample (NOT gated DemoSeed per gotcha #51)
- MenuKeys.cs +HrmConfig sub-group + 4 leaf (LeaveTypes/Holidays/Shifts/OtPolicies) Order=2 dưới Hrm
- DbInitializer.SeedMenuTreeAsync +5 entry (sub-group + 4 leaf)
- fe-admin + fe-user menuKeys.ts +5 const mirror BE (Pattern 16-bis sync)
Verify:
- dotnet build PASS (2 warn DocxRenderer baseline, 0 error)
- dotnet test 130/130 PASS baseline preserve
- Mig 35 applied LocalDB SolutionErp_Dev — verified via dotnet ef database update
- 4 catalog table created + 5+10+3+1 = 19 sample row seed
Defer S35:
- Task 2 BE CQRS 4 catalog CRUD (16 endpoint) — Implementer Case 2 cookie-cutter
- Task 4 FE 2 app 4 catalog page (list/create/edit dialog) — Implementer Case 2
Cumulative S34 mig: 34 → 35 (+1). Tables 67 → 71 (+4). Menu keys 64 → 69 (+5).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@ -34,6 +34,12 @@ export const MenuKeys = {
|
||||
// Module Hồ sơ Nhân sự (Mig 34 — Phase 10.1 G-H1 Session 33, 2026-05-26)
|
||||
Hrm: 'Hrm',
|
||||
HrmHoSo: 'Hrm_HoSo',
|
||||
// Cấu hình HRM (Mig 35 — Phase 10.2 G-H2 Session 34, 2026-05-27)
|
||||
HrmConfig: 'Hrm_Config',
|
||||
HrmConfigLeaveTypes: 'Hrm_Config_LeaveTypes',
|
||||
HrmConfigHolidays: 'Hrm_Config_Holidays',
|
||||
HrmConfigShifts: 'Hrm_Config_Shifts',
|
||||
HrmConfigOtPolicies: 'Hrm_Config_OtPolicies',
|
||||
// Module Văn phòng số — Danh bạ nội bộ (Phase 10.2 G-O1 Session 34, 2026-05-27)
|
||||
Off: 'Off',
|
||||
OffDanhBa: 'Off_DanhBa',
|
||||
|
||||
@ -34,6 +34,12 @@ export const MenuKeys = {
|
||||
// Module Hồ sơ Nhân sự (Mig 34 — Phase 10.1 G-H1 Session 33, 2026-05-26)
|
||||
Hrm: 'Hrm',
|
||||
HrmHoSo: 'Hrm_HoSo',
|
||||
// Cấu hình HRM (Mig 35 — Phase 10.2 G-H2 Session 34, 2026-05-27)
|
||||
HrmConfig: 'Hrm_Config',
|
||||
HrmConfigLeaveTypes: 'Hrm_Config_LeaveTypes',
|
||||
HrmConfigHolidays: 'Hrm_Config_Holidays',
|
||||
HrmConfigShifts: 'Hrm_Config_Shifts',
|
||||
HrmConfigOtPolicies: 'Hrm_Config_OtPolicies',
|
||||
// Module Văn phòng số — Danh bạ nội bộ (Phase 10.2 G-O1 Session 34, 2026-05-27)
|
||||
Off: 'Off',
|
||||
OffDanhBa: 'Off_DanhBa',
|
||||
|
||||
@ -95,5 +95,13 @@ public interface IApplicationDbContext
|
||||
DbSet<EmployeeDocument> EmployeeDocuments { get; }
|
||||
DbSet<EmployeeCodeSequence> EmployeeCodeSequences { get; }
|
||||
|
||||
// Phase 10.2 G-H2 (Mig 35 — S34) — Cấu hình HRM 4 catalog lookup.
|
||||
// LeaveTypes + Holidays + ShiftPatterns + OtPolicies. Reference G-O4
|
||||
// LeaveRequest workflow + G-P1 chấm công OT calc business logic.
|
||||
DbSet<LeaveType> LeaveTypes { get; }
|
||||
DbSet<Holiday> Holidays { get; }
|
||||
DbSet<ShiftPattern> ShiftPatterns { get; }
|
||||
DbSet<OtPolicy> OtPolicies { get; }
|
||||
|
||||
Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
24
src/Backend/SolutionErp.Domain/Hrm/Holiday.cs
Normal file
24
src/Backend/SolutionErp.Domain/Hrm/Holiday.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using SolutionErp.Domain.Common;
|
||||
|
||||
namespace SolutionErp.Domain.Hrm;
|
||||
|
||||
// Phase 10.2 G-H2 (Mig 35 — S34 2026-05-27) — Ngày lễ Việt Nam.
|
||||
// Catalog admin maintain per year. IsRecurring=true (vd 1/1) → auto roll-over
|
||||
// năm sau (admin bulk clone). Non-recurring (vd Tết Nguyên đán date thay đổi
|
||||
// theo Âm lịch) → admin tạo mới mỗi năm.
|
||||
//
|
||||
// Sample seed 10 ngày lễ VN 2026: Tết Dương lịch (1/1) + Tết Nguyên đán
|
||||
// (5 ngày 28/1-1/2 đầu năm tới) + Giỗ tổ Hùng Vương (14/3 ÂL ~2026-04-20) +
|
||||
// 30/4 + 1/5 + 2/9 + Quốc khánh 3/9.
|
||||
public class Holiday : AuditableEntity
|
||||
{
|
||||
public int Year { get; set; } // 2026
|
||||
public DateOnly Date { get; set; } // UNIQUE composite (Year, Date)
|
||||
public string Name { get; set; } = string.Empty; // "Tết Dương lịch"
|
||||
|
||||
public bool IsRecurring { get; set; } // 1/1 lặp mỗi năm, Tết Âm lịch không
|
||||
public bool IsPaid { get; set; } = true; // Có lương / Không lương (mặc định có)
|
||||
|
||||
public bool IsActive { get; set; } = true;
|
||||
public string? Description { get; set; }
|
||||
}
|
||||
25
src/Backend/SolutionErp.Domain/Hrm/LeaveType.cs
Normal file
25
src/Backend/SolutionErp.Domain/Hrm/LeaveType.cs
Normal file
@ -0,0 +1,25 @@
|
||||
using SolutionErp.Domain.Common;
|
||||
|
||||
namespace SolutionErp.Domain.Hrm;
|
||||
|
||||
// Phase 10.2 G-H2 (Mig 35 — S34 2026-05-27) — Loại phép.
|
||||
// Catalog lookup table cho HRM Workflow Apps (G-O4 LeaveRequest).
|
||||
// Sample seed 5 loại: ANNUAL (12d) + SICK (30d) + MATERNITY (180d) +
|
||||
// COMPASSIONATE (3d) + UNPAID (0d, không giới hạn).
|
||||
public class LeaveType : AuditableEntity
|
||||
{
|
||||
public string Code { get; set; } = string.Empty; // UNIQUE — "ANNUAL", "SICK", ...
|
||||
public string Name { get; set; } = string.Empty; // "Phép năm", "Phép ốm"
|
||||
|
||||
// Số ngày max được nghỉ trong năm. 0 = không giới hạn (UNPAID).
|
||||
// decimal(5,2) cho phép half-day (vd 0.5d).
|
||||
public decimal DaysPerYear { get; set; }
|
||||
|
||||
public bool IsPaid { get; set; } = true; // Có lương / Không lương
|
||||
|
||||
// Yêu cầu đính kèm giấy tờ (vd Sick → giấy bác sĩ, Maternity → giấy KS).
|
||||
public bool RequiresAttachment { get; set; }
|
||||
|
||||
public bool IsActive { get; set; } = true;
|
||||
public string? Description { get; set; }
|
||||
}
|
||||
32
src/Backend/SolutionErp.Domain/Hrm/OtPolicy.cs
Normal file
32
src/Backend/SolutionErp.Domain/Hrm/OtPolicy.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using SolutionErp.Domain.Common;
|
||||
|
||||
namespace SolutionErp.Domain.Hrm;
|
||||
|
||||
// Phase 10.2 G-H2 (Mig 35 — S34 2026-05-27) — Chính sách tăng ca (OT).
|
||||
// Catalog admin define hệ số OT theo loại ngày + giới hạn max hour.
|
||||
// 1 OtPolicy hoạt động "default" cho toàn công ty (IsActive=true unique).
|
||||
//
|
||||
// Sample seed 1 default:
|
||||
// STANDARD: Weekday 1.5x / Weekend 2.0x / Holiday 3.0x
|
||||
// MaxHoursPerDay=4h, MaxHoursPerMonth=40h (Luật Lao động VN cap)
|
||||
//
|
||||
// Future G-P1 Chấm công attendance + G-O4 OtRequest workflow sẽ reference
|
||||
// OtPolicy.IsActive=true để calc lương + validate approval.
|
||||
public class OtPolicy : AuditableEntity
|
||||
{
|
||||
public string Code { get; set; } = string.Empty; // UNIQUE — "STANDARD"
|
||||
public string Name { get; set; } = string.Empty; // "Chính sách OT chuẩn"
|
||||
|
||||
// Hệ số nhân lương OT decimal(4,2) — vd 1.5 / 2.0 / 3.0.
|
||||
public decimal MultiplierWeekday { get; set; }
|
||||
public decimal MultiplierWeekend { get; set; }
|
||||
public decimal MultiplierHoliday { get; set; }
|
||||
|
||||
// Giới hạn OT — vd Luật Lao động VN max 4h/day, 40h/month, 200h/year.
|
||||
public int MaxHoursPerDay { get; set; }
|
||||
public int MaxHoursPerMonth { get; set; }
|
||||
public int MaxHoursPerYear { get; set; }
|
||||
|
||||
public bool IsActive { get; set; } = true;
|
||||
public string? Description { get; set; }
|
||||
}
|
||||
30
src/Backend/SolutionErp.Domain/Hrm/ShiftPattern.cs
Normal file
30
src/Backend/SolutionErp.Domain/Hrm/ShiftPattern.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using SolutionErp.Domain.Common;
|
||||
|
||||
namespace SolutionErp.Domain.Hrm;
|
||||
|
||||
// Phase 10.2 G-H2 (Mig 35 — S34 2026-05-27) — Ca làm việc.
|
||||
// Catalog admin define ca làm — assign cho NV qua EmployeeProfile (defer Phase 1.5
|
||||
// nếu user cần per-NV shift assignment) hoặc default "HC" cho toàn công ty.
|
||||
//
|
||||
// Sample seed 3 ca:
|
||||
// HC (Hành chính) — 8:00-17:00 Mon-Fri, nghỉ trưa 60 phút
|
||||
// CA1 (Ca sáng) — 6:00-14:00 Mon-Sat, nghỉ trưa 30 phút
|
||||
// CA2 (Ca chiều) — 14:00-22:00 Mon-Sat, nghỉ giữa ca 30 phút
|
||||
public class ShiftPattern : AuditableEntity
|
||||
{
|
||||
public string Code { get; set; } = string.Empty; // UNIQUE — "HC", "CA1", "CA2"
|
||||
public string Name { get; set; } = string.Empty; // "Hành chính", "Ca sáng"
|
||||
|
||||
public TimeOnly StartTime { get; set; } // 08:00
|
||||
public TimeOnly EndTime { get; set; } // 17:00
|
||||
|
||||
public int BreakMinutes { get; set; } // Phút nghỉ trưa / giữa ca
|
||||
|
||||
// Comma-separated weekday codes: "Mon,Tue,Wed,Thu,Fri" cho HC,
|
||||
// "Mon,Tue,Wed,Thu,Fri,Sat" cho CA1/CA2 (working Sat).
|
||||
// FE Designer multi-select chuyển → comma string. Flexibility cao hơn bitmask int.
|
||||
public string WorkDays { get; set; } = string.Empty;
|
||||
|
||||
public bool IsActive { get; set; } = true;
|
||||
public string? Description { get; set; }
|
||||
}
|
||||
@ -84,6 +84,12 @@ public static class MenuKeys
|
||||
// ============================================================
|
||||
public const string Hrm = "Hrm"; // root group
|
||||
public const string HrmHoSo = "Hrm_HoSo"; // Hồ sơ Nhân sự (list + detail + edit)
|
||||
// Phase 10.2 G-H2 (Mig 35 — S34) — Cấu hình HRM 4 catalog lookup.
|
||||
public const string HrmConfig = "Hrm_Config"; // sub-group cấu hình
|
||||
public const string HrmConfigLeaveTypes = "Hrm_Config_LeaveTypes"; // Loại phép
|
||||
public const string HrmConfigHolidays = "Hrm_Config_Holidays"; // Ngày lễ
|
||||
public const string HrmConfigShifts = "Hrm_Config_Shifts"; // Ca làm việc
|
||||
public const string HrmConfigOtPolicies = "Hrm_Config_OtPolicies"; // Chính sách OT
|
||||
|
||||
// ============================================================
|
||||
// Module Văn phòng số (Phase 10.2 G-O1+ S34 2026-05-27).
|
||||
@ -119,6 +125,7 @@ public static class MenuKeys
|
||||
PurchaseEvaluations,
|
||||
Budgets, BudgetList, BudgetCreate, BudgetPending,
|
||||
Hrm, HrmHoSo, // Mig 34 — Phase 10.1
|
||||
HrmConfig, HrmConfigLeaveTypes, HrmConfigHolidays, HrmConfigShifts, HrmConfigOtPolicies, // Mig 35 — Phase 10.2 G-H2
|
||||
Off, OffDanhBa, // Phase 10.2 G-O1 — Văn phòng số
|
||||
System, Users, Roles, Permissions, MenuVisibility, Workflows, PeWorkflows,
|
||||
ApprovalWorkflowsV2, ApprovalWorkflowDuyetNccV2, ApprovalWorkflowDuyetNccPhuongAnV2, // Mig 22
|
||||
|
||||
@ -90,6 +90,12 @@ public class ApplicationDbContext
|
||||
public DbSet<EmployeeDocument> EmployeeDocuments => Set<EmployeeDocument>();
|
||||
public DbSet<EmployeeCodeSequence> EmployeeCodeSequences => Set<EmployeeCodeSequence>();
|
||||
|
||||
// Phase 10.2 G-H2 (Mig 35 — S34) — Cấu hình HRM 4 catalog lookup.
|
||||
public DbSet<LeaveType> LeaveTypes => Set<LeaveType>();
|
||||
public DbSet<Holiday> Holidays => Set<Holiday>();
|
||||
public DbSet<ShiftPattern> ShiftPatterns => Set<ShiftPattern>();
|
||||
public DbSet<OtPolicy> OtPolicies => Set<OtPolicy>();
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder builder)
|
||||
{
|
||||
base.OnModelCreating(builder);
|
||||
|
||||
@ -0,0 +1,19 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using SolutionErp.Domain.Hrm;
|
||||
|
||||
namespace SolutionErp.Infrastructure.Persistence.Configurations;
|
||||
|
||||
// EF Mig 35 G-H2 (S34) — Ngày lễ. UNIQUE composite (Year, Date).
|
||||
public class HolidayConfiguration : IEntityTypeConfiguration<Holiday>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<Holiday> e)
|
||||
{
|
||||
e.ToTable("Holidays");
|
||||
|
||||
e.Property(x => x.Name).HasMaxLength(200).IsRequired();
|
||||
e.Property(x => x.Description).HasMaxLength(500);
|
||||
|
||||
e.HasIndex(x => new { x.Year, x.Date }).IsUnique();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using SolutionErp.Domain.Hrm;
|
||||
|
||||
namespace SolutionErp.Infrastructure.Persistence.Configurations;
|
||||
|
||||
// EF Mig 35 G-H2 (S34) — Loại phép. Catalog standalone, no FK.
|
||||
public class LeaveTypeConfiguration : IEntityTypeConfiguration<LeaveType>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<LeaveType> e)
|
||||
{
|
||||
e.ToTable("LeaveTypes");
|
||||
|
||||
e.Property(x => x.Code).HasMaxLength(50).IsRequired();
|
||||
e.Property(x => x.Name).HasMaxLength(200).IsRequired();
|
||||
e.Property(x => x.DaysPerYear).HasColumnType("decimal(5,2)");
|
||||
e.Property(x => x.Description).HasMaxLength(500);
|
||||
|
||||
e.HasIndex(x => x.Code).IsUnique();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using SolutionErp.Domain.Hrm;
|
||||
|
||||
namespace SolutionErp.Infrastructure.Persistence.Configurations;
|
||||
|
||||
// EF Mig 35 G-H2 (S34) — Chính sách OT. Catalog standalone.
|
||||
// Future business logic: G-P1 chấm công + G-O4 OtRequest reference IsActive=true.
|
||||
public class OtPolicyConfiguration : IEntityTypeConfiguration<OtPolicy>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<OtPolicy> e)
|
||||
{
|
||||
e.ToTable("OtPolicies");
|
||||
|
||||
e.Property(x => x.Code).HasMaxLength(50).IsRequired();
|
||||
e.Property(x => x.Name).HasMaxLength(200).IsRequired();
|
||||
e.Property(x => x.MultiplierWeekday).HasColumnType("decimal(4,2)");
|
||||
e.Property(x => x.MultiplierWeekend).HasColumnType("decimal(4,2)");
|
||||
e.Property(x => x.MultiplierHoliday).HasColumnType("decimal(4,2)");
|
||||
e.Property(x => x.Description).HasMaxLength(500);
|
||||
|
||||
e.HasIndex(x => x.Code).IsUnique();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using SolutionErp.Domain.Hrm;
|
||||
|
||||
namespace SolutionErp.Infrastructure.Persistence.Configurations;
|
||||
|
||||
// EF Mig 35 G-H2 (S34) — Ca làm việc. Catalog standalone.
|
||||
public class ShiftPatternConfiguration : IEntityTypeConfiguration<ShiftPattern>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<ShiftPattern> e)
|
||||
{
|
||||
e.ToTable("ShiftPatterns");
|
||||
|
||||
e.Property(x => x.Code).HasMaxLength(20).IsRequired();
|
||||
e.Property(x => x.Name).HasMaxLength(200).IsRequired();
|
||||
e.Property(x => x.WorkDays).HasMaxLength(100).IsRequired(); // "Mon,Tue,Wed,Thu,Fri"
|
||||
e.Property(x => x.Description).HasMaxLength(500);
|
||||
|
||||
e.HasIndex(x => x.Code).IsUnique();
|
||||
}
|
||||
}
|
||||
@ -92,6 +92,9 @@ public static class DbInitializer
|
||||
// (infrastructure data, mirror Mig 32 SeedSampleContractWorkflowV2
|
||||
// gotcha #51 lesson). Bro UAT update field nhạy cảm qua FE Hồ sơ NS.
|
||||
await SeedDemoEmployeeProfilesAsync(db, userManager, logger);
|
||||
// Plan G-H2 (Mig 35 S34 2026-05-27) — Cấu hình HRM 4 catalog. Infrastructure
|
||||
// data (NOT gated DemoSeed flag) — Workflow Apps reference cần data ngày 1.
|
||||
await SeedHrmConfigsAsync(db, logger);
|
||||
await SeedMenuTreeAsync(db, logger);
|
||||
await SeedAdminPermissionsAsync(db, roleManager, logger);
|
||||
await SeedDemoMasterDataAsync(db, logger);
|
||||
@ -1484,6 +1487,13 @@ public static class DbInitializer
|
||||
(MenuKeys.Hrm, "Nhân sự", null, 28, "UserCircle"),
|
||||
(MenuKeys.HrmHoSo, "Hồ sơ Nhân sự", MenuKeys.Hrm, 1, "ContactRound"),
|
||||
|
||||
// Phase 10.2 G-H2 (Mig 35 — S34). Sub-group "Cấu hình HRM" + 4 catalog leaf.
|
||||
(MenuKeys.HrmConfig, "Cấu hình HRM", MenuKeys.Hrm, 2, "Settings2"),
|
||||
(MenuKeys.HrmConfigLeaveTypes, "Loại phép", MenuKeys.HrmConfig, 1, "CalendarOff"),
|
||||
(MenuKeys.HrmConfigHolidays, "Ngày lễ", MenuKeys.HrmConfig, 2, "PartyPopper"),
|
||||
(MenuKeys.HrmConfigShifts, "Ca làm việc", MenuKeys.HrmConfig, 3, "Clock"),
|
||||
(MenuKeys.HrmConfigOtPolicies, "Chính sách OT", MenuKeys.HrmConfig, 4, "TimerReset"),
|
||||
|
||||
// Module Văn phòng số (Phase 10.2 G-O1+ S34). 1 root + leaf Danh bạ.
|
||||
// Future leaf: Off_PhongHop (G-O2) + workflow apps Off_DeXuat/DonTu/DatXe/ItTicket.
|
||||
(MenuKeys.Off, "Văn phòng số", null, 29, "Briefcase"),
|
||||
@ -2029,4 +2039,121 @@ public static class DbInitializer
|
||||
"SeedDemoEmployeeProfilesAsync: seeded {Count} profiles + 1 sequence row NV/{Year} LastSeq={Seq}",
|
||||
seq, year, seq);
|
||||
}
|
||||
|
||||
// Phase 10.2 G-H2 (Mig 35 — S34 2026-05-27) — Cấu hình HRM 4 catalog seed sample.
|
||||
// INFRASTRUCTURE seed (NOT gated DemoSeed flag — gotcha #51 lesson).
|
||||
// Workflow Apps Phase 10.3 (G-O4 LeaveRequest, G-P1 chấm công OT) reference
|
||||
// 4 catalog active rows ngày 1 → admin có thể tinh chỉnh sau qua Designer UI.
|
||||
private static async Task SeedHrmConfigsAsync(ApplicationDbContext db, ILogger logger)
|
||||
{
|
||||
if (await db.LeaveTypes.AnyAsync()
|
||||
&& await db.Holidays.AnyAsync()
|
||||
&& await db.ShiftPatterns.AnyAsync()
|
||||
&& await db.OtPolicies.AnyAsync())
|
||||
{
|
||||
logger.LogInformation("SeedHrmConfigsAsync: skip — đã có 4 catalog.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 5 LeaveType — Luật Lao động VN 2019 reference.
|
||||
if (!await db.LeaveTypes.AnyAsync())
|
||||
{
|
||||
db.LeaveTypes.AddRange(
|
||||
new LeaveType
|
||||
{
|
||||
Code = "ANNUAL", Name = "Phép năm", DaysPerYear = 12m, IsPaid = true,
|
||||
RequiresAttachment = false,
|
||||
Description = "Phép năm tiêu chuẩn. Luật quy định tối thiểu 12 ngày/năm cho lao động làm việc đủ 12 tháng.",
|
||||
},
|
||||
new LeaveType
|
||||
{
|
||||
Code = "SICK", Name = "Phép ốm", DaysPerYear = 30m, IsPaid = true,
|
||||
RequiresAttachment = true,
|
||||
Description = "Nghỉ ốm có giấy bác sĩ. BHXH chi trả 75% lương.",
|
||||
},
|
||||
new LeaveType
|
||||
{
|
||||
Code = "MATERNITY", Name = "Phép thai sản", DaysPerYear = 180m, IsPaid = true,
|
||||
RequiresAttachment = true,
|
||||
Description = "Phép thai sản 6 tháng (180 ngày) cho lao động nữ. BHXH chi trả 100%.",
|
||||
},
|
||||
new LeaveType
|
||||
{
|
||||
Code = "COMPASSIONATE", Name = "Phép việc riêng", DaysPerYear = 3m, IsPaid = true,
|
||||
RequiresAttachment = false,
|
||||
Description = "Cưới hỏi / hiếu / việc gia đình quan trọng. Luật quy định 1-3 ngày tùy lý do.",
|
||||
},
|
||||
new LeaveType
|
||||
{
|
||||
Code = "UNPAID", Name = "Phép không lương", DaysPerYear = 0m, IsPaid = false,
|
||||
RequiresAttachment = false,
|
||||
Description = "Nghỉ không lương — không giới hạn, cần BOD duyệt.",
|
||||
});
|
||||
}
|
||||
|
||||
// 10 Holiday VN 2026 (placeholder Tết Nguyên đán date — admin update khi có lịch chính thức).
|
||||
if (!await db.Holidays.AnyAsync())
|
||||
{
|
||||
db.Holidays.AddRange(
|
||||
new Holiday { Year = 2026, Date = new DateOnly(2026, 1, 1), Name = "Tết Dương lịch", IsRecurring = true },
|
||||
// Tết Nguyên đán 2026 (Bính Ngọ) — 17/2 mùng 1 Âm — 5 ngày 16-20/2
|
||||
new Holiday { Year = 2026, Date = new DateOnly(2026, 2, 16), Name = "Tết Nguyên đán (30 Tết)", IsRecurring = false },
|
||||
new Holiday { Year = 2026, Date = new DateOnly(2026, 2, 17), Name = "Tết Nguyên đán (Mùng 1)", IsRecurring = false },
|
||||
new Holiday { Year = 2026, Date = new DateOnly(2026, 2, 18), Name = "Tết Nguyên đán (Mùng 2)", IsRecurring = false },
|
||||
new Holiday { Year = 2026, Date = new DateOnly(2026, 2, 19), Name = "Tết Nguyên đán (Mùng 3)", IsRecurring = false },
|
||||
new Holiday { Year = 2026, Date = new DateOnly(2026, 2, 20), Name = "Tết Nguyên đán (Mùng 4)", IsRecurring = false },
|
||||
// Giỗ tổ Hùng Vương 10/3 Âm — 2026 placeholder 14/4
|
||||
new Holiday { Year = 2026, Date = new DateOnly(2026, 4, 14), Name = "Giỗ tổ Hùng Vương", IsRecurring = false },
|
||||
new Holiday { Year = 2026, Date = new DateOnly(2026, 4, 30), Name = "Giải phóng miền Nam", IsRecurring = true },
|
||||
new Holiday { Year = 2026, Date = new DateOnly(2026, 5, 1), Name = "Quốc tế Lao động", IsRecurring = true },
|
||||
new Holiday { Year = 2026, Date = new DateOnly(2026, 9, 2), Name = "Quốc khánh", IsRecurring = true });
|
||||
}
|
||||
|
||||
// 3 ShiftPattern — hành chính + 2 ca xoay.
|
||||
if (!await db.ShiftPatterns.AnyAsync())
|
||||
{
|
||||
db.ShiftPatterns.AddRange(
|
||||
new ShiftPattern
|
||||
{
|
||||
Code = "HC", Name = "Hành chính",
|
||||
StartTime = new TimeOnly(8, 0), EndTime = new TimeOnly(17, 0),
|
||||
BreakMinutes = 60, WorkDays = "Mon,Tue,Wed,Thu,Fri",
|
||||
Description = "Ca hành chính chuẩn 8-17h, nghỉ trưa 60 phút, T2-T6.",
|
||||
},
|
||||
new ShiftPattern
|
||||
{
|
||||
Code = "CA1", Name = "Ca sáng",
|
||||
StartTime = new TimeOnly(6, 0), EndTime = new TimeOnly(14, 0),
|
||||
BreakMinutes = 30, WorkDays = "Mon,Tue,Wed,Thu,Fri,Sat",
|
||||
Description = "Ca sáng 6-14h, nghỉ giữa ca 30 phút, T2-T7.",
|
||||
},
|
||||
new ShiftPattern
|
||||
{
|
||||
Code = "CA2", Name = "Ca chiều",
|
||||
StartTime = new TimeOnly(14, 0), EndTime = new TimeOnly(22, 0),
|
||||
BreakMinutes = 30, WorkDays = "Mon,Tue,Wed,Thu,Fri,Sat",
|
||||
Description = "Ca chiều 14-22h, nghỉ giữa ca 30 phút, T2-T7.",
|
||||
});
|
||||
}
|
||||
|
||||
// 1 OtPolicy default — Luật Lao động VN cap.
|
||||
if (!await db.OtPolicies.AnyAsync())
|
||||
{
|
||||
db.OtPolicies.Add(new OtPolicy
|
||||
{
|
||||
Code = "STANDARD",
|
||||
Name = "Chính sách OT chuẩn",
|
||||
MultiplierWeekday = 1.5m,
|
||||
MultiplierWeekend = 2.0m,
|
||||
MultiplierHoliday = 3.0m,
|
||||
MaxHoursPerDay = 4,
|
||||
MaxHoursPerMonth = 40,
|
||||
MaxHoursPerYear = 200,
|
||||
Description = "Hệ số 1.5x/2.0x/3.0x theo Luật Lao động VN 2019. Max 4h/ngày, 40h/tháng, 200h/năm.",
|
||||
});
|
||||
}
|
||||
|
||||
await db.SaveChangesAsync();
|
||||
logger.LogInformation("SeedHrmConfigsAsync: seeded 5 LeaveTypes + 10 Holidays 2026 + 3 ShiftPatterns + 1 OtPolicy default.");
|
||||
}
|
||||
}
|
||||
|
||||
4968
src/Backend/SolutionErp.Infrastructure/Persistence/Migrations/20260527075940_AddHrmConfigs.Designer.cs
generated
Normal file
4968
src/Backend/SolutionErp.Infrastructure/Persistence/Migrations/20260527075940_AddHrmConfigs.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,159 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace SolutionErp.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddHrmConfigs : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Holidays",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
Year = table.Column<int>(type: "int", nullable: false),
|
||||
Date = table.Column<DateOnly>(type: "date", nullable: false),
|
||||
Name = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
|
||||
IsRecurring = table.Column<bool>(type: "bit", nullable: false),
|
||||
IsPaid = table.Column<bool>(type: "bit", nullable: false),
|
||||
IsActive = table.Column<bool>(type: "bit", nullable: false),
|
||||
Description = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: true),
|
||||
CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||
UpdatedAt = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||
CreatedBy = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||
UpdatedBy = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||
IsDeleted = table.Column<bool>(type: "bit", nullable: false),
|
||||
DeletedAt = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||
DeletedBy = table.Column<Guid>(type: "uniqueidentifier", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Holidays", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "LeaveTypes",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
Code = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: false),
|
||||
Name = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
|
||||
DaysPerYear = table.Column<decimal>(type: "decimal(5,2)", nullable: false),
|
||||
IsPaid = table.Column<bool>(type: "bit", nullable: false),
|
||||
RequiresAttachment = table.Column<bool>(type: "bit", nullable: false),
|
||||
IsActive = table.Column<bool>(type: "bit", nullable: false),
|
||||
Description = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: true),
|
||||
CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||
UpdatedAt = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||
CreatedBy = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||
UpdatedBy = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||
IsDeleted = table.Column<bool>(type: "bit", nullable: false),
|
||||
DeletedAt = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||
DeletedBy = table.Column<Guid>(type: "uniqueidentifier", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_LeaveTypes", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "OtPolicies",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
Code = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: false),
|
||||
Name = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
|
||||
MultiplierWeekday = table.Column<decimal>(type: "decimal(4,2)", nullable: false),
|
||||
MultiplierWeekend = table.Column<decimal>(type: "decimal(4,2)", nullable: false),
|
||||
MultiplierHoliday = table.Column<decimal>(type: "decimal(4,2)", nullable: false),
|
||||
MaxHoursPerDay = table.Column<int>(type: "int", nullable: false),
|
||||
MaxHoursPerMonth = table.Column<int>(type: "int", nullable: false),
|
||||
MaxHoursPerYear = table.Column<int>(type: "int", nullable: false),
|
||||
IsActive = table.Column<bool>(type: "bit", nullable: false),
|
||||
Description = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: true),
|
||||
CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||
UpdatedAt = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||
CreatedBy = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||
UpdatedBy = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||
IsDeleted = table.Column<bool>(type: "bit", nullable: false),
|
||||
DeletedAt = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||
DeletedBy = table.Column<Guid>(type: "uniqueidentifier", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_OtPolicies", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "ShiftPatterns",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
Code = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: false),
|
||||
Name = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
|
||||
StartTime = table.Column<TimeOnly>(type: "time", nullable: false),
|
||||
EndTime = table.Column<TimeOnly>(type: "time", nullable: false),
|
||||
BreakMinutes = table.Column<int>(type: "int", nullable: false),
|
||||
WorkDays = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
|
||||
IsActive = table.Column<bool>(type: "bit", nullable: false),
|
||||
Description = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: true),
|
||||
CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||
UpdatedAt = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||
CreatedBy = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||
UpdatedBy = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||
IsDeleted = table.Column<bool>(type: "bit", nullable: false),
|
||||
DeletedAt = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||
DeletedBy = table.Column<Guid>(type: "uniqueidentifier", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_ShiftPatterns", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Holidays_Year_Date",
|
||||
table: "Holidays",
|
||||
columns: new[] { "Year", "Date" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_LeaveTypes_Code",
|
||||
table: "LeaveTypes",
|
||||
column: "Code",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OtPolicies_Code",
|
||||
table: "OtPolicies",
|
||||
column: "Code",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ShiftPatterns_Code",
|
||||
table: "ShiftPatterns",
|
||||
column: "Code",
|
||||
unique: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "Holidays");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "LeaveTypes");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "OtPolicies");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "ShiftPatterns");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2494,6 +2494,262 @@ namespace SolutionErp.Infrastructure.Persistence.Migrations
|
||||
b.ToTable("EmployeeWorkHistories", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SolutionErp.Domain.Hrm.Holiday", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<Guid?>("CreatedBy")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<DateOnly>("Date")
|
||||
.HasColumnType("date");
|
||||
|
||||
b.Property<DateTime?>("DeletedAt")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<Guid?>("DeletedBy")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasMaxLength(500)
|
||||
.HasColumnType("nvarchar(500)");
|
||||
|
||||
b.Property<bool>("IsActive")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<bool>("IsDeleted")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<bool>("IsPaid")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<bool>("IsRecurring")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("nvarchar(200)");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<Guid?>("UpdatedBy")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<int>("Year")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Year", "Date")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Holidays", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SolutionErp.Domain.Hrm.LeaveType", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("Code")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("nvarchar(50)");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<Guid?>("CreatedBy")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<decimal>("DaysPerYear")
|
||||
.HasColumnType("decimal(5,2)");
|
||||
|
||||
b.Property<DateTime?>("DeletedAt")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<Guid?>("DeletedBy")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasMaxLength(500)
|
||||
.HasColumnType("nvarchar(500)");
|
||||
|
||||
b.Property<bool>("IsActive")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<bool>("IsDeleted")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<bool>("IsPaid")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("nvarchar(200)");
|
||||
|
||||
b.Property<bool>("RequiresAttachment")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<Guid?>("UpdatedBy")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Code")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("LeaveTypes", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SolutionErp.Domain.Hrm.OtPolicy", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("Code")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("nvarchar(50)");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<Guid?>("CreatedBy")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<DateTime?>("DeletedAt")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<Guid?>("DeletedBy")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasMaxLength(500)
|
||||
.HasColumnType("nvarchar(500)");
|
||||
|
||||
b.Property<bool>("IsActive")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<bool>("IsDeleted")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<int>("MaxHoursPerDay")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("MaxHoursPerMonth")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("MaxHoursPerYear")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<decimal>("MultiplierHoliday")
|
||||
.HasColumnType("decimal(4,2)");
|
||||
|
||||
b.Property<decimal>("MultiplierWeekday")
|
||||
.HasColumnType("decimal(4,2)");
|
||||
|
||||
b.Property<decimal>("MultiplierWeekend")
|
||||
.HasColumnType("decimal(4,2)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("nvarchar(200)");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<Guid?>("UpdatedBy")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Code")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("OtPolicies", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SolutionErp.Domain.Hrm.ShiftPattern", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<int>("BreakMinutes")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Code")
|
||||
.IsRequired()
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("nvarchar(20)");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<Guid?>("CreatedBy")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<DateTime?>("DeletedAt")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<Guid?>("DeletedBy")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasMaxLength(500)
|
||||
.HasColumnType("nvarchar(500)");
|
||||
|
||||
b.Property<TimeOnly>("EndTime")
|
||||
.HasColumnType("time");
|
||||
|
||||
b.Property<bool>("IsActive")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<bool>("IsDeleted")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("nvarchar(200)");
|
||||
|
||||
b.Property<TimeOnly>("StartTime")
|
||||
.HasColumnType("time");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<Guid?>("UpdatedBy")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("WorkDays")
|
||||
.IsRequired()
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("nvarchar(100)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Code")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("ShiftPatterns", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SolutionErp.Domain.Identity.MenuItem", b =>
|
||||
{
|
||||
b.Property<string>("Key")
|
||||
|
||||
Reference in New Issue
Block a user