Skip to content

US-T05: Check snapshot một ticket ​

Thuộc FS: 00-overview.md — SAPP-23954 Ticket Owner Phần chung (tổng quan, roles, flow tổng, related features, NFR, Open Questions, References) xem ở Overview. File này chỉ chứa nội dung riêng của US. As-built @ e77c47a · nguồn: inventory 23954 A-11, A-12.

Chỉ đọc — US này không ghi dữ liệu vào bất kỳ hệ thống nào.

FieldValue
US IDUS-T05
Role thực hiệnR1 - Người dùng tool Assumption (OQ về G-01)
PhaseĐã triển khai (as-built @ e77c47a)
PriorityN/A — as-built
StatusDraft
NFR liên quanNFR-T-01, NFR-T-02, NFR-T-06, NFR-T-07 — xem Overview §5
OQ liên quanOQ-T-01, OQ-T-12, OQ-T-13, OQ-T-14, OQ-T-15, OQ-T-17, OQ-T-18 — xem Overview §6

1. US Statement ​

text
As a Người dùng tool (Assumption — OQ về G-01)
I want nhập một Ticket ID và xem logic gán owner theo class owner sẽ chạy tiếp hay dừng ở bước nào và vì sao,
       tại mọi thời điểm cap_nhat_owner của ticket đổi giá trị và tại hiện tại, mà không thay đổi gì trên HubSpot
So that [Assumption — OQ-T-01] chẩn đoán được vì sao một ticket không được gán owner
        (màn tool tự mô tả: "xem logic thật sẽ chạy tiếp hay dừng ở đâu và vì sao")

2. Dependencies & Definition Of Ready ​

N/A — đã triển khai (Mode B).

Dependency runtime (tham khảo):

#Cần sẵn sàngAi cung cấpTrạng thái
D1Token HubSpot của portal có quyền đọc ticket, contact, lịch sử thuộc tính (US-P04)Admin CMSN/A — runtime
D2Tool sapp.009 đang bật / đã mở khoá (US-P02)Admin CMSN/A — runtime
D3Hằng số điều kiện khớp logic gốc ở repo sapp-platform-lms-be (REL-07)Owner repo gốcN/A — runtime (OQ-T-13)

3. Business Rules ​

