Skip to content

US-T02: Làm mới cap_nhat_owner hàng loạt ​

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-06, A-07.

⚠️ Ghi PROD — US này ghi thuộc tính ticket lên HubSpot của portal đang chọn, kể cả portal prod.

FieldValue
US IDUS-T02
Role thực hiệnR1 - Người dùng tool Assumption (OQ về G-01); R2 - Hệ thống (ghi lịch sử)
PhaseĐã triển khai (as-built @ e77c47a)
PriorityN/A — as-built
StatusDraft
NFR liên quanNFR-T-01, NFR-T-02, NFR-T-03, NFR-T-05, NFR-T-07 — xem Overview §5
OQ liên quanOQ-T-01, OQ-T-02, OQ-T-03, OQ-T-07, OQ-T-08, OQ-T-09 — xem Overview §6

1. US Statement ​

text
As a Người dùng tool (Assumption — OQ về G-01)
I want chọn nhiều ticket rồi "làm mới" cap_nhat_owner của chúng — hệ thống ghi rỗng rồi ghi lại đúng giá trị cũ
       trên portal HubSpot đang chọn (Dev hoặc Prod) — và xem ticket nào đã làm mới / bỏ qua / lỗi
So that [Assumption — OQ-T-01] automation HubSpot bắt sự kiện đổi cap_nhat_owner chạy lại và gán owner cho ticket
        (màn tool tự mô tả: "reset + khôi phục cap_nhat_owner để kích hoạt lại automation")

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
D1Có kết quả truy vấn và ≥ 1 ticket được chọn (US-T01)Người dùngN/A — runtime
D2Token HubSpot của portal đang chọn có quyền ghi ticket, trong env_systems (US-P04)Admin CMSN/A — runtime
D3Redis của mind_keep hoạt động (lưu lịch sử — US-T04)Hạ tầngN/A — runtime

3. Business Rules ​

