fix(family-grouping): resolve 422 error and preserve custom roles during family creation
Merge Request
Overview
Fixes a 422 Unprocessable Entity bug that occurs when attempting to create a new family from the volunteer interface. The fix aligns the frontend's API call with the backend's expected JSON schema and ensures that the user's selected family role is correctly saved to the database.
What does this MR do and why?
Previously, when a volunteer attempted to put a patient into a new family, the React application passed book_no and family_role as URL query parameters with an empty POST body. The FastAPI backend, anticipating a JSON object inside the body, promptly rejected the request with a 422 Unprocessable Entity.
Additionally, the FastAPI server strictly ignored the family_role option entirely, hardcoding every new family creator as "head".
This MR updates the payload structure on the frontend so a standard JSON body is sent, tracks the custom family_role directly inside the Pydantic schema, and connects it to the service layer so the actual user selection is correctly written to the database. Minor adjustments were also made to ensure that if a family is created by a role other than "head", a "head" can still legally be appended to the family later on.
Changes Made
Technical Details
- Frontend (api.ts): Updated the createFamily helper function to dispatch the data payload inside the JSON body rather than attaching to the URL parameters.
-
Schema (app/schemas/family.py): Explicitly enforced the
family_roleproperty inside the FamilyCreate schema to allow Pydantic to parse it smoothly. -
Routes (app/api/v1/routes/family_routes.py): Exposed and forwarded
data.family_role.valueto the service handler. - Service Layer (app/services/family_service.py): Re-wired create_family to ingest and validate the selected role rather than defaulting to "head", and slightly relaxed add_family_member to permit the assignment of a "head" exclusively if the family doesn't currently possess one.
- Tests (test_family_routes.py, test_family_service.py): Updated existing unit tests to supply the new required schema fields properly and expanded coverage testing logic to account for multiple head role checks during family manipulation.
Type of Change
-
🐛 Bug fix (non-breaking change that fixes an issue) -
✨ New feature (non-breaking change that adds functionality) -
💥 Breaking change (fix or feature that would cause existing functionality to change) -
📝 Documentation update -
♻ ️ Refactor (no functional changes) -
⚡ Performance improvement -
🧪 Test update -
🔧 Configuration change -
🚨 Security fix -
🗑 ️ Deprecation (removing deprecated code)
Related Issues / References
Screenshots or Screen Recordings
How to Validate Locally
- Launch both the backend API and frontend React app locally.
- In the UI, navigate to the Family Grouping page as a volunteer.
- Check a valid book number and click "Create Family".
- Fill out the Book Number and select any Family Role from the dropdown (e.g. "Parent").
- Click Create Family.
- Previous Behavior: The network tab shows a 422 error complaining about process validation and the operation fails.
- New Behavior: The family seamlessly creates on the screen without error, and fetching the members verifies that the explicitly selected role was preserved.
Testing Done
-
Unit tests added/updated -
API endpoint tests passing
Test Cases Covered:
| Scenario | Expected Result | Status |
|---|---|---|
| Attempting to create family with valid payload | Returns 200 and matches created role | |
| Creating family without providing a body payload | FastAPI natively blocks via 422 | |
| Adding a "head" to a family that already has one | Safely caught by ValueError checks |
Test Commands Run:
pytest tests/test_api/test_family_routes.py tests/unit/services/test_family_service.py
pytest --cov=app tests/
### Code Standards
- [x] Code follows project conventions (naming, structure, formatting)
- [x] No debug statements or commented-out code left (unless necessary and intended)
- [x] No unused imports, variables, or functions
- [x] No duplicate code (DRY principle followed)
- [x] Type hints are properly defined (no `Any` unless justified and no mypy type check errors)
- [ ] Ruff checks pass:
```bash
ruff check .
ruff format . --check
Python & FastAPI Best Practices
-
Functions follow single-responsibility principle -
Async/await used correctly (no blocking calls in async functions) -
Dependency injection used appropriately -
Pydantic models used for request/response validation -
SQLAlchemy queries are optimized (no N+1 queries) -
Error handling is comprehensive (try/except with proper logging)
API Design
-
RESTful conventions followed -
Proper HTTP status codes returned -
Input validation implemented -
Authentication/authorization enforced -
Role Base access control used for user restriction -
API documentation (docstrings) updated
Database & Migrations
-
Database migrations created (if schema changed) -
Database migrations version is pointing to the latest version (and version name follows project conventions) -
Migrations are reversible (migrations contain downgrade scripts) -
Indexes added for frequently queried fields -
No raw SQL queries (using SQLAlchemy ORM) -
Data integrity constraints maintained
Security
-
No sensitive data logged (passwords, tokens, PII) -
SQL injection prevention verified (ORM used) -
Input sanitization implemented -
Authentication tokens handled securely -
CORS settings appropriate -
Security scan passes: bandit -r app/
Error Handling
-
Errors are caught and handled gracefully -
User-friendly error messages returned -
Errors are logged appropriately -
HTTP error responses follow API standards
Documentation
-
README.md updated (if setup steps changed) -
.env.exampleupdated (if new env vars added) -
API documentation updated (docstrings, OpenAPI specs) -
CHANGELOG.md will be updated (if applicable) -
Code comments explain complex logic (not what, but why)
Known Limitations / Technical Debt
Additional Notes
MR Acceptance Checklist
Quality & Correctness
-
Code works as intended and solves the stated problem -
No bugs introduced (existing functionality not broken) -
Edge cases handled appropriately
Maintainability
-
Code is readable and well-organized -
Code is testable and well-tested -
Follows project patterns and conventions
