5.9 KiB
5.9 KiB
Bulk Catalog Delete Endpoint Documentation
Overview
Generic bulk delete endpoint for catalog entities (makes, models, years, trims, engines) in the admin panel.
Endpoint
DELETE /api/admin/catalog/{entity}/bulk-delete
Path Parameters
entity: Entity type - one of:makes,models,years,trims,engines
Request Body
{
"ids": [1, 2, 3, 4, 5]
}
Validation Rules
- IDs must be an array of positive integers
- At least 1 ID required
- Maximum 100 IDs per batch
- All IDs must be valid integers (not strings or floats)
Response Codes
204 No Content: All deletions succeeded (no response body)207 Multi-Status: Some deletions failed (includes response body with details)400 Bad Request: Invalid entity type or invalid request body401 Unauthorized: Missing or invalid authentication500 Internal Server Error: Unexpected server error
Response Body (207 Multi-Status only)
{
"deleted": [1, 3, 5],
"failed": [
{
"id": 2,
"error": "Make 2 not found"
},
{
"id": 4,
"error": "Cannot delete make with existing models"
}
]
}
Cascade Behavior
The endpoint uses existing single-delete methods which have the following behavior:
Makes
- Blocks deletion if models exist under the make
- Error: "Cannot delete make with existing models"
- Solution: Delete all dependent models first
Models
- Blocks deletion if years exist under the model
- Error: "Cannot delete model with existing years"
- Solution: Delete all dependent years first
Years
- Blocks deletion if trims exist under the year
- Error: "Cannot delete year with existing trims"
- Solution: Delete all dependent trims first
Trims
- Blocks deletion if engines exist under the trim
- Error: "Cannot delete trim with existing engines"
- Solution: Delete all dependent engines first
Engines
- No cascade restrictions (leaf entity in hierarchy)
Deletion Order for Hierarchy
To delete an entire make and all its dependencies:
- Delete engines first
- Delete trims
- Delete years
- Delete models
- Delete make last
Examples
Example 1: Delete Multiple Engines (Success)
DELETE /api/admin/catalog/engines/bulk-delete
{
"ids": [101, 102, 103]
}
Response: 204 No Content
Example 2: Delete Multiple Makes (Partial Failure)
DELETE /api/admin/catalog/makes/bulk-delete
{
"ids": [1, 2, 3]
}
Response: 207 Multi-Status
{
"deleted": [3],
"failed": [
{
"id": 1,
"error": "Cannot delete make with existing models"
},
{
"id": 2,
"error": "Make 2 not found"
}
]
}
Example 3: Invalid Entity Type
DELETE /api/admin/catalog/invalid/bulk-delete
{
"ids": [1, 2, 3]
}
Response: 400 Bad Request
{
"error": "Invalid entity type",
"message": "Entity must be one of: makes, models, years, trims, engines"
}
Example 4: Invalid IDs
DELETE /api/admin/catalog/makes/bulk-delete
{
"ids": ["abc", "def"]
}
Response: 400 Bad Request
{
"error": "Invalid IDs",
"message": "All IDs must be positive integers"
}
Implementation Details
Files Modified
-
/backend/src/features/admin/api/admin.routes.ts(line 209-212)- Added route:
DELETE /admin/catalog/:entity/bulk-delete - Requires admin authentication
- Added route:
-
/backend/src/features/admin/api/catalog.controller.ts(line 542-638)- Added method:
bulkDeleteCatalogEntity() - Maps entity type to appropriate delete method
- Processes deletions sequentially
- Collects successes and failures
- Added method:
-
/backend/src/features/admin/api/admin.validation.ts(line 43-49, 57-58)- Added
catalogEntitySchema: Validates entity type - Added
bulkDeleteCatalogSchema: Validates request body - Exported types:
CatalogEntity,BulkDeleteCatalogInput
- Added
-
/backend/src/features/admin/domain/admin.types.ts(line 97-103)- Added
BulkDeleteCatalogResponseinterface
- Added
Continue-on-Failure Pattern
The endpoint uses a continue-on-failure pattern:
- One deletion failure does NOT stop the batch
- All deletions are attempted
- Successes and failures are tracked separately
- Final response includes both lists
Transaction Behavior
- Each individual deletion runs in its own transaction (via service layer)
- If one delete fails, it doesn't affect others
- No rollback of previously successful deletions
Testing
Manual Testing with cURL
# Test valid request (requires auth token)
curl -X DELETE "http://localhost/api/admin/catalog/makes/bulk-delete" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{"ids": [1, 2, 3]}'
# Test invalid entity type
curl -X DELETE "http://localhost/api/admin/catalog/invalid/bulk-delete" \
-H "Content-Type: application/json" \
-d '{"ids": [1, 2, 3]}'
# Test empty IDs
curl -X DELETE "http://localhost/api/admin/catalog/makes/bulk-delete" \
-H "Content-Type: application/json" \
-d '{"ids": []}'
Expected Audit Log Behavior
Each successful deletion creates a platform change log entry:
changeType: "DELETE"resourceType: Entity type (makes, models, years, trims, engines)resourceId: ID of deleted entitychangedBy: Actor's user IDoldValue: Entity data before deletionnewValue: null
Security
- Endpoint requires admin authentication (via
fastify.requireAdmin) - Actor ID is logged for all operations
- All deletions are audited in platform_change_log table
Performance Considerations
- Deletions are processed sequentially (not in parallel)
- Each deletion queries the database separately
- Cache invalidation occurs after each successful deletion
- For large batches (50+ items), consider breaking into smaller batches
Future Enhancements
Potential improvements:
- Add cascade delete option to automatically delete dependent entities
- Add dry-run mode to preview what would be deleted
- Add batch size optimization for better performance
- Add progress tracking for long-running batches