delete openspec

This commit is contained in:
mahdahar 2026-03-09 11:18:48 +07:00
parent ad8b79c0c8
commit 09bfe6fb3e
18 changed files with 0 additions and 1491 deletions

View File

@ -1,2 +0,0 @@
schema: spec-driven
created: 2026-03-08

View File

@ -1,74 +0,0 @@
# Backend Implementation - Quick Reference
## Files to Create
1. **app/Controllers/User/UserController.php**
- Copy from: `code-templates/UserController.php`
- Creates: Full CRUD for users
2. **app/Models/User/UserModel.php**
- Copy from: `code-templates/UserModel.php`
- Creates: User database model
## Files to Modify
3. **app/Controllers/Specimen/SpecimenController.php**
- Add method from: `code-templates/SpecimenController-delete-method.php`
- Adds: Delete specimen functionality
4. **app/Config/Routes.php**
- Add routes from: `code-templates/Routes-additions.php`
- Adds: User routes + Specimen delete route
## Database Migration
Run this SQL if `users` table doesn't exist:
```sql
CREATE TABLE IF NOT EXISTS users (
UserID INT AUTO_INCREMENT PRIMARY KEY,
Username VARCHAR(50) NOT NULL UNIQUE,
Email VARCHAR(100) NOT NULL,
Name VARCHAR(100),
Role VARCHAR(50),
Department VARCHAR(100),
IsActive BOOLEAN DEFAULT TRUE,
CreatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UpdatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
DelDate TIMESTAMP NULL,
INDEX idx_username (Username),
INDEX idx_email (Email)
);
```
## Testing Commands
```bash
# Specimen Delete
curl -X DELETE http://localhost:8000/api/specimen/1
# Users API
curl http://localhost:8000/api/users
curl http://localhost:8000/api/users/1
curl -X POST http://localhost:8000/api/users \
-H "Content-Type: application/json" \
-d '{"Username":"test","Email":"test@test.com","Name":"Test User"}'
curl -X PATCH http://localhost:8000/api/users \
-H "Content-Type: application/json" \
-d '{"UserID":1,"Name":"Updated"}'
curl -X DELETE http://localhost:8000/api/users/1
```
## Timeline Estimate
- **Specimen Delete**: 15 minutes (just add route + method)
- **User API**: 1-2 hours (new controller + model + routes)
- **Testing**: 30 minutes
**Total: ~2-3 hours**
## Questions?
See the detailed specs:
- `specimen-delete.md` - Full specimen delete specification
- `user-api.md` - Complete user API specification with examples

View File

