[CLAUDE] App+Infra: IChangelogService + log Workflow/Contract/Comment/Attachment
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m26s

User decision B (log cả 3): mọi thay đổi liên quan HĐ ghi vào unified
ContractChangelogs để render tab Lịch sử FE.

## IChangelogService (Application/Common/Interfaces/)

5 methods:
- LogContractChangeAsync — Header insert/update
- LogDetailChangeAsync — line item insert/update/delete
- LogWorkflowTransitionAsync — phase change (parallel với ContractApprovals)
- LogCommentAddedAsync — góp ý mới
- LogAttachmentAsync — upload/delete file

KHÔNG SaveChanges trong service — caller chịu trách nhiệm save atomic
cùng business changes (pattern giống INotificationService).

## ChangelogService impl

- Resolve actor qua ICurrentUser → UserManager.FindByIdAsync
- Denormalize UserName (FullName ?? Email) cho log readable
- null UserId = system action (vd SLA auto-approve)
- DI: AddScoped trong DependencyInjection.cs

## Wiring vào handlers hiện tại

- ContractWorkflowService.TransitionAsync — LogWorkflowTransitionAsync
  sau khi insert ContractApproval
- CreateContractCommandHandler — LogContractChangeAsync(Insert)
- UpdateContractDraftCommandHandler — diff GiaTri/TenHopDong/NoiDung/
  TemplateId trước update, log update với fieldChangesJson nếu có thay đổi
- AddCommentCommandHandler — LogCommentAddedAsync
- UploadContractAttachmentCommandHandler — LogAttachmentAsync(Insert)
- DeleteContractAttachmentCommandHandler — LogAttachmentAsync(Delete)

Build: dotnet build BE pass (0 error, 2 pre-existing warning trong
DocxRenderer.cs)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
pqhuy1987
2026-04-23 10:12:51 +07:00
parent 70810e1b34
commit 71c035d31e
6 changed files with 232 additions and 10 deletions

View File

@ -0,0 +1,44 @@
using SolutionErp.Domain.Contracts;
namespace SolutionErp.Application.Common.Interfaces;
// Service ghi ContractChangelog. KHÔNG SaveChanges — caller (CQRS handler)
// chịu trách nhiệm save atomic cùng với business changes. Pattern giống
// INotificationService.
public interface IChangelogService
{
Task LogContractChangeAsync(
Guid contractId,
ChangelogAction action,
string? summary = null,
string? fieldChangesJson = null,
string? contextNote = null,
ContractPhase? phaseAtChange = null,
CancellationToken ct = default);
Task LogDetailChangeAsync(
Guid contractId,
Guid detailId,
ChangelogAction action,
string? summary = null,
string? fieldChangesJson = null,
ContractPhase? phaseAtChange = null,
CancellationToken ct = default);
Task LogWorkflowTransitionAsync(
Guid contractId,
ContractPhase fromPhase,
ContractPhase toPhase,
string? comment,
CancellationToken ct = default);
Task LogCommentAddedAsync(Guid contractId, string content, ContractPhase phase, CancellationToken ct = default);
Task LogAttachmentAsync(
Guid contractId,
Guid attachmentId,
ChangelogAction action,
string fileName,
ContractPhase phase,
CancellationToken ct = default);
}