New feature / Change #8924
Updated by Olivier Bitsch 2 months ago
## Summary FHIR API integration for Appointment and Encounter resources. ## Description As an external EMR system, I need FHIR R4 compliant API endpoints to create appointments and retrieve encounters, enabling interoperability with healthcare systems like OpenEMR. ## Requirements **FHIR Endpoints:** POST /api/fhir/Appointment → Create appointment (returns FHIR Appointment) GET /api/fhir/Appointment → List appointments (returns FHIR Bundle) GET /api/fhir/Appointment/:id → Get appointment (returns FHIR Appointment) PUT /api/fhir/Appointment/:id → Update appointment DELETE /api/fhir/Appointment/:id → Cancel appointment GET /api/fhir/Encounter → List encounters (returns FHIR Bundle) GET /api/fhir/Encounter/:id → Get encounter (returns FHIR Encounter) **FHIR → Internal Model Mapping:** | FHIR Resource | Internal Model | |---------------|----------------| | Appointment | Appointment + Consultation | | Appointment.participant (Patient) | Participant (user, email, phone) | | Appointment.participant (Practitioner) | Participant (doctor) | | Encounter | Consultation | **Appointment Mapping:** | FHIR Field | Internal Field | |------------|----------------| | Appointment.start | Appointment.scheduled_at | | Appointment.end | Appointment.end_expected_at | | Appointment.status | Appointment.status | | Appointment.serviceType | Type (Online/InPerson) | | Appointment.participant[Patient] | Participant (beneficiary) | | Appointment.participant[Practitioner] | Participant (doctor) | | Appointment.reason | Consultation.description | | Appointment.identifier | External reference (store in metadata) | **Encounter Mapping:** | FHIR Field | Internal Field | |------------|----------------| | Encounter.status | Consultation status | | Encounter.period.start | Consultation.created_at | | Encounter.period.end | Consultation.closed_at | | Encounter.appointment | Reference to Appointment | | Encounter.subject | Consultation.beneficiary | | Encounter.participant | Consultation.owned_by (doctor) | **Status Mappings:** | FHIR Appointment | Internal Status | |------------------|-----------------| | proposed | - | | booked | Scheduled | | cancelled | Cancelled | | fulfilled | (completed) | | FHIR Encounter | Internal Status | |----------------|-----------------| | planned | pending | | in-progress | active | | finished | closed | **Request Body Example (Create Appointment):** ```json { "resourceType": "Appointment", "status": "booked", "start": "2025-01-15T10:00:00Z", "end": "2025-01-15T10:30:00Z", "serviceType": [{"coding": [{"code": "online"}]}], "identifier": [{"system": "openemr", "value": "APT-12345"}], "participant": [ { "actor": { "reference": "#patient1", "type": "Patient" }, "status": "accepted" }, { "actor": { "reference": "#practitioner1", "type": "Practitioner" }, "status": "accepted" } } ], "contained": [ { "resourceType": "Patient", "id": "patient1", "name": [{"family": "Doe", "given": ["John"]}], "telecom": [ {"system": "email", "value": "john@example.com"}, {"system": "phone", "value": "+1234567890"} ] ] }, { "resourceType": "Practitioner", "id": "practitioner1", "name": [{"family": "Smith", "given": ["Dr"]}], "telecom": [{"system": "email", "value": "dr.smith@clinic.com"}] } } ] ] } Response (FHIR Appointment): { "resourceType": "Appointment", "id": "123", "status": "booked", "start": "2025-01-15T10:00:00Z", "end": "2025-01-15T10:30:00Z", ... ... } Validation Rules: - Patient participant required with name and contact (email or phone) - Practitioner participant required with email (must exist in system) - Start date required and must be in future - Cannot update after consultation started Search Parameters: - identifier - Search by external system ID - appointment.identifier - Search encounters by appointment ID Acceptance Criteria - POST /fhir/Appointment creates Consultation + Appointment + Participants - POST /fhir/Appointment returns valid FHIR Appointment response - GET /fhir/Appointment returns FHIR Appointment or Bundle - GET /fhir/Encounter returns FHIR Encounter or Bundle - Search by external identifier works - Invalid FHIR body returns 400 with validation errors - Practitioner not in system returns 400 error - Status mappings work bidirectionally - Cannot modify appointment with active consultation Notes - Store original FHIR body for audit/reference ---