IDRuleÁp dụng ởĐã cover bởi (AC)Nguồn code (Mode B/C)
BR-01Có 2 portal Dev (mặc định) và Prod; kiểm tra chạy trên portal đang chọnM1 - tab portalAC-M1.1fe/src/ui/components/works/sapp/sapp-23954-snapshot-tool.tsx:38-41, :618, :662
BR-02Nút "Kiểm tra" chỉ bật khi Ticket ID (đã bỏ khoảng trắng hai đầu) khác rỗng; nhấn Enter trong ô cũng chạy kiểm traM1 - field Ticket IDAC-M1.1, EC-M1.1fe/src/ui/components/works/sapp/sapp-23954-snapshot-tool.tsx:550-553, :565-567, :575
BR-03Kiểm tra chỉ đọc: đọc ticket, contact và lịch sử thuộc tính trên HubSpot; không ghi HubSpot, không truy vấn dữ liệu lớp, dừng trước bước tra class ownerM1 - action Kiểm traAC-M1.2be/libs/modules/src/lib/sapp/common.service.ts:674-688, :689-897; be/libs/constants/src/lib/sapp/sapp-23954.constants.ts:44-50
BR-04Các mốc đánh giá = mỗi lần cap_nhat_owner đổi sang giá trị khác rỗng và khác giá trị đang giữ trước đó (theo thời gian cũ → mới), cộng một mốc "Hiện tại" ở cuối. Một lần "làm mới" (rỗng → giá trị cũ) không tạo mốc mớiM1 - danh sách mốcAC-M1.3be/libs/modules/src/lib/sapp/common.service.ts:827-888
BR-05Tại mỗi mốc lịch sử, giá trị các thuộc tính ticket và contact được lấy "tại thời điểm" đó từ lịch sử thuộc tính; mốc "Hiện tại" dùng giá trị hiện tại. Contact dùng cho mọi mốc là contact đầu tiên đang gắn với ticket hiện nay (OQ-T-14)M1 - action Kiểm traAC-M1.3be/libs/modules/src/lib/sapp/common.service.ts:417-422, :658-672, :782-783, :842-870
BR-06Bước "Kiểm tra cap_nhat_owner": chỉ đi tiếp khi giá trị là "Xử lý ticket thông thường" hoặc "Xử lý ticket chào mừng"; khác → Dừng, lý do "cap_nhat_owner không thuộc nhóm được xử lý."M2 - traceAC-M2.1be/libs/modules/src/lib/sapp/common.service.ts:487-509
BR-07Bước "Kiểm tra pipeline": ticket "thông thường" phải thuộc 1 trong 8 pipeline prod ([CX] Phân luồng chatbot; Exam & Membership Account/ Registration; Student Policy; Internal Back Office task (NO CES); Learning Support & Information; Learner Class Operation; Learning Experience & Complaint Resolution; [IT] Pipeline phân luồng Ticket) hoặc pipeline dev "[DEV] ACCA ONLINE"; ticket "chào mừng" phải thuộc pipeline prod "Learner Class Operation" hoặc pipeline dev "[DEV] ACCA ONLINE". Khác → Dừng, lý do "Pipeline của ticket không thuộc danh sách áp dụng." Danh sách cố định trong code (OQ-T-13)M2 - traceAC-M2.2be/libs/modules/src/lib/sapp/common.service.ts:511-531; be/libs/constants/src/lib/sapp/sapp-23954.constants.ts:96-127
BR-08Bước "Kiểm tra contact gắn với ticket": ticket phải có contact gắn; không có → Dừng, lý do "Không tìm thấy contact gắn với ticket." Bước "Lấy chi tiết contact từ HubSpot": đọc lỗi → trạng thái Lỗi và dừng, lý do "Không đọc được contact {id}."M2 - traceAC-M2.3be/libs/modules/src/lib/sapp/common.service.ts:533-587
BR-09Ticket "chào mừng" bỏ qua bước "Kiểm tra điều kiện áp dụng rule" → kết luận Sẽ chạyM2 - traceAC-M2.4be/libs/modules/src/lib/sapp/common.service.ts:589-602
BR-10Ticket "thông thường" chỉ Sẽ chạy khi thoả ít nhất 1 trong: (cond1) phân loại yêu cầu dịch vụ của ticket thuộc 36 giá trị hợp lệ; (cond2) "vấn đề cần được hỗ trợ" của contact là "Phản hồi về trải nghiệm học tập" hoặc "Hỗ trợ dịch vụ học tập khác"; (cond3) "yêu cầu dịch vụ nội bộ" của contact là "Bổ sung học viên vào lớp sau khai giảng". Không thoả → Dừng, lý do "Ticket không thoả điều kiện áp dụng rule phân owner theo class owner." Danh sách giá trị cố định trong code (OQ-T-13)M2 - trace, khối Điều kiện xétAC-M2.5, AC-M2.6be/libs/modules/src/lib/sapp/common.service.ts:604-655; be/libs/constants/src/lib/sapp/sapp-23954.constants.ts:133-181
BR-11Mỗi mốc có kết luận "Sẽ chạy getClassOwnerFromTicketDetail" hoặc "Sẽ không chạy getClassOwnerFromTicketDetail" kèm mã bước dừng và lý do; mốc lịch sử ghi thêm "cap_nhat_owner đổi thành: {giá trị}"M2 - khối kết luậnAC-M2.1, AC-M2.4fe/src/ui/components/works/sapp/sapp-23954-snapshot-tool.tsx:208-249
BR-12Không đọc được ticket → trả một mốc "Hiện tại" có bước "Lấy chi tiết ticket từ HubSpot" trạng thái Lỗi, kết luận Sẽ không chạy, lý do "Không đọc được ticket {id}." (không báo lỗi hệ thống). Không đọc được lịch sử thuộc tính ticket → chỉ còn mốc "Hiện tại". Không tra được tên pipeline → vẫn đánh giá, hiển thị idM1 - action Kiểm traAC-M1.4, EC-M1.3be/libs/modules/src/lib/sapp/common.service.ts:697-741, :749-761, :766-778
BR-13Tóm tắt "{n} mốc đánh giá — {x} dừng, {y} sẽ chạy"; hai kiểu xem: "Theo mốc" (mặc định, chọn sẵn mốc "Hiện tại") và "Dòng thời gian" (mỗi mốc một thẻ thu gọn, mốc "Hiện tại" mở sẵn); nhãn mốc = ngày giờ đổi giá trị (định dạng vi-VN) hoặc "Hiện tại"M1 - danh sách mốcAC-M1.3, AC-M1.5fe/src/ui/components/works/sapp/sapp-23954-snapshot-tool.tsx:340-353, :379-382, :431, :488-527
BR-14Email / số điện thoại contact chỉ hiển thị trên màn, kèm chú thích "Email / số điện thoại chỉ hiển thị tại đây — không được xuất ra file (theo quy định bảo mật)."; không có nút xuất / sao chépM2 - khối Contact liên kếtAC-M2.7fe/src/ui/components/works/sapp/sapp-23954-snapshot-tool.tsx:279-302; be/libs/interface/src/lib/dto/sapp/sapp-23954-ticket.dto.ts:340-348
BR-15Mỗi bước trong trace hiển thị tên bước, mã bước, trạng thái (Đạt / Dừng / Bỏ qua / Lỗi), chi tiết, và danh sách thu gọn "Giá trị đã đọc ({n})"M2 - traceAC-M2.1fe/src/ui/components/works/sapp/sapp-23954-snapshot-tool.tsx:77-149

