Skip to content

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 TelesalesLeadTelesalesCallAttempt đã 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=TelesalesLeadGET /api/v1/telesales/datasets/{id} (lọc phase='lead')
GET /api/custom-fields?entity=TelesalesCallAttemptGET /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ị entityGhi giá trị quaMục đích
TelesalesLeadImport lead + PATCH /api/telesales/leads/{id}Dữ liệu của Lead — agent thấy khi gọi
TelesalesCallAttemptPOST /api/telesales/calls/{uuid}/dispositionDữ 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

typeKiểu dữ liệu sau khi chuyển đổiRule có thể khaiGhi chú
textstringmax_length, regex_patternFree text 1 dòng
textareastringmax_lengthFree text nhiều dòng
richtextHTML string (đã sanitize)max_lengthHTMLPurifier server-side
numberinteger hoặc decimalmin_value, max_valueLưu dưới dạng decimal(18,4)
dateISO-8601 date (YYYY-MM-DD)
datetimeISO-8601 datetimeServer chuẩn hoá về UTC
booleantrue / falseNhận "0"/"1"/"true"/"false"
emailstringCheck syntactic RFC-5321
phonestringregex_patternAuto chuẩn hoá về 84xxx nếu có thể
urlstringBắt buộc scheme http:// hoặc https://
selectstringoptions[]1 giá trị trong options
multiselectarray of stringoptions[]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).

http
GET /api/custom-fields?entity=TelesalesLead

Query params:

ParamMô tả
entityBắt buộc cho context Telesales — set TelesalesLead hoặc TelesalesCallAttempt.
include_inactivetrue / 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:

json
{
  "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:

  1. Onboarding — gọi 1 lần, cache phía Client, dùng để render UI mapping cột CSV → field khi import.
  2. 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.
  3. 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:

  1. Từ chối Field không tồn tại — key không có định nghĩa active → 422 unknown_field.
  2. Chuyển đổi kiểu dữ liệu"42" → int; "true" → bool; "2026-01-15" → Date.
  3. Áp dụng quy tắc kiểm tramax_length, min_value, max_value, regex_pattern, options membership.
  4. Kiểm tra tính duy nhất — trả 422 duplicate kèm conflicting_record_id.
  5. 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.

Cấp phép theo điều khoản sử dụng của Zorio.