Feature/unregister doctor for camp
Overview
Updates the doctor camp registration endpoint to support both register and unregister actions through a single endpoint, while preserving doctor camp-visit history for analytics and audit use cases.
What does this MR do and why?
Previously, unregistering a doctor deleted the CampVisit row entirely, causing permanent loss of historical participation data. This MR introduces a soft-unregister approach — setting attendance = false instead of deleting the record — so camp analytics and audit trails remain intact.
The register/unregister actions are unified under a single endpoint using a register boolean flag in the request body, keeping the API surface minimal and consistent.
Changes Made
-
app/schemas/doctor.py— AddedDoctorRegisterSchema -
app/services/doctor_service.py— Updatedregister_doctor_for_campwith reactivation logic; addedunregister_doctor_for_campwith soft-delete -
app/api/v1/routes/doctor_routes.py— Updated endpoint to acceptDoctorRegisterSchemabody and branch onregisterflag -
tests/test_api/test_doctor_routes.py— Updated tests for new request body contract; added unregister400test -
tests/test_services/test_doctor_service.py— Added integration tests for reactivation, soft-unregister, and attendance filtering
Technical Details
Endpoint: POST /api/v1/doctors/{doctor_id}/register
Request body:
{ "register": true }
or
{ "register": false }
Register (register = true):
- Registers the doctor for the latest medical camp
- If no
CampVisitrecord exists, a new one is created withattendance = trueandsignup = true - If a
CampVisitalready exists withattendance = false(previously unregistered), the existing record is reactivated —attendance = true,signup = true - Raises
400if the doctor is already actively registered (attendance = true)
Unregister (register = false):
- Does not delete the
CampVisitrecord — preserves history for reporting and audit - Marks the doctor as inactive for the latest camp —
attendance = false,signup = false - Raises
400if the doctor has no active registration for the camp
Impact on existing endpoints:
GET /api/v1/doctors/registered is unaffected — it continues to return only doctors where CampVisit.camp_id matches the selected/latest camp, CampVisit.camp_role = 'doctor', and CampVisit.attendance = true. Unregistered doctors are automatically excluded.
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 -
🎨 UI/UX improvement -
♻ ️ Refactor (no functional changes) -
⚡ Performance improvement -
🧪 Test update -
🔧 Configuration change -
🚨 Security fix
Related Issues / References
Screenshots or Screen Recordings
How to Set Up and Validate Locally
- Checkout this branch
- Start the backend services:
docker compose up - Run focused backend tests:
pytest tests/test_api/test_doctor_routes.py tests/test_services/test_doctor_service.py -v - To test manually via API:
- Register a doctor:
POST /api/v1/doctors/{doctor_id}/registerwith{ "register": true } - Unregister the same doctor:
POST /api/v1/doctors/{doctor_id}/registerwith{ "register": false } - Verify the
CampVisitrow still exists in DB withattendance = false - Confirm
GET /api/v1/doctors/registeredno longer returns the unregistered doctor
- Register a doctor:
Testing Done
-
Manual testing completed -
Unit tests added/updated
Test Cases Covered:
| Scenario | Expected Result | Status |
|---|---|---|
| Register a new doctor for a camp | New CampVisit created with attendance = true
|
|
| Re-register a previously unregistered doctor | Existing CampVisit reactivated, not duplicated |
|
| Register an already active doctor |
400 error returned |
|
| Unregister an active doctor |
CampVisit preserved, attendance = false
|
|
| Unregister a doctor with no active registration |
400 error returned |
|
| Fetch registered doctors after unregister | Unregistered doctor excluded from results |
Test results: 10 passed, 0 failed
Code Quality Checklist
Code Standards
-
Code follows project conventions (naming, structure, formatting) -
No console.log() or debugger statements left in code -
No unused imports, variables, or functions -
No duplicate code and use of existing components for reusability -
i18n check passed with no hardcoded strings in codebase for i18n support -
TypeScript types are properly defined (no anyunless justified) -
ESLint and Prettier checks pass bun run lint
React Best Practices
-
Components are properly split and single-responsibility -
Hooks follow rules (no conditional hooks, proper dependencies) -
State management is appropriate (local vs global state) -
No unnecessary re-renders (memoization used where needed) -
Event handlers are properly cleaned up
Component Patterns
-
shadcn/ui components used correctly -
Tailwind classes follow utility-first approach -
Responsive design considered (mobile-first if applicable) -
Accessibility attributes included (aria-*, role, etc.) -
Icons from lucide-react used consistently
API & Data Fetching
-
TanStack Query used for server state (if applicable) -
Loading and error states handled -
API types defined in src/types/api.ts -
Axios interceptors handle auth tokens correctly -
Use of Zod for data validations
Error Handling
-
Errors are caught and handled gracefully -
User-friendly error messages displayed -
Errors are being toasted properly -
Network failures handled appropriately
Documentation
-
README.md updated (if setup steps changed) -
.env.exampleupdated (if new env vars added) -
CHANGELOG.md updated (if applicable)
Known Limitations / Technical Debt
None introduced. Historical CampVisit records with attendance = false will accumulate over time — a future cleanup/archival strategy may be worth considering for large-scale deployments.
Additional Notes
- This is a backend-only MR. The corresponding frontend MR handles the unregister UI and calls this endpoint.
- The
registerflag approach was chosen over separate/registerand/unregisterendpoints to keep the API surface lean and mirror how the frontend tracks state.
MR Acceptance Checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

