- Add OpenSpec experimental workflow with commands (opsx-apply, opsx-archive, opsx-explore, opsx-propose) - Add Serena memory system for project context - Implement User API (UserController, UserModel, routes) - Add Specimen delete endpoint - Update Test definitions and Routes - Sync API documentation (OpenAPI) - Archive completed 2026-03-08-backend-specs change
120 lines
2.7 KiB
Markdown
120 lines
2.7 KiB
Markdown
# Specimen Delete Endpoint
|
|
|
|
## Overview
|
|
Add DELETE endpoint for specimens to complete CRUD operations.
|
|
|
|
## Current State
|
|
- GET /api/specimen - List specimens ✅
|
|
- GET /api/specimen/(:num) - Get single specimen ✅
|
|
- POST /api/specimen - Create specimen ✅
|
|
- PATCH /api/specimen - Update specimen ✅
|
|
- DELETE /api/specimen/(:num) - **MISSING** ❌
|
|
|
|
## Requirements
|
|
|
|
### Route
|
|
|
|
Add to `app/Config/Routes.php` in the specimen group:
|
|
|
|
```php
|
|
$routes->group('specimen', function ($routes) {
|
|
// ... existing routes ...
|
|
$routes->delete('(:num)', 'Specimen\SpecimenController::delete/$1');
|
|
});
|
|
```
|
|
|
|
### Controller Method
|
|
|
|
Add to `app/Controllers/Specimen/SpecimenController.php`:
|
|
|
|
```php
|
|
/**
|
|
* Delete a specimen (soft delete)
|
|
* DELETE /api/specimen/(:num)
|
|
*/
|
|
public function delete($id) {
|
|
try {
|
|
// Check if specimen exists
|
|
$specimen = $this->model->where('SID', $id)->first();
|
|
|
|
if (empty($specimen)) {
|
|
return $this->respond([
|
|
'status' => 'failed',
|
|
'message' => 'Specimen not found',
|
|
'data' => null
|
|
], 404);
|
|
}
|
|
|
|
// Perform soft delete (set DelDate)
|
|
$deleted = $this->model->update($id, [
|
|
'DelDate' => date('Y-m-d H:i:s')
|
|
]);
|
|
|
|
if (!$deleted) {
|
|
return $this->respond([
|
|
'status' => 'failed',
|
|
'message' => 'Failed to delete specimen',
|
|
'data' => null
|
|
], 500);
|
|
}
|
|
|
|
return $this->respond([
|
|
'status' => 'success',
|
|
'message' => 'Specimen deleted successfully',
|
|
'data' => ['SID' => $id]
|
|
], 200);
|
|
|
|
} catch (\Exception $e) {
|
|
log_message('error', 'SpecimenController::delete error: ' . $e->getMessage());
|
|
return $this->respond([
|
|
'status' => 'failed',
|
|
'message' => 'Failed to delete specimen',
|
|
'data' => null
|
|
], 500);
|
|
}
|
|
}
|
|
```
|
|
|
|
## Expected Request/Response
|
|
|
|
### Request
|
|
```http
|
|
DELETE /api/specimen/123 HTTP/1.1
|
|
```
|
|
|
|
### Success Response (200)
|
|
```json
|
|
{
|
|
"status": "success",
|
|
"message": "Specimen deleted successfully",
|
|
"data": {
|
|
"SID": 123
|
|
}
|
|
}
|
|
```
|
|
|
|
### Not Found Response (404)
|
|
```json
|
|
{
|
|
"status": "failed",
|
|
"message": "Specimen not found",
|
|
"data": null
|
|
}
|
|
```
|
|
|
|
### Error Response (500)
|
|
```json
|
|
{
|
|
"status": "failed",
|
|
"message": "Failed to delete specimen",
|
|
"data": null
|
|
}
|
|
```
|
|
|
|
## Implementation Notes
|
|
|
|
1. **Use soft delete**: Set `DelDate` field instead of hard delete
|
|
2. **Check existence first**: Return 404 if specimen doesn't exist
|
|
3. **Use SID as identifier**: The specimen ID field is `SID`, not `id`
|
|
4. **Follow existing patterns**: Match style of other delete methods in codebase
|