Content Subcategory
Overview
Content Subcategory sits beneath Content Category and can nest several levels deep as a
tree. Depth is capped by the MAX_SUBCATEGORY_LEVEL constant, which counts the category itself
as level one and permits four further levels of subcategories.
Because it models a tree, this module exposes considerably more endpoints than a flat category would: retrieving the full tree, retrieving an indented hierarchical dropdown, resolving the path from root to node for breadcrumbs, and reordering how items are displayed.
Soft deletes use a plain deleted_date column rather than gorm.DeletedAt, so every read must
add deleted_date IS NULL itself and the delete is issued as a manual UPDATE.
Business Flow
GET /api/content-subcategorieslists every subcategory perQueryContentSubcategoryDto.GET /api/content-subcategories/dropdownreturns a flat dropdown.- Several endpoints operate within a single parent category.
GET /api/content-subcategories/by-category/:categoryIdlists that category's children.GET /api/content-subcategories/by-category/:categoryId/dropdownreturns a dropdown scoped to that category.GET /api/content-subcategories/by-category/:categoryId/treereturns the full tree for tree-style UIs.GET /api/content-subcategories/by-category/:categoryId/hierarchical-dropdownreturns a dropdown indented by depth.
GET /api/content-subcategories/:id/pathreturns the path from the root category to the current node, for rendering breadcrumbs.POST /api/content-subcategoriescreates a subcategory, verifying the depth cap is not exceeded.GET /api/content-subcategories/:idreturns details andPATCH /api/content-subcategories/:idupdates them.PATCH /api/content-subcategories/reorder/sort-orderaccepts a{items: [{id, sortOrder}]}body to reorder many entries in a single request.DELETE /api/content-subcategories/:idwith an optionalforceparameter deletes a subcategory. The request is normally rejected if child subcategories or linked content still exist;forceoverrides that check.
Key Files & Functions
Core code lives in internal/modules/contentsubcategory/, comprising controller.go,
service.go, and dto.go, registered on the authed.Group("/content-subcategories") group.
| Method | Route | Handler | Policy (metadata) |
|---|---|---|---|
| GET | /api/content-subcategories | ct.findAll | readAll line-oa |
| GET | /api/content-subcategories/dropdown | ct.getDropdown | readAll line-oa |
| GET | /api/content-subcategories/by-category/:categoryId | ct.findByCategoryID | readAll line-oa |
| GET | /api/content-subcategories/by-category/:categoryId/dropdown | ct.getDropdownByCategoryID | readAll line-oa |
| GET | /api/content-subcategories/by-category/:categoryId/tree | ct.getTreeByCategoryID | readAll line-oa |
| GET | /api/content-subcategories/by-category/:categoryId/hierarchical-dropdown | ct.getHierarchicalDropdownByCategoryID | readAll line-oa |
| GET | /api/content-subcategories/:id/path | ct.getPath | read line-oa |
| GET | /api/content-subcategories/:id | ct.findOne | read line-oa |
| POST | /api/content-subcategories | ct.create | create line-oa |
| PATCH | /api/content-subcategories/reorder/sort-order | ct.updateSortOrder | update line-oa |
| PATCH | /api/content-subcategories/:id | ct.update | update line-oa |
| DELETE | /api/content-subcategories/:id | ct.remove | delete line-oa |
The depth limit is held in the maxSubcategoryLevel constant, ported from
MAX_SUBCATEGORY_LEVEL.
Connections to Other Services
- Access control — requests must pass global
JwtAuth. The policy metadata isPolicyModuleLineOaand is not yet enforced; there is noModuleGate. - Tables —
content_subcategory,content_category,content_page,line_oa - Context — reads
lineOaIdandorganizationIdfrom CLS to scope queries. - Related modules — Content Category, Content Page, and Public API.