IDRuleÁp dụng ởĐã cover bởi (AC)Nguồn code (Mode B/C)
BR-01Làm mới chỉ chạy khi đã chọn ≥ 1 ticket và người dùng bấm "Làm mới" trong hộp xác nhận; hộp ghi số ticket và tên portal. Bấm "Hủy" thì không gọi gìM1 - action Xác nhận làm mớiAC-M1.1, AC-M1.2fe/src/ui/components/works/sapp/sapp-23954-tool.tsx:655-671, :776
BR-02Làm mới một ticket = đọc giá trị cap_nhat_owner hiện tại A → ghi cap_nhat_owner = rỗng → ghi lại A. Giá trị cuối cùng không đổi; chỉ thuộc tính cap_nhat_owner bị ghiM1 - action Xác nhận làm mớiAC-M1.3be/libs/modules/src/lib/sapp/common.service.ts:899-903, :927-959
BR-03Ticket có cap_nhat_owner đang rỗng → bỏ qua, lý do "cap_nhat_owner is empty", không ghi gì lên ticket đóM1 - action Xác nhận làm mới; M2 - nhóm Bỏ quaAC-M1.4be/libs/modules/src/lib/sapp/common.service.ts:944-947
BR-04Mỗi ticket xử lý độc lập: một ticket lỗi không dừng cả lượt; lỗi đọc / ghi của từng ticket (kể cả portal thiếu token) được đưa vào nhóm "lỗi" kèm lý do, cả lượt vẫn trả kết quảM1 - action Xác nhận làm mới; M2 - nhóm LỗiAC-M1.5, EC-M1.3be/libs/modules/src/lib/sapp/common.service.ts:925-926, :978-986
BR-05Các ticket được xử lý lần lượt theo thứ tự đã chọn, trong cùng một lần gọiM1 - action Xác nhận làm mớiAC-M1.3, NFR-T-03be/libs/modules/src/lib/sapp/common.service.ts:925-987
BR-06Kết quả gồm 3 nhóm: "đã làm mới", "bỏ qua", "lỗi"; mỗi ticket bỏ qua / lỗi có lý do. Sau khi xong, màn xoá lựa chọn và hiện hộp thành công "{x} làm mới · {y} bỏ qua · {z} lỗi (portal {env})."M2 - khối Kết quả làm mớiAC-M2.1, AC-M2.2fe/src/ui/components/works/sapp/sapp-23954-tool.tsx:145-176, :576-601
BR-07Khi có ≥ 1 ticket làm mới thành công, hộp thành công báo thêm "Sẽ tự kiểm tra thay đổi sau 15s." và hệ thống bắt đầu kiểm tra tự động (US-T03); không có ticket thành công thì không kiểm traM2 - hộp thành côngAC-M2.3fe/src/ui/components/works/sapp/sapp-23954-tool.tsx:583-598
BR-08Sau mỗi lượt, hệ thống ghi 1 dòng lịch sử cho mỗi ticket làm mới thành công vào lịch sử của portal đó; ticket bỏ qua / lỗi không ghi. Mọi dòng của cùng lượt có chung thời điểm làm mớiM1 - action Xác nhận làm mới (hệ thống)AC-M1.6be/libs/modules/src/lib/sapp/common.service.ts:971-977, :989, :1025, :1047-1060
BR-09Mỗi dòng lịch sử ghi: ticket, tên ticket, cap_nhat_owner "trước" → "sau", owner "trước" → "sau". "Sau" = giá trị đã ghi lại / owner lúc làm mới; "trước" = giá trị "sau" của dòng gần nhất cùng ticket trong lịch sử portal đó (lần đầu = trống)M1 - action Xác nhận làm mới (hệ thống)AC-M1.6, AC-M1.7be/libs/modules/src/lib/sapp/common.service.ts:1033-1060
BR-10Owner trong lịch sử hiển thị dạng "{tên} ({id})"; tên = "Tên Họ" của owner trên portal, không có thì email; không tra được tên thì chỉ id; ticket chưa có owner thì trốngM1 - action Xác nhận làm mới (hệ thống)AC-M1.7be/libs/modules/src/lib/sapp/common.service.ts:1281-1319, :976
BR-11Ghi lịch sử thất bại không làm lượt làm mới bị báo lỗi — chỉ ghi log hệ thốngM1 - action Xác nhận làm mới (hệ thống)EC-M1.5be/libs/modules/src/lib/sapp/common.service.ts:1067-1071
BR-12Làm mới chạy được trên cả portal prod và dev, theo tab đang chọn; biện pháp kiểm soát duy nhất là hộp xác nhận chung có ghi tên portal (không có bước xác nhận riêng cho prod)M1 - hộp xác nhậnAC-M1.1, EC-M1.1be/apps/api/src/sapp/sapp.controller.ts:321-337; fe/src/ui/components/works/sapp/sapp-23954-tool.tsx:58-61, :661

⚠️ Observed không viết thành BR: ghi lại thất bại → ticket bị bỏ rỗng, không thử lại / hoàn tác (EC-M1.2, OQ-T-09); không giới hạn số ticket mỗi lượt, tuần tự trong 1 request (EC-M1.4, NFR-T-03, OQ-T-08); ghi prod không có chốt chặn riêng (EC-M1.1, OQ-T-03); làm mới mọi giá trị khác rỗng (EC-M1.6, OQ-T-07).

4. Design ​

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

text
[US-T01 M1: Bảng kết quả, đã chọn N ticket]
  ↓ bấm "Làm mới cap_nhat_owner (N)"
[M1: Hộp xác nhận "Làm mới cap_nhat_owner"]
  ├─ "Hủy" ──→ đóng hộp, không ghi gì
  └─ "Làm mới" ──→ BE xử lý tuần tự N ticket (đọc → ghi rỗng → ghi lại) trên portal đang chọn
                    ↓ ghi lịch sử cho ticket thành công (US-T04)
                  [Hộp thành công] + [M2: Khối "Kết quả làm mới"]
                    └─ ≥ 1 ticket thành công ──→ đếm ngược 15s ──→ US-T03
  └─ cả request lỗi ──→ hộp lỗi "Làm mới cap_nhat_owner thất bại"

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

  • Trạng thái cap_nhat_owner của 1 ticket: inventory 23954 §5 (sơ đồ sau bảng Rule).

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

Màn M1 - Hộp xác nhận "Làm mới cap_nhat_owner" ​