⚠️ Observed không viết thành BR: vế điều kiện thứ 4 thừa (EC-M2.1, OQ-T-12); tên pipeline ở mốc lịch sử lấy theo pipeline hiện tại (EC-M2.2, OQ-T-18); đổi tab mất kết quả (EC-M1.4, OQ-T-15). Drift ví dụ doc: DR-T-02; thiếu token: DR-T-04.

4. Design ​

a. Mối liên hệ giữa các màn & User Flow ​

text
[Menu "SAPP 23954 - Ticket Owner" › "Check snapshot"]
  ↓
[M1: Tab Dev (mặc định) / Prod · ô Ticket ID · nút "Kiểm tra"]
  ↓ nhập ID → Enter / "Kiểm tra"
[M1: "{n} mốc đánh giá — {x} dừng, {y} sẽ chạy" · chọn "Theo mốc" / "Dòng thời gian"]
  ↓ chọn một mốc / mở một thẻ
[M2: Chi tiết mốc — kết luận · Ticket · Contact liên kết · Điều kiện xét · Trace thực thi]
  └─ cả request lỗi ──→ hộp lỗi "Kiểm tra snapshot thất bại"

Chuỗi bước của mỗi mốc (tóm tắt BR-06 → BR-10):

text
Nguồn dữ liệu → Kiểm tra cap_nhat_owner --(không phải thông thường / chào mừng)--> DỪNG
             → Kiểm tra pipeline --(ngoài danh sách)--> DỪNG
             → Kiểm tra contact gắn với ticket --(không có contact)--> DỪNG
             → Lấy chi tiết contact --(đọc lỗi)--> DỪNG (Lỗi)
             → Kiểm tra điều kiện áp dụng rule --(chào mừng)--> SẼ CHẠY (Bỏ qua)
                                              --(thông thường, cond1 | cond2 | cond3)--> SẼ CHẠY
                                              --(không thoả)--> DỪNG

Link flow chi tiết nếu có:

  • Inventory 23954 §5 (sơ đồ "Kết quả mỗi mốc snapshot").

b. Chi tiết từng màn ​

