3.6 KiB
Products Controller Documentation
File: controllers/admin/products.controller.js
Base URL: /api/admin/products
Guards: authenticate → requireAdmin() → adminLimiter
Table of Contents
- Get Course Product
- Upsert Course Product
- Remove Course Product
- Get Course Categories
- Sync Course Categories
Notes
- Each course has at most one product listing (
productstable, unique oncourse_id). - Upsert restores a soft-deleted product if one exists rather than creating a duplicate.
- Categories are managed via the
course_product_categoriesjunction table (many-to-many betweencoursesandcategories). - Syncing categories replaces the full set — it is a replace-all, not an append.
Get Course Product
GET /api/admin/products/courses/:courseId/product
Returns the product listing for a course, or null if none exists. Includes archived products (paranoid: false).
Response 200
{
"status": "success",
"message": "Product retrieved.",
"data": {
"id": 1,
"course_id": 5,
"name": "Advanced JavaScript",
"description": "Full course access",
"price": "49.99",
"currency": "USD",
"access_days": 365,
"is_active": true,
"createdAt": "2026-01-01T00:00:00.000Z",
"updatedAt": "2026-01-01T00:00:00.000Z",
"deletedAt": null
}
}
Upsert Course Product
PUT /api/admin/products/courses/:courseId/product
Creates the product if it does not exist. If a soft-deleted product exists, it is restored and updated. If an active product exists, it is updated.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Product name |
price |
number | Yes | Price (decimal, e.g. 49.99) |
description |
string | No | |
currency |
string | No | ISO 4217 code. Default: USD |
access_days |
number | No | Days of access after purchase. null = lifetime |
is_active |
boolean | No | Default: true |
Response 200 (updated) / 201 (created)
{
"status": "success",
"message": "Product updated.",
"data": { ... }
}
Error Responses
| Status | Message |
|---|---|
400 |
name and price are required. |
Remove Course Product
DELETE /api/admin/products/courses/:courseId/product
Soft-deletes the course product.
Response 200
{ "status": "success", "message": "Product removed." }
Error Responses
| Status | Message |
|---|---|
404 |
Product not found. |
Get Course Categories
GET /api/admin/products/courses/:courseId/categories
Returns the list of categories assigned to a course.
Response 200
{
"status": "success",
"message": "Course categories retrieved.",
"data": [
{ "id": 1, "name": "Business", "slug": "business", "is_active": true },
{ "id": 3, "name": "Design", "slug": "design", "is_active": true }
]
}
Error Responses
| Status | Message |
|---|---|
404 |
Course not found. |
Sync Course Categories
POST /api/admin/products/courses/:courseId/categories
Replaces the full set of category assignments for a course. All existing assignments are removed first, then the new set is inserted.
Request Body
{ "category_ids": [1, 3, 7] }
Pass an empty array to clear all category assignments.
Response 200
{ "status": "success", "message": "Course categories updated." }