[CLAUDE] PurchaseEvaluation: demo seed 4 phieu + MaPhieu atomic sequence + Pe_* perm defaults
Polish session tiep cua PE module skeleton (commit 2c6f0ca..3990066):
3 task A (MISSING in MVP) khac STATUS.md In Progress:
1. Demo PE data seed (SeedDemoPurchaseEvaluationsAsync)
- 4 phieu varied A/B x phase: A-001 DangSoanThao (mo), A-002
ChoCEODuyetNCC (winner+9 quotes), A-003 DaDuyet (chua tao HD,
PaymentTerms JSON), B-001 ChoDuAn (5-step giua chung).
- Idempotent: skip-if-[DEMO]-exists.
- Approval history dung policy A (3-step) hoac B (5-step).
2. MaPhieu atomic sequence — Migration 13
- Format PE/{YYYY}/{TypeLetter}/{Seq:D3} (vd PE/2026/A/001).
- PurchaseEvaluationCodeSequence entity (Prefix PK).
- IPurchaseEvaluationCodeGenerator + impl SERIALIZABLE
transaction (mirror ContractCodeGenerator 1:1).
- Replace Random.Shared trong CreatePurchaseEvaluationCommandHandler.
- Migration AddPurchaseEvaluationCodeSequences (1 bang).
3. Pe_* permission defaults
- SeedPurchaseEvaluationPermissionDefaultsAsync — 7 role business x 9 menu key.
- Drafter/DeptManager/Procurement: R+C+U; CostControl/PM/Director/AuthorizedSigner: R+U.
- DeptManager them Delete (xoa nhap).
- Idempotent per-(roleId x menuKey).
Build: 0 error, 2 warning (pre-existing DocxRenderer).
Files: 4 new + 8 modified (1 migration + entity + generator + DI + 2 ctx + 2 features).
Resolves: STATUS.md In Progress §A — 3 item PE MISSING.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@ -56,6 +56,7 @@ public interface IApplicationDbContext
|
||||
DbSet<PurchaseEvaluationWorkflowDefinition> PurchaseEvaluationWorkflowDefinitions { get; }
|
||||
DbSet<PurchaseEvaluationWorkflowStep> PurchaseEvaluationWorkflowSteps { get; }
|
||||
DbSet<PurchaseEvaluationWorkflowStepApprover> PurchaseEvaluationWorkflowStepApprovers { get; }
|
||||
DbSet<PurchaseEvaluationCodeSequence> PurchaseEvaluationCodeSequences { get; }
|
||||
|
||||
Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
@ -39,7 +39,8 @@ public class CreatePurchaseEvaluationCommandValidator : AbstractValidator<Create
|
||||
public class CreatePurchaseEvaluationCommandHandler(
|
||||
IApplicationDbContext db,
|
||||
ICurrentUser currentUser,
|
||||
IPurchaseEvaluationWorkflowService workflow) : IRequestHandler<CreatePurchaseEvaluationCommand, Guid>
|
||||
IPurchaseEvaluationWorkflowService workflow,
|
||||
IPurchaseEvaluationCodeGenerator codeGen) : IRequestHandler<CreatePurchaseEvaluationCommand, Guid>
|
||||
{
|
||||
public async Task<Guid> Handle(CreatePurchaseEvaluationCommand request, CancellationToken ct)
|
||||
{
|
||||
@ -67,8 +68,9 @@ public class CreatePurchaseEvaluationCommandHandler(
|
||||
workflow.GetPhaseSla(PurchaseEvaluationPhase.DangSoanThao) ?? TimeSpan.FromDays(3)),
|
||||
};
|
||||
|
||||
// Auto-gen MaPhieu đơn giản PE-YYYYMM-XXXX (4 digit random) — format sau
|
||||
entity.MaPhieu = $"PE-{DateTime.UtcNow:yyyyMM}-{Random.Shared.Next(1000, 9999)}";
|
||||
// Atomic MaPhieu sequence — format PE/{YYYY}/{TypeLetter}/{Seq:D3}
|
||||
// (mirror IContractCodeGenerator pattern, transaction SERIALIZABLE).
|
||||
entity.MaPhieu = await codeGen.GenerateAsync(entity, ct);
|
||||
|
||||
db.PurchaseEvaluations.Add(entity);
|
||||
|
||||
|
||||
@ -18,3 +18,15 @@ public interface IPurchaseEvaluationWorkflowService
|
||||
|
||||
TimeSpan? GetPhaseSla(PurchaseEvaluationPhase phase);
|
||||
}
|
||||
|
||||
// Atomic sequence generator cho mã PE (MaPhieu) — mirror IContractCodeGenerator.
|
||||
// Format: PE/{YYYY}/{TypeLetter}/{Seq:D3}
|
||||
// - YYYY = năm hiện tại (UTC)
|
||||
// - TypeLetter = "A" (DuyetNcc) / "B" (DuyetNccPhuongAn)
|
||||
// - Seq = 3 chữ số tăng dần per (year × type)
|
||||
// VD: PE/2026/A/001, PE/2026/A/002, PE/2026/B/001
|
||||
public interface IPurchaseEvaluationCodeGenerator
|
||||
{
|
||||
// Gen mã phiếu atomic. Transaction SERIALIZABLE để tránh race condition.
|
||||
Task<string> GenerateAsync(PurchaseEvaluation evaluation, CancellationToken ct = default);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user