Màn M1 - Nhập ticket và danh sách mốc (sapp.009) ​

FieldValue
Figma frameN/A
Trigger vào mànMở /works/sapp/tools/sapp-23954-snapshot từ menu "SAPP 23954 - Ticket Owner" › "Check snapshot"
Mô tả ngắnTiêu đề "SAPP-23954 Kiểm tra snapshot (Ticket)", 2 tab Dev / Prod, ô Ticket ID + nút "Kiểm tra", chú thích "Chạy thử (chỉ đọc) chuỗi điều kiện gán owner cho 1 ticket trong portal {env}. Không thay đổi gì trên HubSpot."; sau khi kiểm tra: tóm tắt và bộ chọn kiểu xem
UI States ​
StateKhi nàoHiển thịFigma frame
DefaultVừa vào màn / đổi tabÔ Ticket ID trống (gợi ý "VD: 99001"); "Nhập Ticket ID rồi bấm "Kiểm tra" để xem kết quả."N/A
LoadingĐang kiểm traNút "Đang kiểm tra…" có spinner, khoáN/A
Has dataCó kết quả"{n} mốc đánh giá — {x} dừng, {y} sẽ chạy"; bộ chọn "Theo mốc" / "Dòng thời gian"; "Theo mốc": hàng nút mốc (biểu tượng đạt / dừng + nhãn), "Mốc đang xem: {nhãn}" + M2; "Dòng thời gian": danh sách thẻ cũ → mới, mỗi thẻ có nhãn mốc, "Sẽ chạy" / "Dừng", "→ {giá trị cap_nhat_owner}"N/A
EmptyKết quả không có mốc nào"Không có snapshot nào cho ticket này." (thực tế luôn có ít nhất mốc "Hiện tại")N/A
ErrorCả request lỗiHộp lỗi "Kiểm tra snapshot thất bại", nội dung "{thông điệp} ({mã})"N/A
DisabledTicket ID trống / đang kiểm traNút "Kiểm tra" khoáN/A
Fields ​
FieldRequiredTypeDefaultFormatValidationError MessageVisibilityDepends On
Tab portalYesTab (Dev / Prod)Dev—Chỉ 2 giá trị (BR-01)—Always—
Ticket IDYesTextTrốngid ticket HubSpot (gợi ý "VD: 99001")Khác rỗng sau khi bỏ khoảng trắng (BR-02); không kiểm tra định dạng số— (nút khoá)Always—
Kiểu xem—Toggle (Theo mốc / Dòng thời gian)Theo mốc———Khi có kết quả—
Mốc đang xem—Chọn một (Theo mốc)Mốc "Hiện tại"ngày giờ vi-VN / "Hiện tại"——Khi kiểu xem = Theo mốcDanh sách mốc
Filter / Search / Sort (chỉ màn List/Report — xóa nếu không phải) ​
LoạiTheo fieldKiểuDefaultNotes
Filter———N/A — không lọc mốc
SearchTicket IDnhập chính xác 1 id—Không tìm theo tên
SortThời điểm mốccố địnhCũ → mới, "Hiện tại" cuốiBR-04
Pagination——Không phân trangTrả toàn bộ mốc
Actions ​
A1 - Chọn portal ​
ItemDescription
TriggerBấm tab "Dev" / "Prod"
BehaviorĐổi portal; panel dựng lại, ô nhập và kết quả bị xoá (BR-01). Không ghi dữ liệu
Success ResultTrạng thái Default của portal mới

Error cases:

CaseExpected Handling
Đang có kết quả ở tab cũ⚠️ Observed — mất khi đổi tab (EC-M1.4)
A2 - Kiểm tra ​
ItemDescription
TriggerBấm "Kiểm tra" hoặc Enter trong ô Ticket ID (BR-02)
BehaviorBE của portal đang chọn: đọc ticket (kèm contact gắn), tên pipeline, lịch sử thuộc tính ticket, chi tiết + lịch sử thuộc tính của contact đầu tiên; lập danh sách mốc (BR-04, BR-05); chạy chuỗi bước cho từng mốc (BR-06 → BR-10). Ghi vào: không ghi — chỉ đọc HubSpot portal dev / prod (BR-03)
Success ResultTóm tắt + danh sách mốc (BR-13)