FieldValue
Figma frameN/A
Trigger vào mànBấm "Làm mới cap_nhat_owner (N)" ở bảng kết quả US-T01 (N ≥ 1)
Mô tả ngắnHộp xác nhận chung của hệ thống: "Sẽ reset về rỗng rồi khôi phục cap_nhat_owner cho {N} ticket trong portal {env}. Ticket đang rỗng sẽ bị bỏ qua." với 2 nút "Làm mới" / "Hủy"
UI States ​
StateKhi nàoHiển thịFigma frame
DefaultHộp vừa mởTiêu đề "Làm mới cap_nhat_owner", nội dung có số ticket và tên portal (dev / prod), nút "Làm mới", "Hủy"N/A
LoadingĐã bấm "Làm mới", đang chờ BEHộp đóng; nút ở bảng hiện "Đang làm mới…" có spinner, bị khoáN/A
Has dataBE trả kết quảChuyển sang hộp thành công + M2N/A
EmptyN/A — hộp không mở khi chưa chọn ticket—N/A
ErrorCả request lỗiHộp lỗi "Làm mới cap_nhat_owner thất bại", nội dung "{thông điệp} ({mã})"N/A
DisabledChưa chọn ticket / đang làm mớiNút "Làm mới cap_nhat_owner (0)" khoá; đang làm mới thì khoáN/A
Fields ​
FieldRequiredTypeDefaultFormatValidationError MessageVisibilityDepends On
Danh sách ticket đã chọn (ẩn, lấy từ US-T01)YesDanh sách Ticket IDCác dòng đang chọnchuỗi id≥ 1 ở màn (BR-01); API chấp nhận cả danh sách rỗng, không giới hạn số phần tử—Hidden (chỉ hiện số N)Lựa chọn ở US-T01
Filter / Search / Sort (chỉ màn List/Report — xóa nếu không phải) ​

N/A — hộp xác nhận, không phải màn List.

Actions ​
A1 - Xác nhận làm mới ​
ItemDescription
TriggerBấm "Làm mới" trong hộp xác nhận
BehaviorGửi danh sách ticket tới BE của portal đang chọn. BE: tải danh sách owner của portal (để hiển thị tên — BR-10); với từng ticket lần lượt (BR-05): đọc tên, cap_nhat_owner, owner; rỗng → bỏ qua (BR-03); khác rỗng → ghi rỗng rồi ghi lại giá trị cũ (BR-02); lỗi → nhóm lỗi (BR-04). Cuối lượt: ghi lịch sử cho ticket thành công (BR-08, BR-09) vào Redis của mind_keep. Ghi vào: HubSpot CRM, thuộc tính cap_nhat_owner của ticket, portal dev hoặc prod theo tab; Redis mind_keep (lịch sử, key theo portal).
Success ResultTrả 3 nhóm đã làm mới / bỏ qua / lỗi → M2

⚠️ Ghi PROD — trên tab Prod, action này ghi cap_nhat_owner của ticket thật trên HubSpot production, mỗi ticket 2 lần ghi, có thể kích hoạt automation thật (REL-06). Không có giới hạn số ticket, không có xác nhận riêng cho prod (OQ-T-03, OQ-T-08).

Error cases:

CaseExpected Handling
Ticket cap_nhat_owner rỗngVào nhóm "bỏ qua" với lý do "cap_nhat_owner is empty"; không ghi (BR-03)
Đọc ticket lỗi / ghi rỗng lỗi / portal thiếu tokenVào nhóm "lỗi" với lý do là thông điệp lỗi kỹ thuật (mặc định "Failed to refresh cap_nhat_owner"); nếu lỗi ở bước ghi rỗng thì giá trị trên HubSpot chưa bị đổi. Cả request vẫn thành công (BR-04, DR-T-03)
Ghi rỗng thành công nhưng ghi lại lỗi⚠️ Observed — vào nhóm "lỗi" với lý do "Failed to restore cap_nhat_owner (left empty)"; ticket bị bỏ rỗng trên HubSpot (EC-M1.2)
Cả request lỗi (mạng, lỗi không lường trước)Hộp lỗi "Làm mới cap_nhat_owner thất bại"; lỗi không xác định phía BE trả "Failed to refresh SAPP-23954 cap_nhat_owner (13023)". Lựa chọn giữ nguyên
A2 - Hủy ​
ItemDescription
TriggerBấm "Hủy"
BehaviorĐóng hộp, không gọi API, không ghi dữ liệu
Success ResultQuay lại bảng US-T01, lựa chọn giữ nguyên

