Report Subscription
Report Subscription = đăng ký nhận báo cáo định kỳ tự động (vd báo cáo tuần). Đây là một đường automation gọn chạy qua đúng các primitive lõi:
AutomationScheduler, key helper dùng chung,Ensure*, dispatch guard, send claim.
Trạng thái implementation: Roll Sheet đã chạy end-to-end: create/edit/pause/resume/delete/duplicate, Run Now, lưu file, secure link và run history. Không mô tả các report type khác nếu chưa có generator branch tương ứng.
Đường đi
Gửi thẳng
OutgoingMessagemà bỏ cầuNotificationSchedulercần phê duyệt riêng và vẫn phải giữ send-claim guard.
Dùng AutomationScheduler (không thêm cột mới)
AutomationTypeId = ReportSubscription
TriggerTypeId = ScheduledRun | ManualRun
SourceEntityTypeId = ReportSubscription ; SourceEntityGuid = ReportSubscription.Guid
SchedulerKey = report-subscription:{guid}:scheduled:{periodStartUtc-or-scheduledOn}
| report-subscription:{guid}:manual:{manualRunGuid}SchedulerKeylà khóa run nghiệp vụ canonical — không suy delivery key từAutomationScheduler.Id/Guid.manualRunGuidsinh trước insert, trả về caller, tái dùng khi retry.StorageRunKeyHash(hash ngắn ổn định củaSchedulerKey) gom các delivery artifact (MessagingJob.Guid, reportNotificationJob.RowKey).
One-Owner Guard — không gửi đôi khi cutover
Scheduler cũ và automation scheduler mới cùng kiểm một ownership guard trước khi tạo delivery:
ReportRunOwnership: SchedulerKey, OwnerTypeId (OldScheduler | AutomationScheduler),
OwnerVersion, StatusId (Owned | DeliveryCreated | Cancelled), CoordinatesJson?- Chỉ owner mới tạo
NotificationJob/MessagingJob/blob/NotificationScheduler. - Shadow rows không acquire ownership.
- Retry tái dùng ownership + tọa độ. Xung đột ownership →
IsOnSupportHold, không bao giờ tạo delivery thứ hai.
Rollout từng bước (an toàn, rollback được)
0 Design validation : xác nhận delivery path, hành vi scheduler cũ, ownership storage.
1 Shadow : row không-chạy; so khóa kỳ vọng với run của scheduler cũ.
2 Run-now allowlist : automation chạy các manual run được chọn; scheduler cũ bị chặn cho chúng.
3 Scheduled allowlist: chọn BU/subscription; theo dõi conflict/failure/latency.
4 Cutover : guard scheduler cũ cho subscription trong allowlist;
rollback = bỏ allowlist, ownership trả về scheduler cũ.Lifecycle & support
- Create/update → ensure next scheduled row (chỉ next run, trừ khi cần horizon có biên rõ).
- Pause/deactivate/delete → deactivate pending rows; completed runs giữ nguyên.
- Template/recipient/delivery đổi → reload lúc execution. Run-now →
manualRunGuidmới. - Support API:
GET/POST /report-subscriptions/{guid}/automation-runs[...]— report run detail, ownership detail, delivery coordinates, failed report queue, recent runs/subscription.
Contract hiện tại của một run
- Mỗi run dùng lại data/render service của manual Attendance Roll Sheet; không có data thì run vẫn hoàn tất với trạng thái no-data tương ứng, không tạo nội dung giả.
- File được lưu dù email có attachment hay không. Email mặc định dùng secure view/download link; attachment quá lớn tự fallback link-only.
- Run history nối
ReportSubscriptionScheduler, file metadata và delivery per recipient; hiển thị run type (Scheduled/Manual), status, recipient và attachment/link state. - Pause chỉ dừng lịch tương lai; Run Now vẫn chạy khi subscription còn valid. Delete chặn action mới nhưng giữ history/file để support tra cứu.
Ví dụ thực tế: Admin pause report cuối tuần nhưng cần gửi ngay một bản. → Không resume lịch nền. → Bấm Run Now, hệ thống dùng subscriber đã lưu và tạo manual run coordinate riêng.
Liên quan
- Automation & Reminders — nền automation chung.
- Subscription — khác với "report subscription"; subscription là gói đăng ký học/billing.