หมวดหมู่ย่อยคอนเทนต์
ภาพรวม
Content Subcategory คือหมวดหมู่ย่อยที่อยู่ใต้ Content Category และ ซ้อนกันได้หลายชั้น
ในลักษณะ tree โดยมีเพดานความลึกกำหนดไว้ที่ค่าคงที่ MAX_SUBCATEGORY_LEVEL
ซึ่งนับ Category เป็นชั้นที่ 1 แล้วซ้อนหมวดย่อยได้อีก 4 ชั้น
เนื่องจากเป็นโครงสร้างต้นไม้ โมดูลนี้จึงมี endpoint มากกว่าหมวดหมู่ธรรมดา ทั้งการดึงข้อมูลเป็น tree เต็มรูปแบบ การดึงเป็น hierarchical dropdown ที่เยื้องตามชั้น การดู path จากรากถึงโหนดสำหรับทำ breadcrumb และการจัดลำดับการแสดงผลใหม่
soft delete ของโมดูลนี้ใช้คอลัมน์ deleted_date แบบธรรมดา ไม่ใช่ gorm.DeletedAt
จึงต้องใส่เงื่อนไข deleted_date IS NULL เอง และการลบเป็นคำสั่ง UPDATE แบบ manual
Business Flow
GET /api/content-subcategoriesลิสต์หมวดย่อยทั้งหมด ตามQueryContentSubcategoryDtoGET /api/content-subcategories/dropdownคืน dropdown แบบแบน- ภายใต้หมวดหมู่หลักหนึ่ง ๆ มี endpoint เฉพาะทางหลายตัว
GET /api/content-subcategories/by-category/:categoryIdลิสต์หมวดย่อยทั้งหมดของหมวดนั้นGET /api/content-subcategories/by-category/:categoryId/dropdowndropdown เฉพาะหมวดนั้นGET /api/content-subcategories/by-category/:categoryId/treeโครงต้นไม้เต็มสำหรับ UI แบบ treeGET /api/content-subcategories/by-category/:categoryId/hierarchical-dropdowndropdown ที่เยื้องตามระดับชั้น
GET /api/content-subcategories/:id/pathคืนเส้นทางจากหมวดรากถึงโหนดปัจจุบัน สำหรับแสดงเป็น breadcrumbPOST /api/content-subcategoriesสร้างหมวดย่อยใหม่ พร้อมตรวจสอบว่าไม่เกินเพดานความลึกGET /api/content-subcategories/:idดูรายละเอียด และPATCH /api/content-subcategories/:idแก้ไขPATCH /api/content-subcategories/reorder/sort-orderรับ body รูปแบบ{items: [{id, sortOrder}]}เพื่อจัดลำดับการแสดงผลใหม่หลายรายการในคำขอเดียวDELETE /api/content-subcategories/:idพร้อมพารามิเตอร์forceใช้ลบหมวดย่อย โดยปกติระบบจะปฏิเสธหากยังมีหมวดย่อยลูกหรือมีคอนเทนต์ผูกอยู่ ส่วนforceใช้บังคับลบ
ไฟล์และฟังก์ชันหลัก
โค้ดหลักอยู่ที่ internal/modules/contentsubcategory/ ประกอบด้วย controller.go, service.go
และ dto.go โดย register บน group authed.Group("/content-subcategories")
| 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 |
ค่าคงที่ควบคุมความลึกคือ maxSubcategoryLevel ซึ่ง port มาจาก MAX_SUBCATEGORY_LEVEL
จุดเชื่อมต่อกับ Service อื่น
- สิทธิ์การเข้าถึง — ต้องผ่าน global
JwtAuthโดย policy metadata เป็นPolicyModuleLineOaซึ่งยังไม่บังคับใช้ และไม่มีModuleGateครอบ - ตารางที่เกี่ยวข้อง —
content_subcategory,content_category,content_page,line_oa - Context — อ่าน
lineOaIdและorganizationIdจาก CLS เพื่อกำหนดขอบเขตข้อมูล - โมดูลที่เกี่ยวข้อง — Content Category, Content Page และ Public API