Error cases:

CaseExpected Handling
Ticket không tồn tại / không đọc được / portal thiếu tokenKhông báo lỗi hệ thống: trả 1 mốc "Hiện tại" "Sẽ không chạy", bước "fetch-ticket" Lỗi, lý do "Không đọc được ticket {id}." (BR-12, DR-T-04)
Lịch sử thuộc tính ticket lỗiChỉ có mốc "Hiện tại" (BR-12)
Cả request lỗi (lỗi không lường trước)Hộp lỗi "Kiểm tra snapshot thất bại" — "Failed to check SAPP-23954 snapshot (13028)"
A3 - Đổi kiểu xem / chọn mốc ​
ItemDescription
TriggerBấm "Theo mốc" / "Dòng thời gian"; bấm nút một mốc; bấm tiêu đề một thẻ
BehaviorChỉ đổi cách hiển thị (BR-13). Không gọi API, không ghi dữ liệu
Success ResultM2 của mốc được chọn / thẻ được mở

Error cases:

CaseExpected Handling
N/AKhông có lỗi
Acceptance Criteria của màn M1 ​
AC-M1.1 - Nút Kiểm tra và portal ​
gherkin
Given đang ở tab "Dev" (mặc định) và ô Ticket ID chỉ chứa khoảng trắng
Then nút "Kiểm tra" bị khoá
When nhập " 99001 " rồi nhấn Enter
Then hệ thống kiểm tra ticket "99001" trên portal HubSpot dev

Maps to:

  • Business Rule: BR-01, BR-02
  • Field/Action: Ticket ID, A2
AC-M1.2 - Không ghi gì ​
gherkin
Given ticket 99001 tồn tại trên portal dev
When kiểm tra ticket 99001
Then không có thuộc tính nào của ticket hay contact trên HubSpot bị thay đổi
And không có dữ liệu nào được lưu ở mind_keep

Maps to:

  • Business Rule: BR-03
AC-M1.3 - Lập mốc từ lịch sử cap_nhat_owner ​
gherkin
Given lịch sử cap_nhat_owner của ticket (cũ → mới) là: "Xử lý ticket thông thường", rỗng, "Xử lý ticket thông thường", "Cập nhật thành công"
When kiểm tra ticket
Then có 3 mốc theo thứ tự: mốc đổi thành "Xử lý ticket thông thường", mốc đổi thành "Cập nhật thành công", mốc "Hiện tại"
And tại mỗi mốc lịch sử, giá trị ticket / contact hiển thị là giá trị tại thời điểm đó
And tóm tắt hiển thị "3 mốc đánh giá — {x} dừng, {y} sẽ chạy" với x + y = 3

Maps to:

  • Business Rule: BR-04, BR-05, BR-13
AC-M1.4 - Ticket không đọc được ​
gherkin
Given ticket 123 không tồn tại trên portal prod
When ở tab "Prod" kiểm tra ticket 123
Then không có hộp lỗi
And kết quả có đúng 1 mốc "Hiện tại" với kết luận "Sẽ không chạy getClassOwnerFromTicketDetail", bước "fetch-ticket" trạng thái Lỗi và lý do "Không đọc được ticket 123."

Maps to:

  • Business Rule: BR-12
AC-M1.5 - Hai kiểu xem ​
gherkin
Given kết quả có 3 mốc
When xem mặc định
Then kiểu "Theo mốc" đang chọn, mốc "Hiện tại" đang xem
When chọn "Dòng thời gian"
Then hiện 3 thẻ cũ → mới, chỉ thẻ "Hiện tại" đang mở

Maps to:

  • Business Rule: BR-13
  • Field/Action: A3
