Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FR] Support for FHIRPatch #68

Open
ZuSe opened this issue Feb 9, 2021 · 6 comments
Open

[FR] Support for FHIRPatch #68

ZuSe opened this issue Feb 9, 2021 · 6 comments

Comments

@ZuSe
Copy link

ZuSe commented Feb 9, 2021

The lib is missing support for proper PATCH operations as defined in the standard: http://hl7.org/implement/standards/fhir/http.html#patch

According to the docs update/save with a given list of fields should use this operation.

Tested with HAPI FHIR 5.2.0

@mkizesov
Copy link
Contributor

mkizesov commented Feb 9, 2021

This feature is already implemented.
Could you provide an example of your code?

@ZuSe
Copy link
Author

ZuSe commented Feb 9, 2021

Hi @mkizesov

thanks for your help. Comes the code:

        client: SyncFHIRClient = get_client(async=False)
        # get or create FHIR object
        try:
            patient: SyncFHIRResource = client.reference('Patient', id=str(user.username)).to_resource()
            modifiedfields = [] #do a PATCH
        except exceptions.ResourceNotFound:
            modifiedfields = None #do a post
            patient = client.resource('Patient', id=str(user.username))

        # set telecom fields
        if any(x in update_fields for x in ["email", "mobile", "phone"]):
            if modifiedfields is not None:
                modifiedfields.append("telecom")
            try:
                # https://github.com/beda-software/fhir-py/issues/66
                getattr(patient, "telecom")
            except KeyError:
                patient.telecom = []

            def update_or_create(system, telelist, entry):
                updated = False
                # update if system already exists in FHIR object
                for i, t in enumerate(telelist):
                    if t["system"] == system:
                        updated = True
                        telelist[i] = entry
                        break
                if not updated:
                    telelist.append(entry)

            if "email" in update_fields:
                update_or_create("email", patient.telecom, entry={
                    "system": 'email',
                    "value": str(user.email),
                    "use": 'home'
                })
            if "mobile" in update_fields:
                update_or_create("sms", patient.telecom, entry={
                    "system": 'sms',
                    "value": str(user.mobile),
                    "use": 'mobile'
                })
            if "phone" in update_fields:
                update_or_create("phone", patient.telecom, entry={
                    "system": 'phone',
                    "value": str(user.phone),
                    "use": 'home'
                })

        if "first_name" in update_fields or "last_name" in update_fields:
            if modifiedfields is not None:
                modifiedfields.append("name")
            try:
                # https://github.com/beda-software/fhir-py/issues/66
                getattr(patient, "name")
            except KeyError:
                patient.name = [{}]
            patient.name[0]["use"] = 'official'
            if "first_name" in update_fields:
                patient.name[0]["given"] = str(user.first_name)
                patient.name[0]["text"] = f'{user.first_name} {patient.name[0].get("family", "")}'
            if "last_name" in update_fields:
                patient.name[0]["family"] = str(user.last_name)
                patient.name[0]["text"] = f'{patient.name[0].get("given", "")} {user.last_name}'
        if "birthdate" in update_fields:
            if modifiedfields is not None:
                modifiedfields.append("birthDate")
            patient.birthDate = user.birthdate.isoformat()
        if "gender" in update_fields:
            if modifiedfields is not None:
                modifiedfields.append("gender")
            patient.gender = user.gender
        if "is_active" in update_fields:
            if modifiedfields is not None:
                modifiedfields.append("active")
            patient.active = user.is_active    
        patient.save(fields=modifiedfields)

So basically the purpose of the code is to update only attributes that have been updated on our side.
What we try achieve is to implement some kind of sync-adapter that keeps the FHIR Server in sync with the client.
However, as many clients write to the server we want to limit the usage of PUT as much as possible ;)

Best
Patrick

@ruscoder
Copy link
Member

ruscoder commented Jun 23, 2021

Hi! Maybe it will worth if we just allow passing not only field names in save, for example:

resource.save(fhirpatch=[{"op": "add", "path": "path expr here", "value": "value to add"}])

It will be more flexible. What do you think? Will it solve the issue?

@ZuSe
Copy link
Author

ZuSe commented Jun 25, 2021

yes, should work. Maybe it makes sense to compute as well.
Basically

  1. Define FHIR related resource by id
  2. change fields via Dot-notation e.g. tmpPatient.name = "ABC"
  3. Save changed/added fields via patch tmpPatient.save(partial_update=True)

For me that's always the nice use case to use patch, when I know that I want to add/change some specific params but try to avoid loading the whole resource in advance and PUT everything back, just for a couple of small changes (and risk that I run into raise conditions because it changed in the meanwhile).

@usr-av
Copy link

usr-av commented Sep 19, 2022

#68 (comment)
is patch operation available ?

@mkizesov
Copy link
Contributor

As I understand, fhir patch is not implemented yet. Only standard http PATCH operation (fhir update) is available using either resource.update(fieldToUpdate="") or resource.save(fields=['fieldsToUpdate']).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants