Skip to main content

Content Categories & Link Collections

Overview

This domain has 3 tables: content_category stores top-level content categories per LINE OA, content_subcategory stores subcategories with multi-level nesting through parent_id/level, and content_link stores content link collections (a single link that resolves to a set of content filtered by category and publication date range) together with a click counter

Table content_category

ColumnTypeNullableDefaultDescription
idSERIALNOnextval(...)Primary key
uuidUUIDNOgen_random_uuid()External reference id for the category (unique)
line_oa_idINTEGERNO-LINE OA the category belongs to (FK to line_oa.id)
organization_idINTEGERNO-Organization that owns the category
nameVARCHAR(255)NO-Category name
slugVARCHAR(255)NO-Category slug used in the URL
descriptionTEXTYES-Category description
thumbnailVARCHAR(500)YES-Category thumbnail image URL
sort_orderINTEGERNO0Display order
statusContentCategoryStatus (ENUM)NOactiveStatus: active, inactive, delete
created_dateTIMESTAMPTZ(3)NOnow()Creation timestamp
created_byINTEGERNO0Creator (user id)
updated_dateTIMESTAMPTZ(3)NOnow()Last update timestamp
updated_byINTEGERNO0Last updater (user id)
deleted_dateTIMESTAMPTZ(3)YES-Deletion timestamp (soft delete)

Table content_subcategory

ColumnTypeNullableDefaultDescription
idSERIALNOnextval(...)Primary key
uuidUUIDNOgen_random_uuid()External reference id for the subcategory (unique)
category_idINTEGERNO-Parent category (FK to content_category.id)
line_oa_idINTEGERNO-LINE OA the subcategory belongs to
organization_idINTEGERNO-Organization that owns the subcategory
nameVARCHAR(255)NO-Subcategory name
slugVARCHAR(255)NO-Subcategory slug used in the URL
descriptionTEXTYES-Subcategory description
thumbnailVARCHAR(500)YES-Subcategory thumbnail image URL
sort_orderINTEGERNO0Display order
statusContentCategoryStatus (ENUM)NOactiveStatus: active, inactive, delete
parent_idINTEGERYES-Higher-level subcategory (enables multi-level nesting)
content_subcategory_idINTEGERYES-Reference to a related subcategory (self-reference)
levelINTEGERNO2Nesting level of the subcategory (level 1 is the category)
created_dateTIMESTAMPTZ(3)NOnow()Creation timestamp
created_byINTEGERNO0Creator (user id)
updated_dateTIMESTAMPTZ(3)NOnow()Last update timestamp
updated_byINTEGERNO0Last updater (user id)
deleted_dateTIMESTAMPTZ(3)YES-Deletion timestamp (soft delete)
ColumnTypeNullableDefaultDescription
idSERIALNOnextval(...)Primary key
uuidUUIDNOgen_random_uuid()External reference id for the link (unique)
tokenVARCHAR(64)NO-Token used in the public link (unique)
line_oa_idINTEGERNO-LINE OA the link belongs to (FK to line_oa.id)
organization_idINTEGERNO-Organization that owns the link
nameVARCHAR(255)NO-Link collection name
descriptionTEXTYES-Link collection description
category_idINTEGERYES-Filter content by category (FK to content_category.id)
subcategory_idINTEGERYES-Filter content by subcategory (FK to content_subcategory.id)
published_date_fromTIMESTAMPTZ(3)YES-Include content published on or after this timestamp
published_date_toTIMESTAMPTZ(3)YES-Include content published up to this timestamp
audience_idsJSONBYES'[]'Audiences allowed to access this link
statusVARCHAR(20)NO'active'Link status
click_countBIGINTNO0Cumulative click count for the link
created_dateTIMESTAMPTZ(3)NOnow()Creation timestamp
created_byINTEGERNO-Creator (user id)
updated_dateTIMESTAMPTZ(3)NOnow()Last update timestamp
updated_byINTEGERNO-Last updater (user id)
deleted_dateTIMESTAMPTZ(3)YES-Deletion timestamp (soft delete)
deleted_byINTEGERYES-User who deleted the link (user id)

Notes

  • content_category has a unique constraint on (line_oa_id, slug) — slugs must be unique within one OA
  • content_subcategory has a unique constraint on (category_id, slug) — subcategory slugs must be unique within the same parent category
  • content_subcategory.category_id is a FK to content_category.id with ON DELETE CASCADE — deleting a parent category deletes all of its subcategories
  • content_subcategory supports multi-level nesting through parent_id and level (default 2 meaning the second level below the category), and both columns are indexed
  • content_link.token has a unique constraint plus a separate index, because it is the key used to open the link from outside
  • content_link stores only the filter criteria, not an explicit content list — the displayed content is resolved from category_id, subcategory_id and the published_date_from/published_date_to range
  • All three tables use soft delete via deleted_date, which is indexed
  • content_category and content_subcategory are referenced by content_page and content_link (see Content Pages)