Negative AC / Edge Cases của màn M1 ​
IDTình huốngHành vi mong đợi
EC-M1.1Ticket ID có chữ / ký tự đặc biệtKhông kiểm tra định dạng ở màn; HubSpot không đọc được → như AC-M1.4
EC-M1.2Ticket chưa từng có cap_nhat_owner khác rỗngChỉ có mốc "Hiện tại"
EC-M1.3Không tra được tên pipelineVẫn đánh giá; ô Pipeline hiển thị id (BR-12)
EC-M1.4⚠️ Observed — đổi tab Dev ↔ ProdHành vi hiện tại: ô nhập và kết quả bị xoá (chú thích code nói "mỗi tab giữ riêng"). Nguồn: fe/src/ui/components/works/sapp/sapp-23954-snapshot-tool.tsx:660-662. OQ-T-15, DR-T-09
EC-M1.5Portal thiếu token HubSpotHành vi hiện tại: ra kết quả như ticket không đọc được (AC-M1.4) thay vì lỗi cấu hình 12001 như API doc nói (DR-T-04)
EC-M1.6Lịch sử thuộc tính contact đọc lỗiSuy từ code (chưa chạy thử): mốc lịch sử nhận giá trị contact trống → cond2 / cond3 sai ở các mốc đó; mốc "Hiện tại" không bị ảnh hưởng. Nguồn: be/libs/modules/src/lib/sapp/common.service.ts:799-811, :849-855

Màn M2 - Chi tiết một mốc ​

FieldValue
Figma frameN/A
Trigger vào mànChọn một mốc ở "Theo mốc" hoặc mở một thẻ ở "Dòng thời gian"
Mô tả ngắnKhối kết luận, khối "Ticket", khối "Contact liên kết" (nếu đọc được contact), khối "Điều kiện xét (thông thường)" (nếu tới bước điều kiện rule), "Trace thực thi ({n} bước)"
UI States ​
StateKhi nàoHiển thịFigma frame
DefaultMốc được chọnKết luận xanh "Sẽ chạy getClassOwnerFromTicketDetail" hoặc đỏ "Sẽ không chạy getClassOwnerFromTicketDetail" + mã bước dừng + lý do; mốc lịch sử có "cap_nhat_owner đổi thành: {giá trị}"N/A
LoadingN/A — dữ liệu đã có từ M1—N/A
Has dataCó contact / điều kiệnKhối Ticket: Ticket ID, Subject, Pipeline, cap_nhat_owner, Owner ID, Phân loại yêu cầu DV, Mã lớp HV cần hỗ trợ, Ngày tạo. Khối Contact liên kết: Contact ID, Tên, Email, Số điện thoại, Vấn đề cần hỗ trợ, Yêu cầu DV nội bộ + chú thích bảo mật. Khối Điều kiện xét: 3 nhãn cond1 / cond2 / cond3 (đạt / không) + chú thích công thức. Trace: các bướcN/A
EmptyDừng trước bước contact / điều kiệnKhông hiện khối Contact / Điều kiện xét; giá trị trống hiện "—"N/A
ErrorBước đọc lỗiBước tương ứng trạng thái "Lỗi" (đỏ) với chi tiết lỗiN/A
DisabledN/A—N/A
Fields ​
FieldRequiredTypeDefaultFormatValidationError MessageVisibilityDepends On
Kết luận—Text—"Sẽ chạy / Sẽ không chạy getClassOwnerFromTicketDetail"BR-11—AlwaysKết quả mốc
Bước dừng + lý do—Text—mã bước + câu lý doBR-06 → BR-12—Khi Sẽ không chạyKết quả mốc
cap_nhat_owner đổi thành—Text—giá trị gốcBR-11—Chỉ mốc lịch sửMốc
Khối Ticket (8 trường)—Text—Ngày tạo theo vi-VN; trống = "—"BR-05—AlwaysGiá trị tại mốc
Khối Contact liên kết (6 trường)—Text—trống = "—"BR-14—Khi đọc được contactContact đầu tiên
cond1 / cond2 / cond3—Boolean chip—đạt / khôngBR-10—Chỉ ticket thông thường tới bước điều kiệnGiá trị tại mốc
Trace thực thi—List bước"Giá trị đã đọc" thu gọntên · mã · trạng thái · chi tiếtBR-15—AlwaysKết quả mốc
Filter / Search / Sort (chỉ màn List/Report — xóa nếu không phải) ​

