Trường tuỳ chỉnh (Custom Fields)
⚠️ Đã ngừng phục vụ cho Telesales
Từ 14/08/2026, mọi endpoint /api/custom-fields cho hai entity TelesalesLead và TelesalesCallAttempt đã ngừng phục vụ và trả về HTTP 410 Gone. Các entity khác (Customer, Ticket) không bị ảnh hưởng.
Trường tuỳ chỉnh cho Telesales nay được quản lý qua Bộ dữ liệu (Dataset) — mỗi chiến dịch gắn với 1 bộ dữ liệu riêng, chứa cả field cho lead + kết quả cuộc gọi + mã kết quả. Xem tài liệu API mới tại Bộ dữ liệu Telesales (Datasets).
Bảng ánh xạ endpoint cũ ↔ mới:
| Endpoint cũ (410 Gone) | Endpoint mới thay thế |
|---|---|
GET /api/custom-fields?entity=TelesalesLead | GET /api/v1/telesales/datasets/{id} (lọc phase='lead') |
GET /api/custom-fields?entity=TelesalesCallAttempt | GET /api/v1/telesales/datasets/{id} (lọc phase='attempt') |
POST /api/custom-fields (Telesales) | POST /api/v1/telesales/datasets/{id}/fields |
PUT /api/custom-fields/{id} (Telesales) | PUT /api/v1/telesales/datasets/{id}/fields/{fid} |
DELETE /api/custom-fields/{id} (Telesales) | DELETE /api/v1/telesales/datasets/{id}/fields/{fid} |
Zorio cho phép quản trị viên tenant mở rộng dữ liệu Lead và Call Attempt bằng các trường bổ sung — không cần thay đổi cấu trúc cơ sở dữ liệu. Là đối tác tích hợp, bạn lấy danh sách trường tại thời điểm chạy hoặc lấy danh sách trường hiện có rồi dùng field_code để (a) ánh xạ cột CSV khi import lead và (b) gửi/nhận giá trị qua các endpoint Lead và Call Attempt.
Việc quản lý danh mục (tạo / sửa / xoá / gom nhóm) do quản trị viên thao tác trực tiếp trong portal Zorio, không thao tác qua API công khai.
Nội dung bên dưới chỉ áp dụng cho entity Customer / Ticket (module CSKH). Với Telesales, chuyển sang trang Bộ dữ liệu.
Entity được hỗ trợ
Trong phạm vi Telesales có 2 entity mở rộng được trường tuỳ chỉnh:
Giá trị entity | Ghi giá trị qua | Mục đích |
|---|---|---|
TelesalesLead | Import lead + PATCH /api/telesales/leads/{id} | Dữ liệu của Lead — agent thấy khi gọi |
TelesalesCallAttempt | POST /api/telesales/calls/{uuid}/disposition | Dữ liệu của cuộc gọi — kết quả agent điền khi đóng call |
Luôn filter ?entity=TelesalesLead hoặc ?entity=TelesalesCallAttempt khi gọi endpoint discovery bên dưới.
Danh mục kiểu field
type | Kiểu dữ liệu sau khi chuyển đổi | Rule có thể khai | Ghi chú |
|---|---|---|---|
text | string | max_length, regex_pattern | Free text 1 dòng |
textarea | string | max_length | Free text nhiều dòng |
richtext | HTML string (đã sanitize) | max_length | HTMLPurifier server-side |
number | integer hoặc decimal | min_value, max_value | Lưu dưới dạng decimal(18,4) |
date | ISO-8601 date (YYYY-MM-DD) | — | |
datetime | ISO-8601 datetime | — | Server chuẩn hoá về UTC |
boolean | true / false | — | Nhận "0"/"1"/"true"/"false" |
email | string | — | Check syntactic RFC-5321 |
phone | string | regex_pattern | Auto chuẩn hoá về 84xxx nếu có thể |
url | string | — | Bắt buộc scheme http:// hoặc https:// |
select | string | options[] | 1 giá trị trong options |
multiselect | array of string | options[] | 0..n giá trị trong options |
Thuộc tính chung mỗi field:
is_required— hệ thống từ chối khi field bị thiếu hoặc rỗng.is_unique— kiểm tra unique theo(tenant, entity, code).is_encrypted— giá trị mã hóa khi lưu trữ (at rest); response list mask thành***trừ khi caller có quyền phù hợp.default_value— được áp dụng khi dữ liệu đầu vào không có hoặc có giá trị null (chỉ Import).
GET /api/custom-fields — Lấy danh sách định nghĩa
Yêu cầu caller có quyền module crm (viewer trở lên). Cache 60 giây per (tenant, entity).
GET /api/custom-fields?entity=TelesalesLeadQuery params:
| Param | Mô tả |
|---|---|
entity | Bắt buộc cho context Telesales — set TelesalesLead hoặc TelesalesCallAttempt. |
include_inactive | true / false (mặc định false). Bao gồm field admin đã disable. Nên giữ mặc định — field inactive không nhận write mới. |
Response 200:
{
"data": [
{
"id": 41,
"entity": "TelesalesLead",
"code": "reference_code",
"label": "Mã tham chiếu",
"type": "text",
"options": null,
"is_required": true,
"is_unique": true,
"is_encrypted": false,
"max_length": 32,
"regex_pattern": "^REF-[0-9]{'{'}4,10{'}'}$",
"default_value": null,
"placeholder": "vd REF-000123",
"help_text": "Mã tham chiếu từ CRM nguồn",
"display_order": 10
},
{
"id": 42,
"entity": "TelesalesLead",
"code": "product_interest",
"label": "Sản phẩm quan tâm",
"type": "multiselect",
"options": ["Life", "Health", "Investment", "Motor"],
"is_required": false,
"help_text": "Multi-select — chọn mọi sản phẩm khách đã nhắc",
"display_order": 20
}
]
}Cách dùng phổ biến:
- Onboarding — gọi 1 lần, cache phía Client, dùng để render UI mapping cột CSV → field khi import.
- Trước mỗi import batch — gọi lại để phát hiện field mới quản trị viên có thể đã thêm.
- Trước mỗi PATCH lead / disposition — áp dụng cùng bộ quy tắc kiểm tra phía Client để user thấy lỗi trước khi hit server.
Pipeline kiểm tra khi ghi
Mọi endpoint ghi custom_fields đều đi qua cùng một pipeline server-side với 5 bước:
- Từ chối Field không tồn tại — key không có định nghĩa active → 422
unknown_field. - Chuyển đổi kiểu dữ liệu —
"42"→ int;"true"→ bool;"2026-01-15"→ Date. - Áp dụng quy tắc kiểm tra —
max_length,min_value,max_value,regex_pattern,optionsmembership. - Kiểm tra tính duy nhất — trả 422
duplicatekèmconflicting_record_id. - Encrypt — field
is_encrypted=trueđược mã hoá tự động.
Endpoint Import trả thống kê lỗi theo từng trường trong response 201 (xem Import lead). Endpoint PATCH lead trả breakdown per-field trong custom_fields_report (xem PATCH lead).
Lưu ý — không sửa danh mục qua SQL trực tiếp
Danh sách định nghĩa được cache 3600 giây. Cache tự invalidate khi admin sửa qua portal, nhưng nếu ai đó chỉnh trực tiếp custom_field_definitions bằng SQL (không thông qua Portal), cache sẽ giữ định nghĩa cũ đến hết TTL — dẫn tới hệ thống có thể áp dụng sai quy tắc kiểm tra (vd cho phép trùng dù đã bật is_unique=1).
Portal Zorio là nguồn duy nhất đáng tin cậy cho danh mục field. Nếu bạn migrate DB giữa các môi trường thủ công, sau khi migration xong hãy yêu cầu quản trị viên clear cache để hệ thống đọc định nghĩa mới nhất.
