Skip to content

Domain Model

Cả hai entity được định nghĩa trong @nx/core dưới schema PostgreSQL outreach và được re-export vào package này. Không có khoá ngoại giữa chúng - mỗi entity là một bảng thu thập độc lập.

1. ERD đầy đủ

2. Entities

Inquiry

Thuộc tínhGiá trị
Bảngoutreach.Inquiry
Nguồnpackages/core/src/models/schemas/outreach/inquiry/schema.ts
Soft-deletecó (deletedAt)
Cột Owner ID- (toàn cục, không phân tách theo merchant)
Thuộc tính ẩndeletedAt

Trường:

TrườngKiểuBắt buộcMặc địnhMô tả
idtextSnowflakeKhóa chính
typetext000_CONSULTKênh nguồn - xem enum
statustextNEWTrạng thái trong pipeline - xem enum
firstNametext-Tên liên hệ
lastNametext-Họ liên hệ
emailtext-Email liên hệ (có index)
phonetext-SĐT liên hệ
businessNametext-Doanh nghiệp của lead
businessTypetext-Danh mục doanh nghiệp
locationCounttext-Đánh giá lead
estimatedRevenuetext-Đánh giá lead
subjecttext-Chủ đề tin nhắn
messagetext-Nội dung dạng văn bản tự do
assignedTotext-id của admin/user sở hữu
repliedAttimestamptz-Thời điểm trả lời đầu tiên
repliedBytext-id của user trả lời
convertedAttimestamptz-Thời điểm chuyển đổi
lostReasontext-Lý do mất deal
notetext-Ghi chú nội bộ
createdAttimestamptznow()-

Enum type (InquiryTypes):

Giá trịMô tả
000_CONSULTTư vấn chung / nguồn không rõ (mặc định)
100_CONTACTForm liên hệ (/contact)
200_SALESYêu cầu bán hàng (/contact-sales)
300_DEMOYêu cầu demo (/demo)
400_PARTNERĐăng ký đối tác (/partners)

Enum status (InquiryStatuses, IGNIS Statuses):

Giá trịMô tả
NEWVừa gửi
PROCESSINGAdmin đã tiếp nhận
COMPLETEDĐã chuyển đổi
CLOSEDĐã xử lý nhưng không chuyển đổi
CANCELLEDSpam / không hợp lệ / bị bỏ dở

Index & constraint:

TênCộtLoại
PK_InquiryidKhóa chính
IDX_Inquiry_typetypeBtree
IDX_Inquiry_statusstatusBtree
IDX_Inquiry_emailemailBtree

Quan hệ: không có.

Subscriber

Thuộc tínhGiá trị
Bảngoutreach.Subscriber
Nguồnpackages/core/src/models/schemas/outreach/subscriber/schema.ts
Soft-deletecó (deletedAt)
Cột Owner ID- (toàn cục)
Thuộc tính ẩndeletedAt, unsubscribeToken (không bao giờ được model API trả về)

Trường:

TrườngKiểuBắt buộcMặc địnhMô tả
idtextSnowflakeKhóa chính
emailtext-Duy nhất (partial, với dòng chưa xoá)
localetextviNgôn ngữ newsletter (vi / en)
topicsjsonb (string[])['all']Tuỳ chọn chủ đề
statustextACTIVATEDXem enum
unsubscribeTokentextSnowflake ($defaultFn)Token cho link huỷ đăng ký; ẩn khỏi API
subscribedAttimestamptznow()Thời điểm đăng ký đầu tiên/gần nhất
unsubscribedAttimestamptz-Được set khi huỷ đăng ký, xoá khi đăng ký lại
createdAttimestamptznow()-

Enum status (SubscriberStatuses, IGNIS Statuses):

Giá trịMô tả
ACTIVATEDĐăng ký đang hoạt động
DEACTIVATEDĐã huỷ đăng ký
ARCHIVEDĐã được admin lưu trữ (trạng thái hợp lệ, không do luồng service tạo ra)

Index & constraint:

TênCộtLoại
PK_SubscriberidKhóa chính
UPI_Subscriber_emailemail (where deletedAt IS NULL)Unique partial index
IDX_Subscriber_statusstatusBtree
IDX_Subscriber_unsubscribeTokenunsubscribeTokenBtree

Quan hệ: không có.

3. Bất biến giữa các entity

Bất biếnCách thực thi
Mỗi email chỉ có một Subscriber còn hiệu lựcUnique partial index UPI_Subscriber_email (where deletedAt IS NULL) + SubscriberService.subscribe() tìm-rồi-kích-hoạt-lại
unsubscribeToken đủ độc nhất để không đoán đượcSnowflake $defaultFn (64-bit, worker 10) - xem ADR-0001
Đăng ký lại sẽ xoá unsubscribedAtSubscriberService.subscribe() đặt unsubscribedAt: null khi kích hoạt lại

4. Hành vi Soft-delete

Hành viChi tiết
Đọc mặc địnhdeletedAt IS NULL (model defaultFilter)
Hard-deleteKhông bao giờ theo mặc định; CRUD của admin deleteById thực hiện soft-delete
Khôi phụcKhông mở ra qua API
Tính duy nhất của emailChỉ áp dụng trên các dòng chưa xoá (partial unique index)

5. Trang liên quan

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.