[CLAUDE] PurchaseEvaluation: chuong bao nguoi duyet khi phieu vao cap cua ho (submit + moi cap)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m48s
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m48s
Tra Sol (Zalo): 'khong thay chuong bao - viec co ho so can duyet'. PE workflow truoc chi notify DRAFTER luc terminal; nguoi DUYET khong duoc bao khi phieu toi cap cua ho. Fix: block trong LogTransitionAsync (sau drafter-notify) - khi toPhase==ChoDuyet, resolve approver cap hien tai (workflow.Steps[CurrentWorkflowStepIndex].Levels Order==CurrentApprovalLevelOrder -> ApproverUserId OR-of-N, exclude actor) -> NotifyManyAsync Generic 'Phieu can ban duyet'. Fire moi luc phieu vao cap ChoDuyet: submit (cap 1) + moi approve-advance (cap ke) - 5 call-site advance deu log toPhase=ChoDuyet sau khi set pointer (verified). Best-effort try/catch (notify fail KHONG rollback transition). V2-only guard. Bell render Generic san (urgent->CEO da chung minh). BE-only, no-mig. Build slnx 0/0, test 354 PASS (khong vo transition cu). Notify = test-after (UAT). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -1055,6 +1055,54 @@ public class PurchaseEvaluationWorkflowService(
|
||||
refId: evaluation.Id,
|
||||
ct: ct);
|
||||
}
|
||||
|
||||
// ===== Notify approver(s) cấp hiện tại khi phiếu vào ChoDuyet =====
|
||||
// Tra Sol (Zalo): approver KHÔNG nhận chuông "có hồ sơ cần duyệt" — chỉ
|
||||
// drafter được báo (block ↑). Bổ sung: mỗi lần phiếu ENTER hoặc ADVANCE
|
||||
// tới 1 Cấp duyệt (toPhase==ChoDuyet) → báo NV Cấp đang chờ.
|
||||
// Resolve mirror ĐÚNG canonical (ApplyDrafterBypassOnSubmit / EnsureActor
|
||||
// line ~301): load ApprovalWorkflow → Step tại CurrentWorkflowStepIndex →
|
||||
// Levels.Where(Order == CurrentApprovalLevelOrder) → distinct ApproverUserId.
|
||||
// V2-only (ApprovalWorkflowId + pointer set); phiếu V1/no-workflow skip.
|
||||
// Best-effort (try/catch) — phiếu đã SaveChanges, notify fail KHÔNG fail transition.
|
||||
if (toPhase == PurchaseEvaluationPhase.ChoDuyet
|
||||
&& evaluation.ApprovalWorkflowId is Guid notifyAwId
|
||||
&& evaluation.CurrentWorkflowStepIndex is int notifyCsi
|
||||
&& evaluation.CurrentApprovalLevelOrder is int notifyLvl)
|
||||
{
|
||||
try
|
||||
{
|
||||
var workflow = await db.ApprovalWorkflows.AsNoTracking()
|
||||
.Include(w => w.Steps).ThenInclude(s => s.Levels)
|
||||
.FirstOrDefaultAsync(w => w.Id == notifyAwId, ct);
|
||||
var stepsOrdered = workflow?.Steps.OrderBy(s => s.Order).ToList();
|
||||
if (stepsOrdered is not null && notifyCsi >= 0 && notifyCsi < stepsOrdered.Count)
|
||||
{
|
||||
var approverIds = stepsOrdered[notifyCsi].Levels
|
||||
.Where(l => l.Order == notifyLvl
|
||||
&& l.ApproverUserId != Guid.Empty
|
||||
&& l.ApproverUserId != actorUserId)
|
||||
.Select(l => l.ApproverUserId)
|
||||
.Distinct()
|
||||
.ToList();
|
||||
if (approverIds.Count > 0)
|
||||
{
|
||||
await notifications.NotifyManyAsync(
|
||||
approverIds,
|
||||
NotificationType.Generic,
|
||||
$"Phiếu cần bạn duyệt: {evaluation.MaPhieu ?? evaluation.TenGoiThau}",
|
||||
"Có phiếu Duyệt NCC đang chờ bạn duyệt.",
|
||||
$"/purchase-evaluations/{evaluation.Id}",
|
||||
evaluation.Id,
|
||||
ct);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// best-effort — nuốt lỗi notify để KHÔNG rollback transition đã lưu.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Mig 26 (Session 19) — helper resolve FullName cho denorm `SignedByFullName`.
|
||||
|
||||
Reference in New Issue
Block a user