Files
solution-erp/src/Backend/SolutionErp.Domain
pqhuy1987 4edcd588d8
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m41s
[CLAUDE] Domain+Infra: User-kind approver runtime guard + Warning 20% SLA
## User-kind approver guard

Trước: WorkflowDefinition Designer cho admin pick User cụ thể vào step
approver, nhưng runtime guard bỏ qua (User-kind treat như DeptManager
fallback per skill doc).

Bây giờ: enable đầy đủ. WorkflowPolicy + UserTransitions parallel dict
(default null cho hardcoded Standard/SkipCcm, populated qua
FromDefinition khi WorkflowStepApprover Kind=User).

IsTransitionAllowed signature update: (from, to, actorRoles, actorUserId?)
- Check Role first (existing behavior)
- Fallback User-kind: actorUserId.ToString() có trong UserTransitions[(from,to)]?

ContractWorkflowService.TransitionAsync dùng IsTransitionAllowed thay
inline check. Error message thêm "{N} user explicit" nếu policy có
User-kind approvers cho transition đó.

FromDefinition cũng update: nếu step CHỈ có User-kind (không Role),
không fallback DeptManager nữa — guard sẽ check user-level. Chỉ
fallback DeptManager nếu step thiếu cả 2.

## Warning 20% SLA

SlaExpiryJob.ProcessWarningsAsync mới — chạy trước ProcessAsync
(auto-approve quá hạn):
- Pull Contracts WHERE !SlaWarningSent && SlaDeadline > now &&
  Phase NOT IN (DaPhatHanh, TuChoi, DangDongDau)
- Per phase, threshold = 20% × default SLA (vd Soạn thảo 7 ngày → 33.6h
  remaining trigger warning; In ký 1 ngày → 4.8h)
- Compute remaining = SlaDeadline - now; nếu remaining <= threshold
  + còn slot → notify Drafter via INotificationService
- Set SlaWarningSent = true để chỉ warning 1 lần per phase (reset trong
  TransitionAsync khi chuyển phase mới)
- NotificationType.SlaWarning (đã có trong enum) + title icon ⚠

## Build

dotnet build BE pass (0 error)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 15:11:34 +07:00
..