@ -1,55 +0,0 @@
# Backend API Requirements
This folder contains specifications for backend changes needed to support the frontend features.
## Quick Summary
| Feature | Status | Priority | Files to Create/Modify |
|---------|--------|----------|----------------------|
| Specimen Delete | Missing | High | Routes.php, SpecimenController.php |
| User CRUD | Not Implemented | High | UserController.php, UserModel.php, Routes.php |
## Directory Structure to Create
```
app/
├── Config/
│ └── Routes.php # MODIFY - Add new routes
├── Controllers/
│ └── Specimen/
│ └── SpecimenController.php # MODIFY - Add delete method
│ └── User/ # CREATE
│ └── UserController.php # CREATE - Full CRUD
├── Models/
│ └── User/ # CREATE
│ └── UserModel.php # CREATE - User database model
```
## Files
1. **specimen-delete.md** - Specimen delete endpoint specification
2. **user-api.md** - Complete User CRUD API specification
3. **code-templates/** - Ready-to-use code templates
- UserController.php
- UserModel.php
- Routes-additions.php
## Testing Checklist
After implementation, verify these endpoints work:
```bash
# Specimen Delete
curl -X DELETE http://localhost:8000/api/specimen/123
# User CRUD
curl http://localhost:8000/api/users
curl http://localhost:8000/api/users/1
curl -X POST http://localhost:8000/api/users -H "Content-Type: application/json" -d '{"username":"test","email":"test@test.com"}'
curl -X PATCH http://localhost:8000/api/users -H "Content-Type: application/json" -d '{"UserID":1,"username":"updated"}'
curl -X DELETE http://localhost:8000/api/users/1
```
## Questions?
Contact the frontend team if you need clarification on data structures or expected responses.

View File

@ -1,42 +0,0 @@
// ============================================================================
// ADD THESE ROUTES TO: app/Config/Routes.php
// ============================================================================
// Add this inside the '$routes->group('api', function ($routes) {' section
// Preferably after the Organization routes and before the Specimen routes
// Users Management
$routes->group('users', function ($routes) {
$routes->get('/', 'User\UserController::index');
$routes->get('(:num)', 'User\UserController::show/$1');
$routes->post('/', 'User\UserController::create');
$routes->patch('/', 'User\UserController::update');
$routes->delete('(:num)', 'User\UserController::delete/$1');
});
// ============================================================================
// SPECIMEN DELETE ROUTE
// Add this INSIDE the existing specimen group (around line 256-296)
// ============================================================================
$routes->group('specimen', function ($routes) {
// ... existing routes ...
// ADD THIS LINE:
$routes->delete('(:num)', 'Specimen\SpecimenController::delete/$1');
// ... rest of existing routes ...
});
// ============================================================================
// COMPLETE EXAMPLE - Users route placement in context
// ============================================================================
// Master Data section (after Equipment, before Specimen)
$routes->group('users', function ($routes) {
$routes->get('/', 'User\UserController::index');
$routes->get('(:num)', 'User\UserController::show/$1');
$routes->post('/', 'User\UserController::create');
$routes->patch('/', 'User\UserController::update');
$routes->delete('(:num)', 'User\UserController::delete/$1');
});

View File

@ -1,49 +0,0 @@
// ============================================================================
// ADD THIS METHOD TO: app/Controllers/Specimen/SpecimenController.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);
}
}

View File

@ -1,290 +0,0 @@
<?php
namespace App\Controllers\User;
use App\Controllers\BaseController;
use App\Models\User\UserModel;
/**
* User Management Controller
* Handles CRUD operations for users
*/
class UserController extends BaseController
{
protected $model;
protected $db;
public function __construct()
{
$this->db = \Config\Database::connect();
$this->model = new UserModel();
}
/**
* List users with pagination and search
* GET /api/users?page=1&per_page=20&search=term
*/
public function index()
{
try {
$page = (int)($this->request->getGet('page') ?? 1);
$perPage = (int)($this->request->getGet('per_page') ?? 20);
$search = $this->request->getGet('search');
// Build query
$builder = $this->model->where('DelDate', null);
// Apply search if provided
if ($search) {
$builder->groupStart()
->like('Username', $search)
->orLike('Email', $search)
->orLike('Name', $search)
->groupEnd();
}
// Get total count for pagination
$total = $builder->countAllResults(false);
// Get paginated results
$users = $builder
->orderBy('UserID', 'DESC')
->limit($perPage, ($page - 1) * $perPage)
->findAll();
return $this->respond([
'status' => 'success',
'message' => 'Users retrieved successfully',
'data' => [
'users' => $users,
'pagination' => [
'current_page' => $page,
'per_page' => $perPage,
'total' => $total,
'total_pages' => ceil($total / $perPage)
]
]
], 200);
} catch (\Exception $e) {
log_message('error', 'UserController::index error: ' . $e->getMessage());
return $this->respond([
'status' => 'failed',
'message' => 'Failed to retrieve users',
'data' => null
], 500);
}
}
/**
* Get single user by ID
* GET /api/users/(:num)
*/
public function show($id)
{
try {
$user = $this->model->where('UserID', $id)
->where('DelDate', null)
->first();
if (empty($user)) {
return $this->respond([
'status' => 'failed',
'message' => 'User not found',
'data' => null
], 404);
}
return $this->respond([
'status' => 'success',
'message' => 'User retrieved successfully',
'data' => $user
], 200);
} catch (\Exception $e) {
log_message('error', 'UserController::show error: ' . $e->getMessage());
return $this->respond([
'status' => 'failed',
'message' => 'Failed to retrieve user',
'data' => null
], 500);
}
}
/**
* Create new user
* POST /api/users
*/
public function create()
{
try {
$data = $this->request->getJSON(true);
// Validation rules
$rules = [
'Username' => 'required|min_length[3]|max_length[50]|is_unique[users.Username]',
'Email' => 'required|valid_email|is_unique[users.Email]',
];
if (!$this->validateData($data, $rules)) {
return $this->respond([
'status' => 'failed',
'message' => 'Validation failed',
'data' => $this->validator->getErrors()
], 400);
}
// Set default values
$data['IsActive'] = $data['IsActive'] ?? true;
$data['CreatedAt'] = date('Y-m-d H:i:s');
$userId = $this->model->insert($data);
if (!$userId) {
return $this->respond([
'status' => 'failed',
'message' => 'Failed to create user',
'data' => null
], 500);
}
return $this->respond([
'status' => 'success',
'message' => 'User created successfully',
'data' => [
'UserID' => $userId,
'Username' => $data['Username'],
'Email' => $data['Email']
]
], 201);
} catch (\Exception $e) {
log_message('error', 'UserController::create error: ' . $e->getMessage());
return $this->respond([
'status' => 'failed',
'message' => 'Failed to create user',
'data' => null
], 500);
}
}
/**
* Update existing user
* PATCH /api/users
*/
public function update()
{
try {
$data = $this->request->getJSON(true);
if (empty($data['UserID'])) {
return $this->respond([
'status' => 'failed',
'message' => 'UserID is required',
'data' => null
], 400);
}
$userId = $data['UserID'];
// Check if user exists
$user = $this->model->where('UserID', $userId)
->where('DelDate', null)
->first();
if (empty($user)) {
return $this->respond([
'status' => 'failed',
'message' => 'User not found',
'data' => null
], 404);
}
// Remove UserID from data array
unset($data['UserID']);
// Don't allow updating these fields
unset($data['CreatedAt']);
unset($data['Username']); // Username should not change
$data['UpdatedAt'] = date('Y-m-d H:i:s');
$updated = $this->model->update($userId, $data);
if (!$updated) {
return $this->respond([
'status' => 'failed',
'message' => 'Failed to update user',
'data' => null
], 500);
}
return $this->respond([
'status' => 'success',
'message' => 'User updated successfully',
'data' => [
'UserID' => $userId,
'updated_fields' => array_keys($data)
]
], 200);
} catch (\Exception $e) {
log_message('error', 'UserController::update error: ' . $e->getMessage());
return $this->respond([
'status' => 'failed',
'message' => 'Failed to update user',
'data' => null
], 500);
}
}
/**
* Delete user (soft delete)
* DELETE /api/users/(:num)
*/
public function delete($id)
{
try {
// Check if user exists
$user = $this->model->where('UserID', $id)
->where('DelDate', null)
->first();
if (empty($user)) {
return $this->respond([
'status' => 'failed',
'message' => 'User not found',
'data' => null
], 404);
}
// Soft delete by setting DelDate
$deleted = $this->model->update($id, [
'DelDate' => date('Y-m-d H:i:s'),
'IsActive' => false
]);
if (!$deleted) {
return $this->respond([
'status' => 'failed',
'message' => 'Failed to delete user',
'data' => null
], 500);
}
return $this->respond([
'status' => 'success',
'message' => 'User deleted successfully',
'data' => ['UserID' => $id]
], 200);
} catch (\Exception $e) {
log_message('error', 'UserController::delete error: ' . $e->getMessage());
return $this->respond([
'status' => 'failed',
'message' => 'Failed to delete user',
'data' => null
], 500);
}
}
}

