# Reverse mapping: FHIR Schedule/Slot/Appointment writes flowing back to OscarPro.
# Most of Schedule/Slot is READ-ONLY from the FHIR side — these resources are
# materialised from templates, not stored directly. The booking system's primary
# write path is Appointment creation + Slot.status PATCH.
#
# Symbol legend:
#   **read-only**         — IG-side consumers cannot modify; converter is sole writer
#   **booking-system**    — booking client writes this field on the FHIR server
#   **converter**         — Oscar-side converter writes this on re-emission
#   **no source field**   — field has no OscarPro analogue; lives only in FHIR

Schedule_Writes:
  # Schedule is materialised from scheduletemplate. There is no FHIR-side write path
  # back to scheduletemplate in Phase 1 — the source EMR remains the system of record.
  Schedule.*: "**read-only** — Schedule is converter-emitted; clients SHOULD NOT PATCH or PUT Schedule resources in Phase 1"

Slot_Writes:
  # Slot is also materialised, but Slot.status is the one mutable field — the booking
  # system flips it to busy/busy-tentative/free as part of the booking lifecycle.
  Slot.status: "**booking-system** — PATCH allowed; values 'free', 'busy', 'busy-tentative'. The converter MAY re-emit and overwrite on next sync; booking systems should use If-Match to detect this."
  Slot.overbooked: "**booking-system** — set when an intentional overbook occurs"
  Slot.comment: "**converter** for blockout reasons; **booking-system** may append hold-context notes (rare)"
  Slot.schedule: "**read-only** — never modified after creation"
  Slot.start: "**read-only** — never modified; window is fixed by the template"
  Slot.end: "**read-only** — never modified"
  Slot.identifier: "**read-only**"
  Slot.serviceType: "**read-only** (Phase 1) — could become writable if booking systems need to retag slots"
  Slot.appointmentType: "**read-only** (Phase 1)"

Appointment_Writes:
  # This is the primary write path for booking. Appointment.slot is the NEW field
  # added in IG 1.10.0; existing Appointment fields are unchanged.
  Appointment.slot: "**booking-system** — references the Slot the appointment was booked from. Cardinality 0..* — walk-ins/historical appointments omit. SHOULD be populated by booking clients on new appointments created from a free Slot."
  Appointment.status: "**booking-system** — full lifecycle (proposed → pending → booked → arrived → fulfilled / cancelled / noshow)"
  Appointment.start: "**booking-system** — copied from Slot.start when booking from a Slot"
  Appointment.end: "**booking-system** — copied from Slot.end when booking from a Slot"
  Appointment.participant: "**booking-system** — Patient, PractitionerRole, Location"
  Appointment.serviceType: "**booking-system** — RECOMMENDED to copy from Slot.serviceType but not REQUIRED (independent per profile design)"
  Appointment.appointmentType: "**booking-system** — RECOMMENDED to copy from Slot.appointmentType but not REQUIRED"
  Appointment.reasonCode: "**booking-system**"
  Appointment.requestedPeriod: "**booking-system**"

Write_Back_To_Oscar:
  # When an Appointment is created/updated via the FHIR server, the Oscar-side
  # write-back process must reconcile to the OscarPro appointment table. This is
  # Oscar's existing write-back logic + the new Slot linkage; see converter-contracts.md
  # for the migration spec.
  appointment_create:
    fhir_event: "POST Appointment with .slot[0].reference = Slot/X and .start, .end, .participant[…]"
    oscar_writes:
      - "INSERT row into appointment table with start_time, end_time, provider_no, demographic_no, etc."
      - "Optionally: store Slot reference in an appointment metadata table (Phase 1: out of scope; Slot linkage lives only in FHIR layer)"

  slot_status_busy:
    fhir_event: "PATCH Slot.status = busy (after Appointment booking confirms)"
    oscar_writes: "**no source field** — Slot.status is computed by the converter from appointment-overlay logic; the FHIR-side PATCH is informational until the next converter re-emission. Booking systems should consider Slot.status authoritative *between converter re-emissions* but understand that re-emission will recompute it."

  slot_status_busy_tentative:
    fhir_event: "PATCH Slot.status = busy-tentative (during a hold)"
    oscar_writes: "**no source field** — busy-tentative has no OscarPro analogue. Converter NEVER writes this status. PATCH lives only in the FHIR layer; if the booking system needs hold state to persist across converter re-emissions, it must store hold context out-of-band (not in OscarPro)."

  appointment_cancel:
    fhir_event: "PATCH Appointment.status = cancelled"
    oscar_writes:
      - "UPDATE appointment table: status = 'C' (or equivalent OscarPro cancellation flag)"
      - "Next converter re-emission will see the cancelled appointment and not include it in busy overlay; Slot reverts to free"

# === Concurrency notes ===

Concurrency:
  converter_vs_booking_system:
    risk: "Converter re-emits a Slot's status as 'free' (computed from appointment table) at the same moment the booking system PATCHes 'busy-tentative'."
    mitigation: "Booking system SHOULD use If-Match against the Slot's ETag to detect the race. Phase 1 does NOT enforce optimistic concurrency at the profile level."

  hold_timeout:
    risk: "User abandons booking after starting a hold; busy-tentative slot lingers."
    mitigation: "Booking-system-owned hold-timeout reconciler PATCHes Slot.status back to free after N minutes. Hold duration is a booking-system concern, not represented on the resource."

# === Phase 1 write-back limitations ===

Limitations:
  - "No FHIR-side editing of Slot.start/Slot.end. Slot windows are fixed by the template; if a clinic needs to change its template, that's done in OscarPro and picked up by the next converter run."
  - "No FHIR-side editing of Schedule.actor. Provider/location assignment is a source-system concern."
  - "Slot.status writes from the booking system are not persisted to OscarPro. They live only in the FHIR layer between converter re-emissions."
  - "No bidirectional sync for busy-tentative. OscarPro has no analogue; if a downstream EMR consumer needs visibility into holds, it must query the FHIR server, not the OscarPro DB."
