How to model recurring appointments?
# support
d
Recurring appointments are critical for us to build a behavioral health EHR. ⛔ FHIR V4 and Medplum don't offer ways to model recurring appointments ✍️ ...So instead, we're going off the guidelines in FHIR V6 for inspiration, and plan to model
Appointment.recurrenceTemplate
as an extension. For identifying the original appointment in the series, which has the
recurrenceTemplate
, V6 has an
Appointment.originatingAppointment
field ([docs](https://build.fhir.org/appointment-definitions.html#Appointment.originatingAppointment)) We were initially going to model `originatingAppointment `as an extension, but: ⛔ Extensions can't be searched or indexed on ⛔ The
basedOn
could have been a good candidate, since technically FHIR allows any resource, but Medplum restricts this to ServiceRequest resources only Any guidelines?
f
Hey @Daniel Bennett in what way do you need to be able to search on recurring appointments?
Are you using Slots as well?
d
@finnbergquist thanks for your reply! For an appointment in recurrence series, we want to only store the recurrenceTemplate on the originating appointment, to match FHIR V6 recommendations. This would require looking up the originatingAppointment for any appointment that isn't the first in the series We'll eventually be using slots and modeling practitioner availability
f
Ok got it. I think you are on the right track here. This would require looking up the originatingAppointment for any appointment that isn't the first in the series To address this, on the Appointments in a recurrence series that are not the originating Appointment, you could store a reference to the originating Appointment in the recurring Appointemnt's supportingInformation field. This is searchable with the supporting-info search param.
d
Great idea 👏 we'll go with that!
a
@Daniel Bennett Been following this thread - I've actually built my own behavior health EHR, and I actually went through this exact debate when building recurring appt features for patients. Just be careful... If you're doing the recurring template version for patient appointments, just make sure to have some safeguards for if/when a therapist cancels that first appointment... otherwise poof, there goes your template 😅 Also, breaking up a series mid-way requires complex reference process. IMHO, the template approach for patient appointments might solve problems we don't have in behavioral health (infinite recurrence, complex patterns) while making the actual problems we do have harder (cancellations, modifications, patient visibility).
d
Thanks @albert_wong , great insights! Definitely true that there's some complex logic needed for changes to a series mid-way, we are partially sidestepping that for now by preventing changes to the recurrence sequence, and "deleting" appointments by setting status to
cancelled
instead of hard deleting @finnbergquist I'm finding that the
supportingInformation
field isn't searchable on Medplum - is that expected behavior? I can load all the clinician's appointments into memory and then search from there, if needed, but prefer searching via the API
I spoke too soon. it turns out that FHIR specifies a special naming for this key in queries (
supporting-info
), no idea why they did this, but Medplum faithfully implements it so can't complain: https://www.medplum.com/docs/api/fhir/resources/appointment#search-parameters
@finnbergquist I'm also finding that when I have
supporting-info
as an
include
parameter it doesn't work. Seems like this is not supported? With the below query, I can get the associated "actors" (participants) for the appointment, but not the
supportingInformation
Appointment, which is set to the originating appointment (the one that has the recurrenceTemplate):
Copy code
const searchParams: SearchRequest<Appointment> = {
  resourceType: 'Appointment',
  filters: [
    {
      code: 'practitioner',
      operator: Operator.EQUALS,
      value: getReferenceString(practitioner)
    },
    {
      code: 'date',
      operator: Operator.LESS_THAN,
      value: params.end.toISO() || params.end.toString()
    },
    {
      code: 'end',
      operator: Operator.GREATER_THAN,
      value: params.start.toISO() || params.start.toString()
    }
  ],
  include: [
    {
      resourceType: 'Appointment',
      searchParam: 'actor',
      modifier: 'iterate'
    },
    {
      resourceType: 'Appointment',
      searchParam: 'supporting-info',
      modifier: 'iterate'
    }
  ],
  count: 100
}
f
Can you try this without the 'iterate' modifiers on the include params?
The
iterate
modifier is for recursively traversing through linked resources. See [these docs](https://www.medplum.com/docs/search/includes#iterate-modifier). In this case, it isn't needed because
supporting-info
is a search param on the Appointment resource, not a linked one
d
@finnbergquist I tried that and it still only returns the reference, not the actual object:
Copy code
"supportingInformation": [
      {
        "reference": "Appointment/01982ed2-1dba-754d-acd9-295d879c7392"
      }
    ],
Maybe its just not supported in Medplum's implementation? Since
supporting-info
is a "reference" type search parameter for Appointment, it should be supported according to the FHIR spec: https://hl7.org/fhir/R4/appointment.html#search Ultimately we should probably use the GraphQL library, but its not type-safe 👎 unless we setup graphql codegen, which seems like a big lift
f
It should return the whole resource as an additional entry in the Bundle that is returned by that search
d
Thanks @finnbergquist that was it! I misunderstood how include works. Appreciate you and the whole Medplum team!
149 Views