Error cases:

CaseExpected Handling
N/AKhông có lỗi
Acceptance Criteria của màn M1 ​
AC-M1.1 - Hộp xác nhận ghi số ticket và portal ​
gherkin
Given đang ở tab "Prod" và đã chọn 3 ticket
When bấm "Làm mới cap_nhat_owner (3)"
Then hiện hộp "Làm mới cap_nhat_owner" với nội dung "Sẽ reset về rỗng rồi khôi phục cap_nhat_owner cho 3 ticket trong portal prod. Ticket đang rỗng sẽ bị bỏ qua."
And chưa có ticket nào bị ghi cho tới khi bấm "Làm mới"

Maps to:

  • Business Rule: BR-01, BR-12
  • Field/Action: A1
AC-M1.2 - Hủy không ghi gì ​
gherkin
Given hộp xác nhận đang mở cho 3 ticket
When bấm "Hủy"
Then hộp đóng, không có lời gọi làm mới nào, 3 ticket vẫn đang được chọn

Maps to:

  • Business Rule: BR-01
  • Field/Action: A2
AC-M1.3 - Làm mới giữ nguyên giá trị cuối ​
gherkin
Given ticket T1 có cap_nhat_owner = "Xử lý ticket thông thường"
When xác nhận làm mới T1
Then lịch sử thuộc tính cap_nhat_owner của T1 trên HubSpot có thêm 2 lần đổi: rỗng, rồi "Xử lý ticket thông thường"
And giá trị cap_nhat_owner hiện tại của T1 vẫn là "Xử lý ticket thông thường"
And T1 thuộc nhóm "đã làm mới"

Maps to:

  • Business Rule: BR-02, BR-05
AC-M1.4 - Bỏ qua ticket rỗng ​
gherkin
Given ticket T2 có cap_nhat_owner rỗng
When xác nhận làm mới T1, T2
Then T2 thuộc nhóm "bỏ qua" với lý do "cap_nhat_owner is empty"
And không có lần ghi nào lên T2

Maps to:

  • Business Rule: BR-03
AC-M1.5 - Một ticket lỗi không dừng lượt ​
gherkin
Given danh sách chọn gồm T1 (hợp lệ), T3 (không đọc được trên HubSpot), T4 (hợp lệ)
When xác nhận làm mới
Then T3 thuộc nhóm "lỗi" kèm lý do
And T1 và T4 vẫn được làm mới và thuộc nhóm "đã làm mới"

Maps to:

  • Business Rule: BR-04
AC-M1.6 - Ghi lịch sử cho ticket thành công ​
gherkin
Given lượt làm mới có T1 thành công, T2 bỏ qua, T3 lỗi trên portal dev
When lượt kết thúc
Then lịch sử làm mới của portal dev có thêm đúng 1 dòng cho T1, không có dòng cho T2, T3
And dòng T1 có "sau" cap_nhat_owner = giá trị đã ghi lại, thời gian = thời điểm của lượt

Maps to:

  • Business Rule: BR-08, BR-09
AC-M1.7 - "Trước" lấy từ dòng gần nhất cùng ticket ​
gherkin
Given lịch sử portal dev đã có 1 dòng của T1 với "sau" cap_nhat_owner = "Xử lý ticket thông thường" và owner "sau" = "Nguyễn An (123)"
When làm mới T1 lần nữa
Then dòng mới của T1 có "trước" cap_nhat_owner = "Xử lý ticket thông thường" và owner "trước" = "Nguyễn An (123)"
And nếu T1 chưa từng có dòng nào thì "trước" để trống

Maps to:

  • Business Rule: BR-09, BR-10