View File

@ -1,138 +0,0 @@
<?php
namespace App\Models\User;
use CodeIgniter\Model;
/**
* User Model
* Handles database operations for users
*/
class UserModel extends Model
{
protected $table = 'users';
protected $primaryKey = 'UserID';
// Allow all fields to be mass-assigned
protected $allowedFields = [
'Username',
'Email',
'Name',
'Role',
'Department',
'IsActive',
'CreatedAt',
'UpdatedAt',
'DelDate'
];
// Use timestamps (disabled, we handle manually for consistency)
protected $useTimestamps = false;
// Validation rules
protected $validationRules = [
'Username' => 'required|min_length[3]|max_length[50]',
'Email' => 'required|valid_email|max_length[100]',
];
protected $validationMessages = [
'Username' => [
'required' => 'Username is required',
'min_length' => 'Username must be at least 3 characters',
'max_length' => 'Username cannot exceed 50 characters',
],
'Email' => [
'required' => 'Email is required',
'valid_email' => 'Please provide a valid email address',
'max_length' => 'Email cannot exceed 100 characters',
],
];
/**
* Get active users only
*/
public function getActive()
{
return $this->where('DelDate', null)
->where('IsActive', true)
->findAll();
}
/**
* Find user by username
*/
public function findByUsername($username)
{
return $this->where('Username', $username)
->where('DelDate', null)
->first();
}
/**
* Find user by email
*/
public function findByEmail($email)
{
return $this->where('Email', $email)
->where('DelDate', null)
->first();
}
/**
* Search users by name, username, or email
*/
public function search($term)
{
return $this->where('DelDate', null)
->groupStart()
->like('Username', $term)
->orLike('Email', $term)
->orLike('Name', $term)
->groupEnd()
->findAll();
}
/**
* Get users by role
*/
public function getByRole($role)
{
return $this->where('Role', $role)
->where('DelDate', null)
->where('IsActive', true)
->findAll();
}
/**
* Get users by department
*/
public function getByDepartment($department)
{
return $this->where('Department', $department)
->where('DelDate', null)
->where('IsActive', true)
->findAll();
}
/**
* Soft delete user
*/
public function softDelete($id)
{
return $this->update($id, [
'DelDate' => date('Y-m-d H:i:s'),
'IsActive' => false
]);
}
/**
* Restore soft-deleted user
*/
public function restore($id)
{
return $this->update($id, [
'DelDate' => null,
'IsActive' => true
]);
}
}

