Giao diện
US-I01: Chọn môi trường và xem contact / deal đã tạo bằng tool ​
Thuộc FS: 00-overview.md — SAPP-24395 Contact / Deal instances & Bulk product creation 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 tại commit
e77c47a— suy từ code, chưa chạy thử.
| Field | Value |
|---|---|
| US ID | US-I01 |
| Role thực hiện | R1 - Người dùng tool (Assumption — OQ-I-16 về G-01) |
| Phase | As-built (đã triển khai) |
| Priority | N/A — as-built |
| Status | Draft |
| NFR liên quan | NFR-I-01, NFR-I-04, NFR-I-05, NFR-I-07 — xem Overview §5 |
| OQ liên quan | OQ-I-02, OQ-I-08, OQ-I-11, OQ-I-16, OQ-I-18, OQ-I-19 — xem Overview §6 |
Nguồn inventory: A-01, A-02, A-08.
1. US Statement ​
text
As a Người dùng tool (Assumption — OQ-I-16)
I want chọn môi trường HubSpot (Dev / Staging) và xem lại các contact, deal mà tool đã tạo ở môi trường đó
So that [Assumption] tôi dùng lại được dữ liệu test đã dựng (gắn contact vào deal mới, tìm lại deal để kiểm tra luồng ghi nhận doanh thu) mà không phải tra trên HubSpot2. Dependencies & Definition Of Ready ​
N/A — đã triển khai (Mode B). Dependency runtime:
| # | Cần sẵn sàng | Ai cung cấp | Trạng thái |
|---|---|---|---|
| D1 | Tool sapp.006 đang bật / mở khoá ở workspace (US-P02) | Admin CMS | N/A — runtime |
| D2 | Redis mind-keep hoạt động (danh sách lưu ở Redis) | Hạ tầng BE | N/A — runtime |
3. Business Rules ​
| ID | Rule | Áp dụng ở | Đã cover bởi (AC) | Nguồn code (Mode B/C) |
|---|---|---|---|---|
| BR-01 | Màn có 3 tab môi trường: Dev (mặc định khi mở), Staging, Prod. Tab Prod đang bị vô hiệu hoá, di chuột hiện "Tạm thời vô hiệu hóa" | M1 - tab môi trường | AC-M1.1, EC-M1.1 | fe/src/ui/components/works/sapp/sapp-24395-tool.tsx:49-54, :989, :1014-1021 |
| BR-02 | Đổi tab thì toàn bộ khu vực làm việc được dựng lại cho môi trường mới: nạp lại danh sách contact và deal, xoá lựa chọn contact và dữ liệu đang nhập trong form contact / deal | M1 - tab môi trường | AC-M1.2 | fe/src/ui/components/works/sapp/sapp-24395-tool.tsx:1038, :902-928 |
| BR-03 | Danh sách contact / deal tách riêng theo từng môi trường (prod / staging / dev) — kể cả staging và prod dùng chung một portal HubSpot, danh sách của hai tab vẫn khác nhau | M1 - danh sách | AC-M1.3 | be/libs/constants/src/lib/sapp/sapp.constants.ts:231-240 |
| BR-04 | Danh sách chỉ gồm contact / deal do tool này tạo (không đọc HubSpot), mỗi mục chỉ có id + tên (không lưu email / SĐT), theo thứ tự tạo | M1 - danh sách; M2 | AC-M1.3, AC-M2.1 | be/libs/modules/src/lib/sapp/common.service.ts:1557-1569, :1642-1650, :1666-1684 |
| BR-05 | Khi mở tab: tự nạp cả hai danh sách; nút "Tải lại" (mục 1) nạp lại danh sách contact; nút "Tải lại" ở chân modal lịch sử nạp lại danh sách deal | M1 - A1, A2; M2 - A2 | AC-M1.3, AC-M1.4, AC-M2.3 | fe/src/ui/components/works/sapp/sapp-24395-tool.tsx:908-928, :341-348, :846-857 |
| BR-06 | Lịch sử deal lọc theo tên deal chứa chuỗi tìm, không phân biệt hoa thường, bỏ khoảng trắng đầu cuối; chuỗi rỗng = hiện tất cả | M2 - ô tìm | AC-M2.2, EC-M2.2 | fe/src/ui/components/works/sapp/sapp-24395-tool.tsx:835-841 |
| BR-07 | Lỗi nạp danh sách hiện popup "Không tải được danh sách contact" / "Không tải được danh sách deal" với nội dung <message> (<code>) (13008 / 13010) | M1 - A1 | AC-M1.5 | fe/src/ui/components/works/sapp/sapp-24395-tool.tsx:916, :927; be/libs/constants/src/lib/error-codes/error-codes.constants.ts:579-592 |
Không phải BR (⚠️ Observed → OQ): danh sách không hết hạn / không xoá được (OQ-I-08); tên deal rỗng có thể làm hỏng ô tìm (OQ-I-11); contact trùng email lặp trong danh sách (OQ-I-18); tab Staging = portal prod, route prod BE vẫn mở (OQ-I-02, NFR-I-01).
4. Design ​
a. Mối liên hệ giữa các màn & User Flow ​
text
[Workspace SAPP › "Contact / Deal instances" (sapp.006)]
↓ vào màn (tab Dev mặc định)
[M1: Màn Contact / Deal instances — tab môi trường + mục 1 (contact) + mục 2 (deal)]
├─ đổi tab Dev ↔ Staging ──→ dựng lại M1 cho môi trường mới (BR-02)
├─ tick contact ──→ dùng ở US-I03
└─ bấm icon "Xem lịch sử deal đã tạo"
↓
[M2: Modal "Deal đã tạo (n)" — tìm theo tên deal]
└─ đóng ──→ về M1Link flow chi tiết: N/A.
b. Chi tiết từng màn ​
Màn M1 - Contact / Deal instances (khung + danh sách) ​
| Field | Value |
|---|---|
| Figma frame | N/A |
| Trigger vào màn | Mở tool "Contact / Deal instances" (/works/sapp/tools/sapp-24395) trong nhóm "SAPP 24395 - Tự động ghi nhận doanh thu" |
| Mô tả ngắn | Header "SAPP-24395 · Tự động ghi nhận doanh thu bán hàng CX", 3 tab môi trường, mục 1 "Tạo HubSpot contact instance" (form: US-I02, danh sách contact: US này), mục 2 "Tạo HubSpot deal instance theo case" (form: US-I03, số deal + nút lịch sử: US này) |
UI States ​
| State | Khi nào | Hiển thị | Figma frame |
|---|---|---|---|
| Default | Vừa vào màn | Tab Dev được chọn; tab Prod mờ, không bấm được | N/A |
| Loading | Đang nạp danh sách contact lần đầu | "Đang tải danh sách…" dưới nhãn "Contact đã tạo (0) — tick để gán vào deal"; icon "Tải lại" quay | N/A |
| Has data | Có contact | Danh sách checkbox (tối đa cao ~52 đơn vị, cuộn), mỗi dòng: tên + id; nhãn "Contact đã tạo (n) — tick để gán vào deal"; mục 2 hiện "Deal đã tạo (n)" | N/A |
| Empty | Chưa có contact nào | "Chưa có contact nào. Bấm "Tạo contact mặc định" để bắt đầu." (chữ lệch tên nút — OQ-I-19) | N/A |
| Error | API danh sách lỗi | Popup lỗi (BR-07); danh sách giữ trạng thái rỗng | N/A |
| Disabled | Tab Prod | Tab mờ, tooltip "Tạm thời vô hiệu hóa" | N/A |
Fields ​
| Field | Required | Type | Default | Format | Validation | Error Message | Visibility | Depends On |
|---|---|---|---|---|---|---|---|---|
| Tab môi trường | Yes | Tab (Dev / Staging / Prod) | Dev | — | Prod bị vô hiệu hoá (BR-01) | — | Always | — |
| Danh sách "Contact đã tạo" | No | Checkbox list (tên + id) | Không tick | id dạng số HubSpot | — | — | Always | Tab môi trường (BR-03) |
| "Deal đã tạo (n)" | — | Nhãn đếm + icon lịch sử | — | — | — | — | Always | Tab môi trường |
Filter / Search / Sort (chỉ màn List/Report — xóa nếu không phải) ​
N/A — danh sách contact ở M1 không có lọc / tìm / sắp xếp; thứ tự = thứ tự tạo (BR-04). Tìm deal nằm ở M2.
Actions ​
A1 - Chọn tab môi trường ​
| Item | Description |
|---|---|
| Trigger | Bấm tab Dev hoặc Staging |
| Behavior | Dựng lại khu vực làm việc cho môi trường đã chọn (BR-02), tự gọi đọc danh sách contact và deal của môi trường đó (BR-03, BR-05). Chỉ đọc Redis mind_keep, không gọi HubSpot. Lưu ý: chọn Staging thì các thao tác ghi sau đó (US-I02, US-I03) đi vào HubSpot PRODUCTION (NFR-I-05) |
| Success Result | Hiện danh sách của môi trường mới |
Error cases:
| Case | Expected Handling |
|---|---|
| Đọc danh sách lỗi | Popup BR-07 |
| Bấm tab Prod | Không phản hồi (tab bị vô hiệu hoá) |
A2 - Tải lại danh sách contact ​
| Item | Description |
|---|---|
| Trigger | Bấm "Tải lại" cạnh nút "Tạo contact" |
| Behavior | Gọi lại đọc danh sách contact của môi trường hiện tại (Redis). Không đổi lựa chọn đã tick |
| Success Result | Danh sách cập nhật |
Error cases:
| Case | Expected Handling |
|---|---|
| Đọc lỗi | Popup "Không tải được danh sách contact" |
A3 - Tick / bỏ tick contact ​
| Item | Description |
|---|---|
| Trigger | Bấm vào dòng contact |
| Behavior | Đảo trạng thái chọn; số contact đã chọn dùng ở US-I03 |
| Success Result | Dòng được tô nền khi chọn |
Error cases:
| Case | Expected Handling |
|---|---|
| — | Không có (thao tác cục bộ) |
Acceptance Criteria của màn M1 ​
AC-M1.1 - Mặc định Dev, Prod bị tắt ​
gherkin
Given người dùng mở màn Contact / Deal instances
When màn hiển thị xong
Then tab "Dev" đang được chọn
And tab "Prod" bị vô hiệu hoá, di chuột hiện "Tạm thời vô hiệu hóa"Maps to:
- Business Rule: BR-01
- Field/Action: Tab môi trường
AC-M1.2 - Đổi tab dựng lại khu vực làm việc ​
gherkin
Given đang ở tab Dev, đã tick 2 contact và nhập dở Họ tên ở form contact
When người dùng bấm tab "Staging"
Then danh sách contact và deal được nạp lại cho môi trường staging
And không còn contact nào được tick, form contact / deal trở về rỗngMaps to:
- Business Rule: BR-02
- Field/Action: A1
AC-M1.3 - Danh sách theo môi trường, chỉ do tool tạo ​
gherkin
Given tool đã tạo contact "A" ở tab Dev và contact "B" ở tab Staging
When người dùng mở tab Staging
Then danh sách "Contact đã tạo" chỉ có "B" (tên + id)
And không hiện email / SĐTMaps to:
- Business Rule: BR-03, BR-04, BR-05
AC-M1.4 - Tải lại ​
gherkin
Given danh sách contact đang hiển thị
When người dùng bấm "Tải lại"
Then danh sách contact của môi trường hiện tại được đọc lạiMaps to:
- Business Rule: BR-05
- Field/Action: A2
AC-M1.5 - Lỗi nạp danh sách ​
gherkin
Given Redis không đọc được
When màn nạp danh sách contact
Then hiện popup "Không tải được danh sách contact" với nội dung "Failed to list SAPP contact instances (13008)"Maps to:
- Business Rule: BR-07
Negative AC / Edge Cases của màn M1 ​
| ID | Tình huống | Hành vi mong đợi |
|---|---|---|
| EC-M1.1 | Gọi thẳng API môi trường prod (không qua giao diện) | ⚠️ Observed — route prod vẫn trả / ghi dữ liệu dù tab bị tắt, không cần đăng nhập (NFR-I-01 → OQ-I-02) |
| EC-M1.2 | Danh sách tích luỹ lâu ngày | ⚠️ Observed — danh sách không bao giờ hết hạn, không có nút / API xoá; chỉ tăng (OQ-I-08) |
| EC-M1.3 | Cùng một contact được "tạo" hai lần do trùng email | ⚠️ Observed (suy từ code) — contact đó xuất hiện 2 dòng cùng id; tick một dòng có thể tick cả hai (OQ-I-18) |
| EC-M1.4 | Mất mạng khi nạp | Popup lỗi chung "Không tải được danh sách …" với "Đã có lỗi xảy ra." nếu không có message |
| EC-M1.5 | Refresh trang | Quay về tab Dev, mất lựa chọn contact (không lưu ở trình duyệt); danh sách vẫn còn (Redis) |
Màn M2 - Modal lịch sử deal đã tạo ​
| Field | Value |
|---|---|
| Figma frame | N/A |
| Trigger vào màn | Bấm icon lịch sử cạnh "Deal đã tạo (n)" (tooltip "Xem lịch sử deal đã tạo") ở mục 2 |
| Mô tả ngắn | Modal "Deal đã tạo (n)", phụ đề "Tìm theo tên deal"; ô tìm + danh sách deal (tên + id); chân modal có "Tải lại" |
UI States ​
| State | Khi nào | Hiển thị | Figma frame |
|---|---|---|---|
| Default | Mở modal | Ô tìm trống, hiện tất cả deal | N/A |
| Loading | Đang nạp, chưa có deal | "Đang tải danh sách…" | N/A |
| Has data | Có deal khớp | Danh sách tên deal + id, cuộn được | N/A |
| Empty | Môi trường chưa có deal | "Chưa có deal nào." | N/A |
| Empty (lọc) | Có deal nhưng không khớp chuỗi | "Không tìm thấy deal khớp "<chuỗi>"." | N/A |
| Error | Nạp lỗi | Popup "Không tải được danh sách deal" (BR-07) | N/A |
| Disabled | — | N/A — không có trạng thái disabled | N/A |
Fields ​
| Field | Required | Type | Default | Format | Validation | Error Message | Visibility | Depends On |
|---|---|---|---|---|---|---|---|---|
| Ô tìm | No | Text | Rỗng | Placeholder "Tìm theo tên deal…" | BR-06 | — | Always | — |
| Dòng deal | — | Readonly (tên + id) | — | Tên dạng [IT TEST][SAPP-24395] <nhãn case> <n> (US-I03 BR-03) | — | — | Always | Tab môi trường |
Filter / Search / Sort (chỉ màn List/Report — xóa nếu không phải) ​
| Loại | Theo field | Kiểu | Default | Notes |
|---|---|---|---|---|
| Filter | — | — | — | N/A — không có |
| Search | Tên deal | free-text, chứa chuỗi, không phân biệt hoa thường | — | Lọc tại trình duyệt (BR-06) |
| Sort | — | — | Thứ tự tạo | Không đổi được |
| Pagination | — | — | Không phân trang | Cuộn trong modal |
Actions ​
A1 - Tìm deal ​
| Item | Description |
|---|---|
| Trigger | Gõ vào ô tìm |
| Behavior | Lọc tại chỗ theo BR-06; không gọi API |
| Success Result | Danh sách thu hẹp |
Error cases:
| Case | Expected Handling |
|---|---|
| Có deal tên rỗng (null) trong danh sách | ⚠️ Observed — ô tìm có thể lỗi khi gõ (OQ-I-11) |
A2 - Tải lại danh sách deal ​
| Item | Description |
|---|---|
| Trigger | Bấm "Tải lại" ở chân modal |
| Behavior | Đọc lại danh sách deal của môi trường (Redis) |
| Success Result | Danh sách + số đếm cập nhật |
Error cases:
| Case | Expected Handling |
|---|---|
| Đọc lỗi | Popup "Không tải được danh sách deal" |
Acceptance Criteria của màn M2 ​
AC-M2.1 - Mở lịch sử ​
gherkin
Given tool đã tạo 3 deal ở tab Dev
When người dùng bấm icon lịch sử
Then modal "Deal đã tạo (3)" hiện 3 dòng (tên + id) theo thứ tự tạoMaps to:
- Business Rule: BR-04
AC-M2.2 - Tìm không phân biệt hoa thường ​
gherkin
Given có deal "[IT TEST][SAPP-24395] Deal CBE 2"
When người dùng gõ " deal cbe "
Then deal đó vẫn hiện trong kết quảMaps to:
- Business Rule: BR-06
- Field/Action: A1
AC-M2.3 - Tải lại trong modal ​
gherkin
Given modal lịch sử đang mở
When người dùng bấm "Tải lại"
Then danh sách deal được đọc lại và số đếm cập nhậtMaps to:
- Business Rule: BR-05
- Field/Action: A2
Negative AC / Edge Cases của màn M2 ​
| ID | Tình huống | Hành vi mong đợi |
|---|---|---|
| EC-M2.1 | Deal có tên null | ⚠️ Observed — có thể lỗi khi lọc (OQ-I-11) |
| EC-M2.2 | Chuỗi tìm chỉ gồm khoảng trắng | Coi như rỗng, hiện tất cả |
| EC-M2.3 | Chuỗi tìm có ký tự đặc biệt / emoji | So khớp chuỗi thường (không regex), không lỗi |
| EC-M2.4 | Hai tab trình duyệt cùng tạo deal | Modal chỉ cập nhật khi bấm "Tải lại" |
5. Cross-feature AC ​
AC-X.1 - Tool bị khoá / tắt không vào được màn ​
gherkin
Given tool sapp.006 đang ở trạng thái khoá trên workspace
When người dùng mở /works/sapp/tools/sapp-24395
Then áp dụng hành vi khoá của nền tảng (US-P02); API của tool vẫn gọi được trực tiếp (NFR-I-01)Maps to:
- REL-01 (Affects - Nền tảng Hub / khoá tool)