Negative AC / Edge Cases của màn M1 ​
IDTình huốngHành vi mong đợi
EC-M1.1⚠️ Observed — chạy trên tab ProdHành vi hiện tại: ghi thật lên HubSpot production; chốt chặn duy nhất là hộp xác nhận chung có chữ "portal prod"; không có xác nhận thêm, không giới hạn quyền ở API (NFR-T-01). Nguồn: be/apps/api/src/sapp/sapp.controller.ts:321-337; fe/src/ui/components/works/sapp/sapp-23954-tool.tsx:661. Cố ý hay rủi ro: OQ-T-03
EC-M1.2⚠️ Observed — ghi rỗng thành công, ghi lại thất bạiHành vi hiện tại: ticket vào nhóm "lỗi" với lý do "Failed to restore cap_nhat_owner (left empty)" và bị bỏ rỗng cap_nhat_owner trên HubSpot (kể cả prod); không thử lại, không hoàn tác, không ghi lịch sử cho ticket này; người dùng phải tự sửa trên HubSpot. Nguồn: be/libs/modules/src/lib/sapp/common.service.ts:953-969. Cố ý hay thiếu sót: OQ-T-09
EC-M1.3Portal chưa cấu hình token HubSpotHành vi hiện tại: mọi ticket vào nhóm "lỗi" (lý do là thông điệp thiếu cấu hình), request vẫn trả thành công — không có hộp lỗi cấu hình. Khác API doc (DR-T-03)
EC-M1.4⚠️ Observed — chọn rất nhiều ticket (vd vài trăm sau nhiều lần "Tải thêm" + "Chọn tất cả")Hành vi hiện tại: không có giới hạn; BE xử lý tuần tự 1 đọc + 2 ghi mỗi ticket trong một request; màn chỉ hiện "Đang làm mới…" tới khi xong, không có tiến độ. Rủi ro timeout / HubSpot rate-limit — nếu request đứt giữa chừng thì một phần ticket đã được ghi mà màn không nhận được kết quả. Nguồn: be/libs/interface/src/lib/dto/sapp/sapp-23954-ticket.dto.ts:114-120; be/libs/modules/src/lib/sapp/common.service.ts:925-987. NFR-T-03, OQ-T-08 (chưa chạy thử để xác nhận)
EC-M1.5Redis lỗi khi ghi lịch sửKết quả làm mới vẫn trả bình thường; lịch sử của lượt đó không được lưu; chỉ có log hệ thống (BR-11)
EC-M1.6⚠️ Observed — ticket có cap_nhat_owner = "Cập nhật thành công" / "Cập nhật thất bại" / "Rotate Ticket Owner"Hành vi hiện tại: vẫn được làm mới như mọi giá trị khác rỗng (không lọc theo giá trị). Nguồn: be/libs/modules/src/lib/sapp/common.service.ts:944-959. OQ-T-07
EC-M1.7Cùng ticket bị chọn làm mới ở 2 tab / 2 người cùng lúcKhông có khoá; mỗi lượt đọc giá trị riêng rồi ghi rỗng / ghi lại. Hành vi xen kẽ chưa kiểm chứng (không chạy thử)
EC-M1.8Đóng / refresh trang khi đang làm mớiMàn không còn nhận kết quả; code không có cơ chế huỷ lượt phía BE — ticket nào đã / chưa được ghi chưa kiểm chứng (không chạy thử). Xem lịch sử (US-T04) để biết ticket nào đã thành công

Màn M2 - Khối "Kết quả làm mới" và hộp thành công ​