N/A — màn chi tiết, không phải màn List.

Actions ​
A1 - Mở "Giá trị đã đọc" của một bước ​
ItemDescription
TriggerBấm "Giá trị đã đọc ({n})" dưới một bước
BehaviorMở / thu gọn danh sách tên thuộc tính → giá trị đã đọc ở bước đó (BR-15). Không gọi API, không ghi dữ liệu
Success ResultHiện từng cặp tên thuộc tính / giá trị; trống = "—"

Error cases:

CaseExpected Handling
N/AKhông có lỗi
Acceptance Criteria của màn M2 ​
AC-M2.1 - Dừng ở cap_nhat_owner ​
gherkin
Given tại mốc đang xem, cap_nhat_owner = "Cập nhật thành công"
When xem chi tiết mốc
Then kết luận "Sẽ không chạy getClassOwnerFromTicketDetail", mã bước dừng "cap_nhat_owner", lý do "cap_nhat_owner không thuộc nhóm được xử lý."
And trace có 2 bước: "Nguồn dữ liệu" (Đạt) và "Kiểm tra cap_nhat_owner" (Dừng)

Maps to:

  • Business Rule: BR-06, BR-11, BR-15
AC-M2.2 - Dừng ở pipeline ​
gherkin
Given ticket prod có cap_nhat_owner = "Xử lý ticket chào mừng" và pipeline "Student Policy"
When xem chi tiết mốc
Then kết luận Sẽ không chạy, mã bước dừng "pipeline", lý do "Pipeline của ticket không thuộc danh sách áp dụng."
And cùng ticket đó với cap_nhat_owner = "Xử lý ticket thông thường" thì đi qua bước pipeline

Maps to:

  • Business Rule: BR-07
AC-M2.3 - Không có contact ​
gherkin
Given ticket "thông thường" thuộc pipeline hợp lệ nhưng không có contact gắn
When xem chi tiết mốc
Then kết luận Sẽ không chạy, mã bước dừng "contact-association", lý do "Không tìm thấy contact gắn với ticket."
And không hiện khối "Contact liên kết"

Maps to:

  • Business Rule: BR-08
AC-M2.4 - Ticket chào mừng ​
gherkin
Given ticket prod có cap_nhat_owner = "Xử lý ticket chào mừng", pipeline "Learner Class Operation", có contact đọc được
When xem chi tiết mốc
Then kết luận "Sẽ chạy getClassOwnerFromTicketDetail"
And bước "Kiểm tra điều kiện áp dụng rule" có trạng thái "Bỏ qua", không hiện khối "Điều kiện xét"

Maps to:

  • Business Rule: BR-09, BR-11
AC-M2.5 - Ticket thông thường thoả cond2 ​
gherkin
Given ticket "thông thường" thuộc pipeline hợp lệ, phân loại yêu cầu dịch vụ không thuộc 36 giá trị, contact có "vấn đề cần được hỗ trợ" = "Hỗ trợ dịch vụ học tập khác"
When xem chi tiết mốc
Then khối "Điều kiện xét (thông thường)" có cond1 không đạt, cond2 đạt, cond3 không đạt
And kết luận "Sẽ chạy getClassOwnerFromTicketDetail"

Maps to:

  • Business Rule: BR-10
AC-M2.6 - Ticket thông thường không thoả ​
gherkin
Given ticket "thông thường" thuộc pipeline hợp lệ, có contact, cond1 / cond2 / cond3 đều không đạt
When xem chi tiết mốc
Then kết luận Sẽ không chạy, mã bước dừng "rule-eligibility", lý do "Ticket không thoả điều kiện áp dụng rule phân owner theo class owner."

Maps to:

  • Business Rule: BR-10
