Giao diện
US-H02: Clone property từ prod sang dev ​
Thuộc FS: 00-overview.md — SAPP HubSpot tools (sapp.001–004) 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. Nguồn: inventory A-03 (và A-11 cho popup lỗi).
| Field | Value |
|---|---|
| US ID | US-H02 |
| Role thực hiện | R1 - Người dùng tool (Assumption — OQ-H-01 về G-01) |
| Phase | As-built (đã triển khai) |
| Priority | N/A — as-built |
| Status | Draft |
| NFR liên quan | NFR-H-01, NFR-H-02, NFR-H-04, NFR-H-05, NFR-H-07 — xem Overview §5 |
| OQ liên quan | OQ-H-01, OQ-H-02, OQ-H-04, OQ-H-05, OQ-H-06 — xem Overview §6 |
1. US Statement ​
text
As a Người dùng tool [Assumption — OQ-H-01 về G-01]
I want chọn loại object, nhập internal name của một property prod rồi clone định nghĩa đó sang portal dev
So that [Assumption — OQ-H-04] portal dev có cùng property như prod để dựng và chạy dữ liệu test2. 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.001 đang bật / hiển thị / đã mở khoá — US-P02 | Admin CMS | Runtime |
| D2 | env_systems: cả SAPP_PROD_HUBSPOT_ACCESS_TOKEN (đọc nguồn) và SAPP_DEV_HUBSPOT_ACCESS_TOKEN (ghi đích) — US-P04 | Admin CMS | Runtime |
3. Business Rules ​
| ID | Rule | Áp dụng ở | Đã cover bởi (AC) | Nguồn code (Mode B/C) |
|---|---|---|---|---|
| BR-01 | Clone luôn một chiều: nguồn là portal prod, đích là portal dev; màn không cho chọn chiều hay môi trường | M1 - action A1 | AC-M1.1 | be/apps/api/src/sapp/sapp.controller.ts:626-630; fe/src/data/constants/api.ts:184-187 |
| BR-02 | Loại object: Deal / Ticket / Contact, mặc định Deal | M1 - field Object type | AC-M1.1 | fe/src/ui/components/works/sapp/clone-tool.tsx:23-27,32 |
| BR-03 | Phải nhập tên property (sau khi cắt khoảng trắng) mới được clone; thiếu → popup "Missing property name", không gọi API | M1 - action A1 | AC-M1.2 | fe/src/ui/components/works/sapp/clone-tool.tsx:76-85 |
| BR-04 | Không ghi đè: nếu dev đã có property cùng tên, trả nguyên property dev đó, không đổi label / options (NFR-H-07). Mô tả màn cũng ghi "Existing dev properties are never overwritten." | M1 - action A1 | AC-M1.3 | be/libs/modules/src/lib/hubspot/common.service.ts:841-848; be/apps/api/src/sapp/sapp.controller.ts:626-631; fe/src/ui/components/works/sapp/clone-tool.tsx:101-102 |
| BR-05 | Property tạo mới ở dev chỉ chép: name, label, type, field type, description và options (mỗi option: label, value, description, thứ tự, hidden — hidden thiếu thì = không ẩn) | M1 - action A1 | AC-M1.1 | be/libs/modules/src/lib/hubspot/common.service.ts:678-698 |
| BR-06 | Nhóm property (group) của nguồn bị bỏ; property mới luôn nằm ở nhóm chuẩn của object: Deal → dealinformation, Contact → contactinformation, Ticket → ticketinformation | M1 - action A1 | AC-M1.1 | be/libs/modules/src/lib/hubspot/common.service.ts:684-689; be/libs/constants/src/lib/hubspot/hubspot.constants.ts:39-43 |
| BR-07 | Property nguồn không đọc được ở prod → lỗi 12003 "HubSpot property not found" | M1 - action A1 | EC-M1.1 | be/libs/modules/src/lib/hubspot/common.service.ts:830-836,500-505 |
| BR-08 | Tạo property ở dev thất bại → lỗi 12004 "Failed to clone HubSpot property" | M1 - action A1 | EC-M1.2 | be/libs/modules/src/lib/hubspot/common.service.ts:864-874 |
| BR-09 | Thành công → hiện khối "Dev property" chứa JSON property ở dev (bản mới tạo hoặc bản đã có) + nút "Copy JSON" | M1 - state Has data | AC-M1.1, AC-M1.3 | fe/src/ui/components/works/sapp/clone-tool.tsx:62-64,141-158 |
| BR-10 | Lỗi gọi API → popup "Failed to clone property", nội dung message (code) (NFR-H-04) | M1 - action A1 | EC-M1.1, EC-M1.2 | fe/src/ui/components/works/sapp/clone-tool.tsx:46-60 |
⚠️ Observed (không phải BR): popup thành công luôn "Clone completed — Property "
<name>" is now available in the dev portal.", kể cả khi không tạo gì (dev đã có) — AC-M1.3, OQ-H-05. Mọi lỗi đọc prod đều là12003— EC-M1.1, OQ-H-06.
4. Design ​
a. Mối liên hệ giữa các màn & User Flow ​
text
[Sidebar "SAPP Common Hubspot Tools" → "Clone"] (US-P01, gate US-P02)
↓
[M1: Clone property: prod → dev]
├─ thiếu tên ───────────────────────→ popup "Missing property name"
├─ dev chưa có → tạo ở dev ─────────→ popup "Clone completed" + JSON property dev
├─ dev đã có → không tạo ───────────→ popup "Clone completed" (⚠️ Observed) + JSON property dev cũ
└─ lỗi (12001/12003/12004) ─────────→ popup "Failed to clone property"Link flow chi tiết: N/A — as-built, không có Figma.
b. Chi tiết từng màn ​
Màn M1 - Clone property: prod → dev ​
| Field | Value |
|---|---|
| Figma frame | N/A |
| Trigger vào màn | Mở /works/sapp/tools/hs-clone-prod-to-dev (sidebar "Clone") hoặc link chia sẻ |
| Mô tả ngắn | Tiêu đề "Clone property: prod → dev"; mô tả "Copy a deal / ticket / contact property definition from the prod portal into dev. Existing dev properties are never overwritten." (fe/src/ui/components/works/sapp/clone-tool.tsx:92-105) |
UI States ​
| State | Khi nào | Hiển thị | Figma frame |
|---|---|---|---|
| Default | Vừa vào màn | Object type = Deal, ô "Property internal name" trống (placeholder "e.g. dealstage"), nút "Clone to dev". Không có ô chọn môi trường | N/A |
| Loading | Đang gọi API | Nút "Cloning…"; ô chọn, ô nhập, nút bị khoá (NFR-H-05) | N/A |
| Has data | Clone trả về property | Popup "Clone completed"; bên dưới khối "Dev property" với JSON + "Copy JSON" | N/A |
| Empty | N/A — không có danh sách | — | N/A |
| Error | Thiếu tên / API lỗi | Popup lỗi; không có khối kết quả | N/A |
| Disabled | Đang gọi API | Như Loading | N/A |
Fields ​
| Field | Required | Type | Default | Format | Validation | Error Message | Visibility | Depends On |
|---|---|---|---|---|---|---|---|---|
| Object type | Yes | Dropdown: Deal / Ticket / Contact | Deal | — | BR-02 | — | Always | — |
| Property internal name | Yes | Text | Trống | Cắt khoảng trắng hai đầu | BR-03 | "Missing property name" — "Please enter the HubSpot internal property name to clone." | Always | — |
| Kết quả: Dev property (JSON) | — | Readonly JSON | — | JSON thụt lề 2 | — | — | Sau khi clone thành công | BR-09 |
Filter / Search / Sort ​
N/A — màn thao tác một property, không phải List / Report.
Actions ​
A1 - Clone to dev ​
| Item | Description |
|---|---|
| Trigger | Bấm "Clone to dev" hoặc nhấn Enter trong ô tên (fe/src/ui/components/works/sapp/clone-tool.tsx:124,131-138) |
| Behavior | Kiểm BR-03 → xoá kết quả cũ → gọi POST /api/v1/sapp/dev/hubspot/{deals|contacts|tickets}/properties/clone-prod/:property. BE: (1) đọc property ở HubSpot portal prod; (2) đọc property cùng tên ở portal dev; (3) dev đã có → trả nguyên (BR-04); chưa có → ghi: tạo property mới ở HubSpot portal dev với payload theo BR-05, BR-06. Không ghi prod. |
| Success Result | Popup "Clone completed" + khối "Dev property" (BR-09) |
Error cases:
| Case | Expected Handling |
|---|---|
| Thiếu tên property | Popup "Missing property name" (BR-03) |
| Property không có ở prod / lỗi đọc prod | Popup "Failed to clone property" — "HubSpot property not found (12003)" (BR-07; ⚠️ Observed EC-M1.1) |
| Token prod hoặc dev chưa cấu hình | Popup "Failed to clone property" — "HubSpot access token is not configured for this environment (12001)" (NFR-H-02) |
| HubSpot dev từ chối tạo | Popup "Failed to clone property" — "Failed to clone HubSpot property (12004)" (BR-08) |
A2 - Copy JSON ​
| Item | Description |
|---|---|
| Trigger | Bấm "Copy JSON" ở khối "Dev property" |
| Behavior | Chép JSON vào clipboard; không gọi API, không ghi hệ thống nào (fe/src/ui/components/works/sapp/clone-tool.tsx:145-153) |
| Success Result | Clipboard chứa JSON, không có thông báo |
Error cases:
| Case | Expected Handling |
|---|---|
| Trình duyệt chặn clipboard | Không có xử lý riêng — không hiện thông báo |
Acceptance Criteria của màn M1 ​
AC-M1.1 - Clone tạo mới ở dev ​
gherkin
Given portal prod có property Deal "course_code" thuộc nhóm "sapp_custom", có 3 option
And portal dev chưa có property "course_code"
When người dùng chọn Object type = Deal, nhập "course_code" và bấm "Clone to dev"
Then portal dev có property "course_code" mới với cùng name, label, type, field type, description và 3 option
And nhóm của property mới là "dealinformation" (không phải "sapp_custom")
And portal prod không bị thay đổi
And hiện popup "Clone completed" và khối "Dev property" chứa JSON property devMaps to:
- Business Rule: BR-01, BR-02, BR-05, BR-06, BR-09
- Field/Action: A1
AC-M1.2 - Thiếu tên property ​
gherkin
Given ô "Property internal name" trống hoặc chỉ có khoảng trắng
When người dùng bấm "Clone to dev"
Then hiện popup "Missing property name" — "Please enter the HubSpot internal property name to clone."
And không có lời gọi API nàoMaps to:
- Business Rule: BR-03
AC-M1.3 - Dev đã có property cùng tên (hành vi hiện tại) ​
gherkin
Given portal dev đã có property Deal "course_code" với 2 option, prod có 3 option
When người dùng clone "course_code"
Then không có gì được tạo hay sửa ở dev (vẫn 2 option)
And khối "Dev property" hiện JSON của bản dev cũ
And ⚠️ Observed: popup vẫn là "Clone completed — Property "course_code" is now available in the dev portal.", không nói là đã có sẵn / không cập nhật (OQ-H-05)Maps to:
- Business Rule: BR-04, BR-09
- NFR: NFR-H-07
- OQ: OQ-H-05
Negative AC / Edge Cases của màn M1 ​
| ID | Tình huống | Hành vi mong đợi |
|---|---|---|
| EC-M1.1 | Property không tồn tại ở prod, hoặc token prod hỏng / rate limit / HubSpot lỗi | ⚠️ Observed — hành vi hiện tại: đều báo "HubSpot property not found (12003)" (be/libs/modules/src/lib/hubspot/common.service.ts:500-505) — OQ-H-06 |
| EC-M1.2 | HubSpot dev từ chối tạo (vd kiểu dữ liệu không hợp lệ ở dev) | Popup "Failed to clone property" — "Failed to clone HubSpot property (12004)" (BR-08); không có gì được tạo |
| EC-M1.3 | Lỗi khi kiểm tra tồn tại ở dev (không phải "không tồn tại") | Code coi như chưa có và thử tạo; tạo lỗi → 12004 (be/libs/modules/src/lib/hubspot/common.service.ts:841-847,864-874) — suy từ code, chưa chạy thử |
| EC-M1.4 | Bấm clone hai lần liên tiếp cùng tên | Lần hai rơi vào AC-M1.3 — không tạo trùng (NFR-H-07) |
| EC-M1.5 | Muốn clone dev → prod hoặc ghi đè bản dev | Không hỗ trợ trên UI / API (BR-01, BR-04); tuỳ chọn ghi đè có trong service nhưng không bật — OQ-H-05 |
5. Cross-feature AC ​
AC-X.1 - Tool bị gate chặn ​
gherkin
Given tool sapp.001 đang bị ẩn / tắt / khoá mã bí mật
When người dùng mở /works/sapp/tools/hs-clone-prod-to-dev
Then hành vi theo gate của nền tảng (US-P02)
And route clone vẫn gọi trực tiếp được, ghi vào portal dev (NFR-P-01, Overview §2.2)Maps to:
- REL-H-01 (Affects - Hub + gate tool)
AC-X.2 - Cần cả hai token ​
gherkin
Given SAPP_DEV_HUBSPOT_ACCESS_TOKEN chưa cấu hình, SAPP_PROD_HUBSPOT_ACCESS_TOKEN có
When người dùng clone một property có ở prod
Then nhận lỗi 12001 và không có gì được tạo ở devMaps to:
- REL-H-02 (Affects - Cấu hình env_systems)
AC-X.3 - Property clone về dev dùng tiếp ở tool thêm option ​
gherkin
Given property danh sách vừa được clone sang dev bằng US-H02
When người dùng thêm option cho property đó bằng tool US-P07
Then option được thêm trên chính property dev đã clone [Assumption — quan hệ dữ liệu, chưa chạy thử]Maps to:
- REL-H-03 (Be Affected - Thêm option property HubSpot dev)