[CLAUDE] Domain+App+Infra: Role ShortName + User Department/Position + 13 demo users (migration 11)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m53s
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m53s
User feedback: chi tiết hóa Users/Phòng ban + gán roles. Roles label tiếng Việt có Mã (ShortName) + Tên đầy đủ (Description). ## Entity changes ### Role (Domain/Identity/Role.cs) + ShortName (max 50) — Mã viết tắt VN: QTV/BOD/CCM/PRO/FIN/... + Description (đã có) — Tên đầy đủ VN - Identity Name = code English giữ nguyên (FK + [Authorize] attr) ### User (Domain/Identity/User.cs) + DepartmentId Guid? FK Departments (Restrict — không xóa dept nếu user reference) + Position string? max 200 — chức vụ free text ## Migration 11: AddRoleShortNameAndUserDepartment 3-file rule. Apply LocalDB OK. DB total: 36 tables (không tăng — chỉ thêm cột vào existing). ## Seed VN labels (12 roles) | Code | ShortName | Description | |---|---|---| | Admin | QTV | Quản trị viên hệ thống | | Drafter | NV.PB | Nhân viên phòng ban (soạn thảo HĐ) | | DeptManager | TPB | Trưởng phòng ban | | ProjectManager | PM | Giám đốc dự án | | Procurement | PRO | Phòng Cung ứng | | CostControl | CCM | Phòng Kiểm soát chi phí | | Finance | FIN | Phòng Tài chính | | Accounting | ACT | Phòng Kế toán | | Equipment | EQU | Phòng Thiết bị | | Director | BOD | Ban Giám đốc | | AuthorizedSigner | NĐUQ | Người được Ủy quyền ký HĐ | | HrAdmin | HRA | Phòng Nhân sự - Hành chính | SeedRolesAsync idempotent + backfill (existing role thiếu ShortName/ Description → update). ## Seed 13 demo users Default password: User@123456 (warn log để rotate prod). Coverage full org chart: - bod.huynh (Tổng GĐ — Director, BOD dept) - bod.le (Phó GĐ NĐUQ — AuthorizedSigner, BOD dept) - pm.nguyen (PM FLOCK 01 — ProjectManager, PM dept) - ccm.tran (TPB CCM — CostControl + DeptManager, CCM dept) - pro.pham (TPB PRO — Procurement + DeptManager, PRO dept) - fin.do, act.vu, equ.bui, hra.dang (TPB respective dept) - qs.hoang, qs.ngo (Drafter — QS dept) - nv.cao, nv.dinh (Drafter — PRO/FIN dept) Idempotent (skip nếu email đã tồn tại). ## DTOs + Commands updated - RoleDto + ShortName field - UserDto + DepartmentId/DepartmentName/Position - CreateUserCommand + DepartmentId/Position params (defaults null) - UpdateUserCommand + DepartmentId/Position - ListUsersQueryHandler load dept names denormalize per page - UpdateUserCommandHandler set UpdatedAt ## Note FE updates (UsersPage dept dropdown + role label VN) ở commit kế tiếp. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace SolutionErp.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddRoleShortNameAndUserDepartment : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<Guid>(
|
||||
name: "DepartmentId",
|
||||
table: "Users",
|
||||
type: "uniqueidentifier",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Position",
|
||||
table: "Users",
|
||||
type: "nvarchar(200)",
|
||||
maxLength: 200,
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "ShortName",
|
||||
table: "Roles",
|
||||
type: "nvarchar(50)",
|
||||
maxLength: 50,
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Users_DepartmentId",
|
||||
table: "Users",
|
||||
column: "DepartmentId");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Users_Departments_DepartmentId",
|
||||
table: "Users",
|
||||
column: "DepartmentId",
|
||||
principalTable: "Departments",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Users_Departments_DepartmentId",
|
||||
table: "Users");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Users_DepartmentId",
|
||||
table: "Users");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "DepartmentId",
|
||||
table: "Users");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Position",
|
||||
table: "Users");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ShortName",
|
||||
table: "Roles");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1311,6 +1311,10 @@ namespace SolutionErp.Infrastructure.Persistence.Migrations
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("nvarchar(256)");
|
||||
|
||||
b.Property<string>("ShortName")
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("nvarchar(50)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedName")
|
||||
@ -1337,6 +1341,9 @@ namespace SolutionErp.Infrastructure.Persistence.Migrations
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<Guid?>("DepartmentId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("nvarchar(256)");
|
||||
@ -1375,6 +1382,10 @@ namespace SolutionErp.Infrastructure.Persistence.Migrations
|
||||
b.Property<bool>("PhoneNumberConfirmed")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<string>("Position")
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("nvarchar(200)");
|
||||
|
||||
b.Property<string>("RefreshToken")
|
||||
.HasMaxLength(512)
|
||||
.HasColumnType("nvarchar(512)");
|
||||
@ -1397,6 +1408,8 @@ namespace SolutionErp.Infrastructure.Persistence.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("DepartmentId");
|
||||
|
||||
b.HasIndex("NormalizedEmail")
|
||||
.HasDatabaseName("EmailIndex");
|
||||
|
||||
@ -2114,6 +2127,14 @@ namespace SolutionErp.Infrastructure.Persistence.Migrations
|
||||
b.Navigation("Role");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SolutionErp.Domain.Identity.User", b =>
|
||||
{
|
||||
b.HasOne("SolutionErp.Domain.Master.Department", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("DepartmentId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SolutionErp.Domain.Contracts.Contract", b =>
|
||||
{
|
||||
b.Navigation("Approvals");
|
||||
|
||||
Reference in New Issue
Block a user