AC-M2.7 - Email / SĐT chỉ hiển thị ​
gherkin
Given contact gắn ticket có email và số điện thoại
When xem khối "Contact liên kết"
Then email và số điện thoại hiển thị kèm chú thích "Email / số điện thoại chỉ hiển thị tại đây — không được xuất ra file (theo quy định bảo mật)."
And màn không có nút xuất file, tải xuống hay sao chép dữ liệu

Maps to:

  • Business Rule: BR-14
  • NFR: NFR-T-06
Negative AC / Edge Cases của màn M2 ​
IDTình huốngHành vi mong đợi
EC-M2.1⚠️ Observed — ticket thông thường có mã lớp HV cần hỗ trợHành vi hiện tại: công thức hiển thị và áp dụng là "(cond1 hoặc cond2) hoặc cond3 hoặc (cond1 và có mã lớp HV cần hỗ trợ)" — vế cuối thừa vì đã bị cond1 bao hàm, nên mã lớp không ảnh hưởng kết quả; "Giá trị đã đọc" vẫn liệt kê "có mã lớp HV cần hỗ trợ". Nguồn: be/libs/modules/src/lib/sapp/common.service.ts:620-630; fe/src/ui/components/works/sapp/sapp-23954-snapshot-tool.tsx:316-319. Logic gốc có đúng vậy không: OQ-T-12
EC-M2.2⚠️ Observed — mốc lịch sử khi ticket từng ở pipeline khácHành vi hiện tại (phát hiện ở R3, suy từ code): id pipeline ở mốc lịch sử là id tại thời điểm đó, nhưng tên pipeline luôn là tên của pipeline hiện tại → khối Ticket có thể hiện tên không khớp id. Việc đánh giá bước pipeline dùng id nên không bị ảnh hưởng. Nguồn: be/libs/modules/src/lib/sapp/common.service.ts:747-761, :448-452, :856-863. OQ-T-18
EC-M2.3Ticket có nhiều contactChỉ contact đầu tiên được dùng cho mọi mốc (BR-05, OQ-T-14)
EC-M2.4Repo gốc đổi danh sách pipeline / giá trị điều kiệnSnapshot vẫn dùng bản sao cố định trong code → kết luận có thể lệch với hành vi thật (REL-07, OQ-T-13)
EC-M2.5Đọc chi tiết contact lỗiBước "Lấy chi tiết contact từ HubSpot" trạng thái Lỗi, dừng, lý do "Không đọc được contact {id}."; không hiện khối Contact (BR-08)

5. Cross-feature AC ​

AC-X.1 - Khớp logic gốc gán owner ​

gherkin
Given hằng số pipeline / giá trị điều kiện trong mind_keep đang khớp repo sapp-platform-lms-be
When kiểm tra một ticket trên portal prod
Then kết luận "Sẽ chạy" / "Sẽ không chạy" của mốc "Hiện tại" phải khớp việc logic gốc có chạy tới bước tra class owner hay không

Maps to:

  • REL-07 (Affects - Logic gốc gán owner theo class owner, repo sapp-platform-lms-be)

AC-X.2 - Thấy tác động của lần làm mới ​

gherkin
Given ticket T1 vừa được làm mới ở US-T02 (cap_nhat_owner rỗng rồi giá trị cũ)
When kiểm tra snapshot T1
Then không có mốc mới nào do lần làm mới đó tạo ra (BR-04)
And mốc "Hiện tại" phản ánh giá trị sau khi automation (nếu có) đã chạy

Maps to:

  • REL-06 (Be Affected - Automation HubSpot, ngoài hệ thống)

AC-X.3 - Token portal ​

gherkin
Given token HubSpot của portal dev không được cấu hình trong env_systems
When kiểm tra một ticket ở tab "Dev"
Then kết quả là 1 mốc "Hiện tại" với bước "fetch-ticket" Lỗi, không có hộp lỗi cấu hình

Maps to:

  • REL-03 (Affects - Cấu hình env_systems)