Init Repo
This commit is contained in:
@@ -0,0 +1,240 @@
|
||||
# Task 5 Requirements Checklist
|
||||
|
||||
## Task: Backend: Implement PUT endpoint for updating custom status
|
||||
|
||||
### Requirements Coverage
|
||||
|
||||
#### ✅ Requirement 2.1: Support updating name
|
||||
|
||||
**Implementation:**
|
||||
```python
|
||||
# Validate name uniqueness if name is being changed
|
||||
if status_update.name is not None and status_update.name != status_to_update.get('name'):
|
||||
# Check against other custom statuses
|
||||
existing_names = [
|
||||
s.get('name', '').lower()
|
||||
for i, s in enumerate(custom_statuses_data)
|
||||
if isinstance(s, dict) and i != status_index
|
||||
]
|
||||
|
||||
# Check against system statuses
|
||||
system_names = [s['name'].lower() for s in SYSTEM_TASK_STATUSES]
|
||||
|
||||
if status_update.name.lower() in existing_names:
|
||||
raise HTTPException(status_code=409, ...)
|
||||
|
||||
if status_update.name.lower() in system_names:
|
||||
raise HTTPException(status_code=409, ...)
|
||||
|
||||
# Update name
|
||||
status_to_update['name'] = status_update.name
|
||||
```
|
||||
|
||||
**Verified:**
|
||||
- ✅ Name can be updated
|
||||
- ✅ Name validation works
|
||||
- ✅ Uniqueness check implemented
|
||||
- ✅ Returns updated status
|
||||
|
||||
---
|
||||
|
||||
#### ✅ Requirement 2.2: Support updating color
|
||||
|
||||
**Implementation:**
|
||||
```python
|
||||
# Update color if provided
|
||||
if status_update.color is not None:
|
||||
status_to_update['color'] = status_update.color
|
||||
```
|
||||
|
||||
**Verified:**
|
||||
- ✅ Color can be updated
|
||||
- ✅ Color format validated by schema (hex codes)
|
||||
- ✅ Color updates independently of other fields
|
||||
- ✅ Returns updated status
|
||||
|
||||
---
|
||||
|
||||
#### ✅ Requirement 2.3: Support updating is_default flag
|
||||
|
||||
**Implementation:**
|
||||
```python
|
||||
# Handle is_default flag
|
||||
if status_update.is_default is not None:
|
||||
if status_update.is_default:
|
||||
# If setting as default, unset other default statuses
|
||||
for status_data in custom_statuses_data:
|
||||
if isinstance(status_data, dict):
|
||||
status_data['is_default'] = False
|
||||
|
||||
# Set this status as default
|
||||
status_to_update['is_default'] = True
|
||||
else:
|
||||
# Just unset this status as default
|
||||
status_to_update['is_default'] = False
|
||||
```
|
||||
|
||||
**Verified:**
|
||||
- ✅ is_default flag can be updated
|
||||
- ✅ Can set status as default
|
||||
- ✅ Can unset status as default
|
||||
- ✅ Returns updated status
|
||||
|
||||
---
|
||||
|
||||
#### ✅ Requirement 5.2: If setting as default, unset other default statuses
|
||||
|
||||
**Implementation:**
|
||||
```python
|
||||
if status_update.is_default:
|
||||
# If setting as default, unset other default statuses
|
||||
for status_data in custom_statuses_data:
|
||||
if isinstance(status_data, dict):
|
||||
status_data['is_default'] = False
|
||||
|
||||
# Set this status as default
|
||||
status_to_update['is_default'] = True
|
||||
```
|
||||
|
||||
**Verified:**
|
||||
- ✅ When setting a status as default, all other defaults are unset
|
||||
- ✅ Only one default status exists at a time
|
||||
- ✅ Default status ID is correctly returned in response
|
||||
- ✅ Previous default is properly unset
|
||||
|
||||
---
|
||||
|
||||
#### ✅ Additional Requirement: Validate name uniqueness if name is changed
|
||||
|
||||
**Implementation:**
|
||||
```python
|
||||
# Validate name uniqueness if name is being changed
|
||||
if status_update.name is not None and status_update.name != status_to_update.get('name'):
|
||||
# Check against other custom statuses
|
||||
existing_names = [...]
|
||||
|
||||
# Check against system statuses
|
||||
system_names = [...]
|
||||
|
||||
if status_update.name.lower() in existing_names:
|
||||
raise HTTPException(status_code=409, ...)
|
||||
|
||||
if status_update.name.lower() in system_names:
|
||||
raise HTTPException(status_code=409, ...)
|
||||
```
|
||||
|
||||
**Verified:**
|
||||
- ✅ Name uniqueness validated within project
|
||||
- ✅ Checks against other custom statuses
|
||||
- ✅ Checks against system status names
|
||||
- ✅ Returns 409 Conflict on duplicate
|
||||
|
||||
---
|
||||
|
||||
#### ✅ Additional Requirement: Use flag_modified for JSON column updates
|
||||
|
||||
**Implementation:**
|
||||
```python
|
||||
# Update the status in the list
|
||||
custom_statuses_data[status_index] = status_to_update
|
||||
db_project.custom_task_statuses = custom_statuses_data
|
||||
|
||||
# Use flag_modified for JSON column updates
|
||||
flag_modified(db_project, 'custom_task_statuses')
|
||||
|
||||
try:
|
||||
db.commit()
|
||||
db.refresh(db_project)
|
||||
except Exception as e:
|
||||
db.rollback()
|
||||
raise HTTPException(...)
|
||||
```
|
||||
|
||||
**Verified:**
|
||||
- ✅ flag_modified is used
|
||||
- ✅ Changes persist to database
|
||||
- ✅ JSON column updates work correctly
|
||||
- ✅ Rollback on error
|
||||
|
||||
---
|
||||
|
||||
### Endpoint Details
|
||||
|
||||
**Route:** `PUT /projects/{project_id}/task-statuses/{status_id}`
|
||||
|
||||
**Authorization:** Requires coordinator or admin role
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"name": "string (optional)",
|
||||
"color": "string (optional)",
|
||||
"is_default": "boolean (optional)"
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** `CustomTaskStatusResponse`
|
||||
```json
|
||||
{
|
||||
"message": "string",
|
||||
"status": { ... },
|
||||
"all_statuses": { ... }
|
||||
}
|
||||
```
|
||||
|
||||
**Error Codes:**
|
||||
- 404: Project or status not found
|
||||
- 409: Name conflict (duplicate or system status)
|
||||
- 403: Insufficient permissions
|
||||
- 422: Invalid request body
|
||||
|
||||
---
|
||||
|
||||
### Test Coverage
|
||||
|
||||
**Manual Tests Created:**
|
||||
- ✅ `test_update_status_manual.py` - Comprehensive manual test script
|
||||
- ✅ Tests all requirements
|
||||
- ✅ Tests error conditions
|
||||
- ✅ Tests edge cases
|
||||
|
||||
**Documentation Created:**
|
||||
- ✅ `custom-task-status-update-endpoint.md` - Complete API documentation
|
||||
- ✅ `task-5-implementation-summary.md` - Implementation summary
|
||||
- ✅ `task-5-requirements-checklist.md` - This checklist
|
||||
|
||||
---
|
||||
|
||||
### Code Quality
|
||||
|
||||
**Validation:**
|
||||
- ✅ No syntax errors
|
||||
- ✅ No linting errors
|
||||
- ✅ Follows existing code patterns
|
||||
- ✅ Proper error handling
|
||||
- ✅ Comprehensive validation
|
||||
- ✅ Clear error messages
|
||||
|
||||
**Best Practices:**
|
||||
- ✅ Uses dependency injection
|
||||
- ✅ Proper authorization checks
|
||||
- ✅ Transaction management (commit/rollback)
|
||||
- ✅ Input validation via Pydantic schemas
|
||||
- ✅ Consistent response format
|
||||
- ✅ Proper HTTP status codes
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
✅ **All requirements implemented and verified**
|
||||
|
||||
The PUT endpoint for updating custom task statuses has been successfully implemented with:
|
||||
- Full support for updating name, color, and is_default flag
|
||||
- Comprehensive validation (uniqueness, format, conflicts)
|
||||
- Proper default status management (only one default at a time)
|
||||
- Correct JSON column updates using flag_modified
|
||||
- Complete error handling and authorization
|
||||
- Comprehensive documentation and test scripts
|
||||
|
||||
**Task Status:** ✅ COMPLETED
|
||||
Reference in New Issue
Block a user