FieldValue
Figma frameN/A
Trigger vào mànBE trả kết quả của A1
Mô tả ngắnHộp thành công "Đã làm mới cap_nhat_owner" + khối "Kết quả làm mới" dưới bảng: 3 nhãn đếm và 2 danh sách lý do thu gọn được
UI States ​
StateKhi nàoHiển thịFigma frame
DefaultVừa nhận kết quảHộp thành công: "{x} làm mới · {y} bỏ qua · {z} lỗi (portal {env})." (+ " Sẽ tự kiểm tra thay đổi sau 15s." nếu x > 0). Khối: nhãn "{x} đã làm mới", "{y} bỏ qua", "{z} lỗi" (nhãn lỗi tô đỏ khi z > 0)N/A
LoadingN/A — kết quả hiển thị một lần—N/A
Has dataCó ticket bỏ qua / lỗiDanh sách thu gọn "Bỏ qua (cap_nhat_owner rỗng) ({y})" và "Lỗi ({z})"; mở ra thấy từng dòng "Ticket ID — lý do"N/A
EmptyKhông có ticket bỏ qua / lỗiKhông hiện danh sách tương ứngN/A
ErrorN/A — lỗi cả request ở M1—N/A
DisabledN/A—N/A
Fields ​
FieldRequiredTypeDefaultFormatValidationError MessageVisibilityDepends On
Số đã làm mới—Number—"{x} đã làm mới"——ReadonlyKết quả A1
Số bỏ qua—Number—"{y} bỏ qua"——ReadonlyKết quả A1
Số lỗi—Number—"{z} lỗi"——ReadonlyKết quả A1
Danh sách bỏ qua / lỗi—List (Ticket ID, lý do)Thu gọn———Hiện khi có dòngKết quả A1
Filter / Search / Sort (chỉ màn List/Report — xóa nếu không phải) ​

N/A — khối kết quả, không phải màn List.

Actions ​
A1 - Mở / thu gọn danh sách lý do ​
ItemDescription
TriggerBấm tiêu đề "Bỏ qua (…)" hoặc "Lỗi (…)"
BehaviorMở / thu gọn danh sách. Không gọi API, không ghi dữ liệu
Success ResultHiện từng Ticket ID kèm lý do

Error cases:

CaseExpected Handling
N/AKhông có lỗi
Acceptance Criteria của màn M2 ​
AC-M2.1 - Tổng hợp kết quả ​
gherkin
Given lượt làm mới trên portal dev có 2 ticket thành công, 1 bỏ qua, 1 lỗi
When BE trả kết quả
Then hộp thành công hiển thị "2 làm mới · 1 bỏ qua · 1 lỗi (portal dev). Sẽ tự kiểm tra thay đổi sau 15s."
And khối "Kết quả làm mới" có nhãn "2 đã làm mới", "1 bỏ qua", "1 lỗi"
And bảng ở US-T01 về "đã chọn 0"

Maps to:

  • Business Rule: BR-06, BR-07
AC-M2.2 - Xem lý do ​
gherkin
Given khối kết quả có 1 ticket lỗi
When bấm "Lỗi (1)"
Then hiện dòng gồm Ticket ID và lý do lỗi của ticket đó

Maps to:

  • Business Rule: BR-06
  • Field/Action: M2.A1
AC-M2.3 - Không có ticket thành công thì không tự kiểm tra ​
gherkin
Given mọi ticket trong lượt đều bị bỏ qua hoặc lỗi
When BE trả kết quả
Then hộp thành công không có câu "Sẽ tự kiểm tra thay đổi sau 15s."
And không có đếm ngược kiểm tra (US-T03)

Maps to:

  • Business Rule: BR-07
Negative AC / Edge Cases của màn M2 ​
IDTình huốngHành vi mong đợi
EC-M2.1Truy vấn lại (US-T01) sau khi làm mớiKhối "Kết quả làm mới" biến mất (US-T01 BR-09)
EC-M2.2Đổi tab Dev ↔ ProdKhối kết quả mất (panel dựng lại — OQ-T-15)
EC-M2.3Lý do lỗi là thông điệp kỹ thuật tiếng AnhHiển thị nguyên văn, không dịch

5. Cross-feature AC ​

AC-X.1 - Kích hoạt lại automation HubSpot ​

gherkin
Given trên HubSpot có automation bắt sự kiện đổi cap_nhat_owner của ticket
When làm mới thành công ticket T1
Then HubSpot ghi nhận 2 lần đổi cap_nhat_owner của T1 (rỗng, rồi giá trị cũ) có thể kích hoạt automation đó
And kết quả automation (nếu có) được US-T03 đo lại sau 15 giây

Maps to:

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

AC-X.2 - Token portal ​

gherkin
Given token HubSpot của portal prod bị xoá khỏi cấu hình env_systems
When xác nhận làm mới 2 ticket trên tab Prod
Then cả 2 ticket vào nhóm "lỗi", không có ticket nào bị ghi

Maps to:

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