Files
motovaultpro/BULK-DELETE-ENDPOINT-DOCS.md
2025-11-06 16:29:11 -06:00

228 lines
5.9 KiB
Markdown

# 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
```json
{
"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 body
- `401 Unauthorized`: Missing or invalid authentication
- `500 Internal Server Error`: Unexpected server error
## Response Body (207 Multi-Status only)
```json
{
"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:
1. Delete engines first
2. Delete trims
3. Delete years
4. Delete models
5. Delete make last
## Examples
### Example 1: Delete Multiple Engines (Success)
```bash
DELETE /api/admin/catalog/engines/bulk-delete
{
"ids": [101, 102, 103]
}
Response: 204 No Content
```
### Example 2: Delete Multiple Makes (Partial Failure)
```bash
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
```bash
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
```bash
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
1. `/backend/src/features/admin/api/admin.routes.ts` (line 209-212)
- Added route: `DELETE /admin/catalog/:entity/bulk-delete`
- Requires admin authentication
2. `/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
3. `/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`
4. `/backend/src/features/admin/domain/admin.types.ts` (line 97-103)
- Added `BulkDeleteCatalogResponse` interface
### 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
```bash
# 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 entity
- `changedBy`: Actor's user ID
- `oldValue`: Entity data before deletion
- `newValue`: 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:
1. Add cascade delete option to automatically delete dependent entities
2. Add dry-run mode to preview what would be deleted
3. Add batch size optimization for better performance
4. Add progress tracking for long-running batches