View File

@ -1,119 +0,0 @@
# 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

View File

@ -1,243 +0,0 @@
# User Management API
## Overview
Create a complete User CRUD API for the user management page.
## Required Endpoints
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | /api/users | List all users (with pagination) |
| GET | /api/users/(:num) | Get single user by ID |
| POST | /api/users | Create new user |
| PATCH | /api/users | Update existing user |
| DELETE | /api/users/(:num) | Delete user |
## Database Schema
The User model should use the existing `users` table (or create if doesn't exist):
```sql
-- If table doesn't exist, create it:
CREATE TABLE IF NOT EXISTS users (
UserID INT AUTO_INCREMENT PRIMARY KEY,
Username VARCHAR(50) NOT NULL UNIQUE,
Email VARCHAR(100) NOT NULL,
Name VARCHAR(100),
Role VARCHAR(50),
Department VARCHAR(100),
IsActive BOOLEAN DEFAULT TRUE,
CreatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UpdatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
DelDate TIMESTAMP NULL,
INDEX idx_username (Username),
INDEX idx_email (Email)
);
```
## User Fields
### Required Fields
- `Username` - Unique login username
- `Email` - User email address
### Optional Fields
- `Name` - Full name
- `Role` - User role (admin, technician, doctor, etc.)
- `Department` - Department name
- `IsActive` - Whether user is active
## API Specifications
### 1. List Users
**Request:**
```http
GET /api/users?page=1&per_page=20&search=john HTTP/1.1
```
**Query Parameters:**
- `page` - Page number (default: 1)
- `per_page` - Items per page (default: 20)
- `search` - Search term for username/email/name (optional)
**Success Response (200):**
```json
{
"status": "success",
"message": "Users retrieved successfully",
"data": {
"users": [
{
"UserID": 1,
"Username": "john.doe",
"Email": "john@hospital.com",
"Name": "John Doe",
"Role": "technician",
"Department": "Laboratory",
"IsActive": true,
"CreatedAt": "2024-01-15 10:30:00"
}
],
"pagination": {
"current_page": 1,
"per_page": 20,
"total": 150,
"total_pages": 8
}
}
}
```
### 2. Get Single User
**Request:**
```http
GET /api/users/1 HTTP/1.1
```
**Success Response (200):**
```json
{
"status": "success",
"message": "User retrieved successfully",
"data": {
"UserID": 1,
"Username": "john.doe",
"Email": "john@hospital.com",
"Name": "John Doe",
"Role": "technician",
"Department": "Laboratory",
"IsActive": true,
"CreatedAt": "2024-01-15 10:30:00",
"UpdatedAt": "2024-01-15 10:30:00"
}
}
```
**Not Found Response (404):**
```json
{
"status": "failed",
"message": "User not found",
"data": null
}
```
### 3. Create User
**Request:**
```http
POST /api/users HTTP/1.1
Content-Type: application/json
{
"Username": "jane.smith",
"Email": "jane@hospital.com",
"Name": "Jane Smith",
"Role": "doctor",
"Department": "Pathology"
}
```
**Success Response (201):**
```json
{
"status": "success",
"message": "User created successfully",
"data": {
"UserID": 2,
"Username": "jane.smith",
"Email": "jane@hospital.com"
}
}
```
**Validation Error Response (400):**
```json
{
"status": "failed",
"message": "Validation failed",
"data": {
"Username": "Username is required",
"Email": "Email is required"
}
}
```
### 4. Update User
**Request:**
```http
PATCH /api/users HTTP/1.1
Content-Type: application/json
{
"UserID": 1,
"Name": "John Doe Updated",
"Role": "senior_technician"
}
```
**Success Response (200):**
```json
{
"status": "success",
"message": "User updated successfully",
"data": {
"UserID": 1,
"Name": "John Doe Updated",
"Role": "senior_technician"
}
}
```
### 5. Delete User
**Request:**
```http
DELETE /api/users/1 HTTP/1.1
```
**Success Response (200):**
```json
{
"status": "success",
"message": "User deleted successfully",
"data": {
"UserID": 1
}
}
```
## Implementation Files
See `code-templates/` folder for ready-to-use code:
- `UserController.php` - Complete controller implementation
- `UserModel.php` - Database model
- `Routes-additions.php` - Routes to add to Routes.php
## Testing
After implementation, test with:
```bash
# List users
curl http://localhost:8000/api/users
# Get single user
curl http://localhost:8000/api/users/1
# Create user
curl -X POST http://localhost:8000/api/users \
-H "Content-Type: application/json" \
-d '{"Username":"test","Email":"test@test.com","Name":"Test User"}'
# Update user
curl -X PATCH http://localhost:8000/api/users \
-H "Content-Type: application/json" \
-d '{"UserID":1,"Name":"Updated Name"}'
# Delete user
curl -X DELETE http://localhost:8000/api/users/1
```

View File

@ -1,165 +0,0 @@
## Context
The CLQMS frontend currently has several incomplete features marked with TODO comments:
1. **Patient Delete**: The `deletePatient()` API exists but isn't wired up in the UI
2. **Order Detail**: Orders can only be viewed as a list item, with no detail modal
3. **Barcode Printing**: Referenced in UI but not implemented
4. **TestMap Delete**: Blocked by API limitation (missing TestMapID in list response)
Additionally, the sidebar links to two pages that don't exist:
- **Specimens**: Critical for complete lab workflow (patient → visit → order → specimen → results)
- **Users**: Essential for system administration
This change addresses all these gaps to provide a complete laboratory management experience.
## Goals / Non-Goals
**Goals:**
- Wire up patient delete functionality
- Create order detail view modal
- Implement specimen management page with full CRUD
- Implement user management page with full CRUD
- Prepare barcode printing infrastructure
- Document TestMap delete limitation
**Non-Goals:**
- Full barcode generation library integration (out of scope, preparing structure only)
- Backend API changes for TestMap (document limitation only)
- Role-based access control (reuse existing auth patterns)
- Advanced specimen tracking (batch, location) - basic CRUD only
## Backend API Requirements
### Specimen API (clqms01-be)
**Current Status:** CRU exists, missing DELETE
Required additions:
```php
// Add to app/Config/Routes.php
$routes->delete('(:num)', 'Specimen\SpecimenController::delete/$1');
// Add to SpecimenController
public function delete($id) {
// Soft delete specimen
}
```
### User API (clqms01-be)
**Current Status:** Not implemented
Required new files:
```
app/
├── Controllers/
│ └── User/
│ └── UserController.php # CRUD operations
├── Models/
│ └── User/
│ └── UserModel.php # Database model
└── Config/Routes.php # Add user routes
```
Required endpoints:
- `GET /api/users` - List with pagination
- `GET /api/users/(:num)` - Get single user
- `POST /api/users` - Create user
- `PATCH /api/users` - Update user
- `DELETE /api/users/(:num)` - Delete user
## Decisions
### Decision: Use Existing Patterns
**Rationale**: Consistency with existing codebase reduces cognitive load and maintenance burden.
All new pages follow existing patterns:
- Search/filter pattern from Patients page
- Modal forms from Test Management
- API structure from existing `/lib/api/*.js` files
- DaisyUI + Tailwind styling consistent with current UI
### Decision: Barcode Printing - Stub First
**Rationale**: Barcode libraries (jsbarcode, qrcode) add dependencies. Better to prepare structure first, then integrate library in follow-up.
Current implementation:
- Print button triggers stub function
- Opens print dialog with formatted HTML
- Placeholder text indicates "coming soon"
Future enhancement:
- Add jsbarcode or similar library
- Generate actual barcodes
- Keep same print dialog structure
### Decision: Specimen Page Structure
**Rationale**: Specimens bridge orders and results - need to show relationships.
Page layout:
- Search/filter bar (specimen type, status, date)
- Data table with key columns
- Detail modal showing:
- Specimen attributes
- Related order info
- Collection details
- Container information
### Decision: User Page - Basic CRUD Only
**Rationale**: User management is admin function, not daily use. Complex features (permissions matrix, audit logs) can be added later.
Features:
- List users with search
- Create/edit user form
- Soft delete (disable) users
- Prevent self-deletion
Not included:
- Permission matrix UI
- User activity audit
- Password reset flow (use existing)
## Risks / Trade-offs
**[Risk] API endpoints may not exist for specimens/users**
**Status**: CONFIRMED - Specimen delete missing, User API not implemented
**Mitigation**: Coordinate with backend team to add endpoints before frontend delete features
**[Risk] TestMap delete limitation blocks feature**
**Mitigation**: Document limitation clearly, add informative error message, suggest backend improvement
**[Risk] Barcode printing may not work in all browsers**
**Mitigation**: Use standard window.print(), test in target environments, provide fallback
**[Risk] User delete without RBAC checks**
**Mitigation**: Add client-side check to prevent self-deletion, rely on backend for authorization
## Migration Plan
**Deployment**:
1. Deploy frontend changes
2. Verify new pages load correctly
3. Test patient delete on staging data
4. Verify sidebar navigation works
**Rollback**:
- Revert to previous commit
- No database changes required (frontend only)
## Open Questions
1. **What fields are available for specimens?**
Need to review SpecimenModel for data structure
2. **Are there existing barcode requirements?**
What format? Code128? QR codes? What data to encode?
3. **Should users have soft delete or hard delete?**
Check if backend supports soft delete (status field)
## Backend Coordination Checklist
- [ ] Backend: Add Specimen delete endpoint
- [ ] Backend: Create UserController
- [ ] Backend: Create UserModel
- [ ] Backend: Add user routes to Routes.php
- [ ] Frontend: Implement specimen delete once API ready
- [ ] Frontend: Implement users page once API ready

View File

@ -1,63 +0,0 @@
## Why
The CLQMS frontend has several incomplete features marked with TODO comments that block core workflows. Additionally, the sidebar links to Specimens and Users pages that don't exist yet. Completing these TODOs and adding the missing pages will provide a fully functional laboratory management system with complete patient-to-results tracking and user administration capabilities.
## What Changes
### Backend TODOs (F)
- **Patient Delete**: Wire up existing `deletePatient()` API (currently commented out)
- **Order Detail View**: Create modal component to display order details, test list, and status history
- **Barcode Printing**: Add print stubs and structure for patient wristbands and specimen labels
- **TestMap Delete**: Document API limitation and add error handling for missing TestMapID
### New Pages
- **Specimens Page** (A): Full CRUD page for specimen tracking with search, list, and detail views
- **Users Page** (B): User management interface with CRUD operations
### Backend Requirements (Coordinate with clqms01-be)
- **Specimen Delete API**: Add `DELETE /api/specimen/(:num)` endpoint to backend
- **User Management API**: Create complete CRUD API for user management:
- `GET /api/users` - List users
- `GET /api/users/(:num)` - Get user details
- `POST /api/users` - Create user
- `PATCH /api/users` - Update user
- `DELETE /api/users/(:num)` - Delete user
### Minor Improvements
- Update sidebar navigation to point to new pages
- Add proper error handling for incomplete features
## Capabilities
### New Capabilities
- `specimen-management`: Specimen tracking and management interface
- `user-management`: User administration and role management
- `barcode-printing`: Barcode generation and printing for patients and specimens
- `order-detail-view`: Detailed order inspection with test breakdown
### Modified Capabilities
- `patient-management`: Add delete functionality to complete CRUD operations
## Impact
- **Frontend**: 3 new route pages, 2 new modal components, API integrations
- **Backend**: New endpoints for specimen delete and user CRUD operations
- **User Experience**: Completes core lab workflow from patient registration to results
- **Breaking Changes**: None - additive changes only
## Dependencies
**Backend Changes Required (clqms01-be repo):**
| Feature | Backend Work | Status |
|---------|--------------|--------|
| Patient Delete | ✅ Already exists | Ready |
| Specimens | ⚠️ Add DELETE endpoint | **BLOCKS specimen delete** |
| Users | ❌ Create full CRUD API | **BLOCKS users page** |
| Order Detail | ✅ Already exists | Ready |
**Coordination Strategy:**
1. Backend team creates specimen delete endpoint
2. Backend team creates user management API
3. Frontend implements features as APIs become available
4. Parallel development possible for non-dependent features

View File

@ -1,30 +0,0 @@
## ADDED Requirements
### Requirement: Barcodes can be printed for patients
The system SHALL provide barcode printing functionality for patient identification.
#### Scenario: Print patient wristband
- **WHEN** user clicks print barcode on a patient
- **THEN** system generates barcode with patient ID
- **AND** opens print dialog with wristband layout
- **AND** includes patient name and ID on wristband
#### Scenario: Print specimen label
- **WHEN** user clicks print barcode on an order
- **THEN** system generates barcode with order/specimen ID
- **AND** opens print dialog with label layout
- **AND** includes patient info, test codes, and date
### Requirement: Barcode printing structure is prepared
The system SHALL have barcode printing infrastructure ready for full implementation.
#### Scenario: Barcode generation stub exists
- **WHEN** print barcode is triggered
- **THEN** system calls barcode generation function
- **AND** function returns placeholder for now
- **AND** displays coming soon message
#### Scenario: Print dialog integration
- **WHEN** barcode data is ready
- **THEN** system opens browser print dialog
- **AND** provides formatted layout for printing

View File

@ -1,28 +0,0 @@
## ADDED Requirements
### Requirement: Order details can be viewed
The system SHALL provide a modal to view detailed order information.
#### Scenario: View order details
- **WHEN** user clicks on an order in the list
- **THEN** system opens order detail modal
- **AND** displays order header information (number, date, status)
- **AND** shows patient information
- **AND** lists all tests in the order
#### Scenario: View order test details
- **WHEN** viewing order details
- **THEN** system displays each test with code, name, and status
- **AND** shows specimen requirements
- **AND** indicates if results are entered
#### Scenario: View order status history
- **WHEN** viewing order details
- **THEN** system shows status change history
- **AND** includes timestamps for each status change
- **AND** shows who performed each status change
#### Scenario: Close order detail modal
- **WHEN** user clicks close or outside modal
- **THEN** system closes order detail modal
- **AND** returns to order list

View File

@ -1,16 +0,0 @@
## ADDED Requirements
### Requirement: Patient can be deleted
The system SHALL allow authorized users to delete patients from the system.
#### Scenario: Successful patient deletion
- **WHEN** user clicks delete button on a patient
- **AND** user confirms deletion in the confirmation dialog
- **THEN** system calls deletePatient API with InternalPID
- **AND** patient is removed from the list
- **AND** success message is displayed
#### Scenario: Deletion failure
- **WHEN** deletePatient API returns an error
- **THEN** error message is displayed
- **AND** patient remains in the list

View File

@ -1,34 +0,0 @@
## ADDED Requirements
### Requirement: Specimens can be viewed and managed
The system SHALL provide a page to view, search, and manage laboratory specimens.
#### Scenario: View specimen list
- **WHEN** user navigates to /specimens
- **THEN** system displays a list of specimens with filtering options
- **AND** list includes specimen ID, type, status, and related order
#### Scenario: Search specimens
- **WHEN** user enters search criteria
- **THEN** system filters specimen list matching criteria
- **AND** supports filtering by specimen type, status, date range
#### Scenario: View specimen details
- **WHEN** user clicks on a specimen
- **THEN** system displays specimen detail modal
- **AND** shows all specimen attributes and related information
#### Scenario: Create new specimen
- **WHEN** user clicks "New Specimen" button
- **THEN** system opens specimen creation form
- **AND** saves specimen on form submission
#### Scenario: Edit specimen
- **WHEN** user clicks edit on a specimen
- **THEN** system opens specimen edit form
- **AND** updates specimen on form submission
#### Scenario: Delete specimen
- **WHEN** user clicks delete on a specimen
- **AND** user confirms deletion
- **THEN** system removes specimen from database

View File

@ -1,31 +0,0 @@
## ADDED Requirements
### Requirement: Users can be managed
The system SHALL provide an interface for administrators to manage system users.
#### Scenario: View user list
- **WHEN** administrator navigates to /master-data/users
- **THEN** system displays a list of users
- **AND** list includes username, role, status, and department
#### Scenario: Create new user
- **WHEN** administrator clicks "New User" button
- **THEN** system opens user creation form
- **AND** form includes fields for username, email, role, password
- **AND** system saves user on form submission
#### Scenario: Edit user
- **WHEN** administrator clicks edit on a user
- **THEN** system opens user edit form
- **AND** allows modification of user attributes
- **AND** updates user on form submission
#### Scenario: Delete user
- **WHEN** administrator clicks delete on a user
- **AND** administrator confirms deletion
- **THEN** system removes user from database
- **AND** prevents deletion of own account
#### Scenario: Search users
- **WHEN** administrator enters search term
- **THEN** system filters user list by username, email, or role

View File

@ -1,92 +0,0 @@
## 0. Backend Coordination (clqms01-be repo)
**These backend changes must be completed before dependent frontend tasks:**
- [ ] 0.1 Add Specimen delete endpoint to Routes.php
- [ ] 0.2 Implement SpecimenController::delete() method
- [ ] 0.3 Create UserController with CRUD methods
- [ ] 0.4 Create UserModel for database operations
- [ ] 0.5 Add user routes to Routes.php
- [ ] 0.6 Test backend endpoints with Postman/curl
## 1. Backend TODOs - Patient Delete
- [x] 1.1 Import deletePatient function in patients/+page.svelte
- [x] 1.2 Uncomment delete API call in handleDelete function
- [x] 1.3 Add error handling for delete operation
- [ ] 1.4 Test patient delete functionality
## 2. Backend TODOs - Order Detail View
- [x] 2.1 Create OrderDetailModal.svelte component
- [x] 2.2 Add order header display (number, date, status, patient)
- [x] 2.3 Add test list display with status indicators
- [x] 2.4 Add status history timeline
- [x] 2.5 Wire up modal to order list click handler
- [ ] 2.6 Test order detail modal
## 3. Backend TODOs - Barcode Printing Structure
- [x] 3.1 Create barcode.js utility file with print functions
- [x] 3.2 Add printPatientWristband stub function
- [x] 3.3 Add printSpecimenLabel stub function
- [x] 3.4 Wire up barcode printing to patient order list
- [x] 3.5 Wire up barcode printing to orders page
- [ ] 3.6 Test print dialog opens correctly
## 4. Backend TODOs - TestMap Delete Documentation
- [x] 4.1 Add informative error message for TestMap delete limitation
- [x] 4.2 Document API limitation in code comments
- [x] 4.3 Add console warning with explanation
## 5. Specimens Page
- [x] 5.1 Create specimens API client file (src/lib/api/specimens.js)
- [x] 5.2 Create specimens/+page.svelte route
- [x] 5.3 Add specimen search/filter bar
- [x] 5.4 Add specimen data table with columns
- [x] 5.5 Create SpecimenFormModal component
- [x] 5.6 Implement specimen creation
- [x] 5.7 Implement specimen editing
- [ ] 5.8 Implement specimen deletion **[BLOCKED: Requires task 0.1-0.2]**
- [x] 5.9 Create SpecimenDetailModal component
- [x] 5.10 Wire up detail view
- [ ] 5.11 Test full specimen CRUD workflow
## 6. Users Page
- [x] 6.1 Create users API client file (src/lib/api/users.js)
- [x] 6.2 Create master-data/users/+page.svelte route **[API NOT READY]**
- [x] 6.3 Add user search functionality **[API NOT READY]**
- [x] 6.4 Add user data table **[API NOT READY]**
- [x] 6.5 Create UserFormModal component **[API NOT READY]**
- [x] 6.6 Implement user creation **[API NOT READY]**
- [x] 6.7 Implement user editing **[API NOT READY]**
- [x] 6.8 Implement user deletion with self-delete prevention **[API NOT READY]**
- [ ] 6.9 Test user management workflow **[BLOCKED: Pending backend API]**
## 7. Navigation Updates
- [x] 7.1 Verify specimens link in sidebar works
- [x] 7.2 Verify users link in sidebar works
- [x] 7.3 Update any broken navigation paths
- [ ] 7.4 Test all navigation flows **[PARTIALLY BLOCKED]**
## 8. Integration & Testing
- [ ] 8.1 Run development server
- [ ] 8.2 Test patient delete end-to-end
- [ ] 8.3 Test order detail modal
- [ ] 8.4 Test barcode print dialogs
- [ ] 8.5 Test specimens page CRUD **[PARTIALLY BLOCKED: Delete pending backend]**
- [ ] 8.6 Test users page CRUD **[BLOCKED: Pending backend]**
- [ ] 8.7 Verify no console errors
- [ ] 8.8 Code review and cleanup
## 9. Deployment
- [ ] 9.1 Coordinate backend deployment
- [ ] 9.2 Deploy frontend changes
- [ ] 9.3 Verify all features in production
- [ ] 9.4 Update API documentation

View File

@ -1,20 +0,0 @@
schema: spec-driven
# Project context (optional)
# This is shown to AI when creating artifacts.
# Add your tech stack, conventions, style guides, domain knowledge, etc.
# Example:
# context: |
# Tech stack: TypeScript, React, Node.js
# We use conventional commits
# Domain: e-commerce platform
# Per-artifact rules (optional)
# Add custom rules for specific artifacts.
# Example:
# rules:
# proposal:
# - Keep proposals under 500 words
# - Always include a "Non-goals" section
# tasks:
# - Break tasks into chunks of max 2 hours