<aside> <img src="/icons/checklist_green.svg" alt="/icons/checklist_green.svg" width="40px" />
</aside>
Table product_related {
product_id uuid [not null, ref: > products.id]
related_id uuid [not null, ref: > products.id]
order int [not null, default: 0]
notes text
deleted_at timestamp null
}
product_related và productsproduct_related.product_id phải tham chiếu đến một products.id tồn tại và deleted_at IS NULL.product_related.related_id phải tham chiếu đến một products.id tồn tại và deleted_at IS NULL.product_id = related_id (không tự liên kết bản thân).(product_id, related_id) phải là duy nhất trong bảng (không trùng lặp).order)order là số nguyên ≥ 0, dùng để xác định vị trí của Related Course khi hiển thị.product_id, giá trị order nên là duy nhất để tránh xung đột thứ tự; nếu trùng, service phải reindex hoặc trả lỗi.notes)notes là trường tùy chọn, dùng để lưu thông tin bổ sung về mối quan hệ (ví dụ: “được mua cùng”, “cùng chuyên đề”, v.v.).products.deleted_at ≠ NULL), tất cả các bản ghi product_related mà product_id = <id> hoặc related_id = <id> phải được soft-delete (hoặc service chỉ load các record có cả hai bên deleted_at IS NULL).product_id, chỉ lấy các record có deleted_at IS NULL ở cả product_related lẫn sản phẩm liên quan.