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

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 body
  • 401 Unauthorized: Missing or invalid authentication
  • 500 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:

  1. Delete engines first
  2. Delete trims
  3. Delete years
  4. Delete models
  5. 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

  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

# 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