Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/JFKoryy/autopart-pro/llms.txt

Use this file to discover all available pages before exploring further.

The inventory module is the operational core of AutoPart Pro. It gives administrators complete control over the parts catalog — creating new SKUs, editing prices and descriptions, adjusting stock levels, and removing discontinued parts — while exposing a read-only catalog view to any visitor browsing the storefront. Every write operation is protected by the authorize('admin') middleware so that only accounts with the admin role can mutate inventory data.

Product Fields

Every product record in the products table carries the following fields:
FieldTypeNotes
idINT (PK)Auto-incremented primary key
skuVARCHAR (unique)Auto-uppercased and trimmed by validateProductData middleware
nameVARCHARDisplay name of the part
brandVARCHARManufacturer brand (e.g. Bosch, NGK)
compatible_carsTEXTFree-text vehicle compatibility string (e.g. “Toyota Corolla 2018-2022”)
priceDECIMALMust be ≥ 0; validated by middleware
stockINTCurrent units on hand; must be a non-negative integer
min_stockINTLow-stock threshold, defaults to 5
image_urlVARCHAROptional product photo URL
categoryVARCHAROptional category label (e.g. “Filtros”, “Frenos”)
descriptionTEXTOptional long-form description

SKU Validation

The validateProductData middleware runs before every POST /api/products and PUT /api/products/:id request. It enforces three rules:
  1. sku, name, and brand are required on creation (POST).
  2. price, if provided, must be a non-negative number.
  3. stock, if provided, must be a non-negative integer.
Before the request reaches the controller, the SKU is normalised:
if (sku !== undefined) {
  req.body.sku = sku.toUpperCase().trim();
}
If a product is created or updated with an SKU that already exists in the database, MySQL raises ER_DUP_ENTRY and the controller returns a 400 response:
{
  "success": false,
  "message": "El SKU 'BRK-001' ya está registrado en el inventario."
}

Access Control

Route-level protection is applied in productRoutes.js using the protect (JWT auth) and authorize (role check) middleware:
// Open to everyone — no authentication required
router.get('/', ProductController.getAllProducts);

// Authenticated users only
router.get('/low-stock', protect, ProductController.getLowStockProducts);
router.get('/:id',       protect, ProductController.getProductById);

// Admin only
router.post('/',   protect, authorize('admin'), validateProductData, ProductController.createProduct);
router.put('/:id', protect, authorize('admin'), validateProductData, ProductController.updateProduct);
router.delete('/:id', protect, authorize('admin'),                   ProductController.deleteProduct);
GET /api/products is intentionally unauthenticated so that the public storefront can load the catalog without requiring a login. All mutation endpoints require both a valid JWT and the admin role.

API Operations

MethodEndpointAuth RequiredRoleDescription
GET/api/productsNoList all products ordered by created_at DESC
GET/api/products/:idYesAnyFetch a single product by ID
GET/api/products/low-stockYesAnyList products where stock <= min_stock
POST/api/productsYesadminCreate a new product
PUT/api/products/:idYesadminPartial update — only provided fields are changed
DELETE/api/products/:idYesadminPermanently remove a product

Creating a Product

1

Obtain a JWT token

Log in as an admin account to receive a Bearer token.
curl -s -X POST http://localhost:5000/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"admin@autopart.com","password":"secret123"}' \
  | jq .token
2

POST the new product

Include all required fields (sku, name, brand) plus any optional fields.
curl -X POST http://localhost:5000/api/products \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <TOKEN>" \
  -d '{
    "sku": "brk-001",
    "name": "Pastilla de freno delantera",
    "brand": "Brembo",
    "compatible_cars": "Toyota Corolla 2018-2023, Honda Civic 2019-2022",
    "price": 45.99,
    "stock": 120,
    "min_stock": 10,
    "category": "Frenos",
    "description": "Pastilla cerámica de alto rendimiento.",
    "image_url": "https://cdn.example.com/brk-001.jpg"
  }'
The SKU is auto-uppercased to BRK-001 by the middleware. On success the server responds:
{
  "success": true,
  "message": "Autoparte registrada con éxito",
  "productId": 42
}

Updating a Product (Stock Adjustment)

Only the fields included in the request body are changed. Partial updates are fully supported — you can update stock alone without touching the price or description:
curl -X PUT http://localhost:5000/api/products/42 \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <TOKEN>" \
  -d '{"stock": 8}'
A successful update returns:
{
  "success": true,
  "message": "Autoparte actualizada con éxito."
}
After every PUT, the controller re-fetches the product and checks stock <= min_stock. If the threshold is breached, a low-stock event is emitted via stockEmitter. See Stock Alerts for details.

Frontend Views

The frontend renders different inventory experiences depending on the authenticated user’s role:

Inventory Page (Admin / Employee)

Located at /admin/inventario, the Inventory.jsx page renders a searchable product table with SKU, name, compatibility, price, and a stock badge. Admins see Edit and Delete action buttons. Employees can click the stock badge to open a quick-edit modal but cannot create or delete products.

Catalog Page (Client)

Located at /catalogo, the Catalog.jsx page renders the same product data as a filterable card grid. Clients can filter by brand, vehicle compatibility, category, and sort by price or stock level. An Add to Cart button on each card triggers CartContext.addItem().

Stock Alerts

Learn how the low-stock EventEmitter fires when stock drops to or below min_stock.

User Roles

Understand how authorize('admin') protects every write endpoint.

Build docs developers (and LLMs) love