コード例 #1
0
def test_invalid_reading_not_created(reading_id, reading_referral_followup,
                                     patient_factory, api_post):
    patient_factory.create(patientId="123")
    # Removed bpSystolic to make the eading invalid
    del reading_referral_followup["bpSystolic"]

    response = api_post(endpoint="/api/readings",
                        json=reading_referral_followup)
    assert response.status_code == 400
    assert crud.read(Reading, readingId=reading_id) is None
    assert crud.read(Referral, readingId=reading_id) is None
    assert crud.read(FollowUp, readingId=reading_id) is None
コード例 #2
0
    def post():
        # Get all patients for this user
        timestamp: int = request.args.get("since", None, type=int)
        if not timestamp:
            abort(400, message="'since' query parameter is required")

        #  ~~~~~~~~~~~~~~~~~~~~~~ new Logic ~~~~~~~~~~~~~~~~~~~~~~~~~~
        json = request.get_json(force=True)
        patients_on_server_chache = set()
        for r in json:
            if r.get("patientId") not in patients_on_server_chache:
                patient_on_server = crud.read(Patient,
                                              patientId=r.get("patientId"))
                if patient_on_server is None:
                    continue
                else:
                    patients_on_server_chache.add(patient_on_server.patientId)

            if crud.read(Reading, readingId=r.get("readingId")):
                continue
            else:
                error_message = readings.validate(r)
                if error_message is not None:
                    abort(400, message=error_message)
                reading = marshal.unmarshal(Reading, r)
                invariant.resolve_reading_invariants(reading)
                crud.create(reading, refresh=True)

        user = util.current_user()
        #     TODO: create custome DB calls for referral and followup

        all_patients = view.patient_view_for_user(user)
        new_readings = []
        new_referral = []
        new_followup = []
        for p in all_patients:
            for r in p["readings"]:
                if r["dateTimeTaken"] > timestamp:
                    new_readings.append(r)
                if (r["referral"] and r["referral"]["dateReferred"] > timestamp
                        and r["dateTimeTaken"] < timestamp):
                    new_referral.append(r["referral"])
                if (r["followup"] and r["followup"]["dateAssessed"] > timestamp
                        and r["dateTimeTaken"] < timestamp):
                    new_followup.append(r["followup"])

        return {
            "total": len(new_readings) + len(new_referral) + len(new_followup),
            "readings": new_readings,
            "newReferralsForOldReadings": new_referral,
            "newFollowupsForOldReadings": new_followup,
        }
コード例 #3
0
    def post():
        json = request.get_json(force=True)
        error_message = patients.validate(json)
        if error_message is not None:
            abort(400, message=error_message)
        patient = marshal.unmarshal(Patient, json)

        if crud.read(Patient, patientId=patient.patientId):
            abort(409, message=f"A patient already exists with id: {patient.patientId}")

        # Resolve invariants and set the creation timestamp for the patient ensuring
        # that both the created and lastEdited fields have the exact same value.
        invariant.resolve_reading_invariants(patient)
        creation_time = get_current_time()
        patient.created = creation_time
        patient.lastEdited = creation_time

        crud.create(patient, refresh=True)

        # Associate the patient with the user who created them
        user = util.current_user()
        assoc.associate_by_user_role(patient, user)

        # If the patient has any readings, and those readings have referrals, we
        # associate the patient with the facilities they were referred to
        for reading in patient.readings:
            referral = reading.referral
            if referral and not assoc.has_association(patient, referral.healthFacility):
                assoc.associate(patient, facility=referral.healthFacility)
                # The associate function performs a database commit, since this will
                # wipe out the patient we want to return we must refresh it.
                data.db_session.refresh(patient)
        return marshal.marshal(patient), 201
コード例 #4
0
    def post(self):
        import api.util as util
        import data.crud as crud
        import service.assoc as assoc
        from models import Patient

        try:
            request_body = _get_request_body()
        except:
            return {"HTTP 400": decoding_error}, 400
        if not request_body["patientId"]:
            return {"HTTP 400": "Patient Id is empty."}, 400

        # Emulate old API functionality with new systems, use of /api/associations is
        # preferred over this method now
        patient = crud.read(Patient, patientId=request_body["patientId"])
        if patient:
            user = util.current_user()
            facility = user.healthFacility
            if not assoc.has_association(patient, facility, user):
                assoc.associate(patient, facility, user)
            else:
                abort(409, message="Duplicate entry")
            return {
                "message": "patient has been added to facility successfully"
            }, 201
        else:
            abort(404, message="This patient does not exist.")
コード例 #5
0
    def post():
        json = request.get_json(force=True)

        # Populate the dateAssessed and healthCareWorkerId fields of the followup
        json["dateAssessed"] = get_current_time()
        user = util.current_user()
        json["healthcareWorkerId"] = user.id

        error_message = assessments.validate(json)
        if error_message is not None:
            abort(400, message=error_message)

        follow_up = marshal.unmarshal(FollowUp, json)

        # Check that reading id which doesn’t reference an existing reading in the database
        reading = crud.read(Reading, readingId=follow_up.readingId)
        if not reading:
            abort(404, message=f"No reading with id {follow_up.readingId}")

        crud.create(follow_up)

        # Creating an assessment also marks any referral attached to the associated
        # reading as "assessed"
        if follow_up.reading.referral:
            follow_up.reading.referral.isAssessed = True
            data.db_session.commit()

        return follow_up.id, 201
コード例 #6
0
def test_update(patient_factory):
    patient_factory.create(patientId="abc", patientName="ABC")

    crud.update(Patient, {"patientName": "CDE"}, patientId="abc")

    query = crud.read(Patient, patientId="abc")
    assert query.patientName == "CDE"
コード例 #7
0
    def get(patient_id: str):

        patient = crud.read(Patient, patientId=patient_id)
        if not patient:
            abort(404, message=f"No patient with id {patient_id}")

        # getting all bpSystolic readings for each month
        bp_systolic = statsCalculation.get_stats_data("bpSystolic", patient.readings)

        # getting all bpDiastolic readings for each month
        bp_diastolic = statsCalculation.get_stats_data("bpDiastolic", patient.readings)

        # getting all heart rate readings for each month
        heart_rate = statsCalculation.get_stats_data("heartRateBPM", patient.readings)

        # getting all traffic lights from day 1 for this patient
        traffic_light_statuses = statsCalculation.get_stats_data(
            "trafficLightStatus", patient.readings
        )

        # putting data into one object now
        data = {
            "bpSystolicReadingsMonthly": bp_systolic,
            "bpDiastolicReadingsMonthly": bp_diastolic,
            "heartRateReadingsMonthly": heart_rate,
            "trafficLightCountsFromDay1": {
                "green": traffic_light_statuses[0],  # dont
                "yellowUp": traffic_light_statuses[1],  # hate
                "yellowDown": traffic_light_statuses[2],  # the
                "redUp": traffic_light_statuses[3],  # magic
                "redDown": traffic_light_statuses[4],  # numbers
            },
        }
        return data
コード例 #8
0
def current_user() -> User:
    """
    Returns the the model for the user making the request.

    :return:
    """
    identity = jwt.get_jwt_identity()
    return crud.read(User, id=identity["userId"])
コード例 #9
0
def test_invalid_facility_not_created(facility_name, health_facility,
                                      api_post):
    # Invalid as healthFacilityName is not there
    del health_facility["healthFacilityName"]

    response = api_post(endpoint="/api/facilities", json=health_facility)
    assert response.status_code == 400
    assert crud.read(HealthFacility, healthFacilityName=facility_name) is None
コード例 #10
0
def test_update_patient_name(patient_factory, api_put):
    patient_id = "64164134514"
    patient_factory.create(patientId=patient_id, patientName="AB")

    response = api_put(endpoint=f"/api/patients/{patient_id}/info",
                       json={"patientName": "CD"})

    assert response.status_code == 200
    assert crud.read(Patient, patientId=patient_id).patientName == "CD"
コード例 #11
0
def test_post_facility(facility_name, health_facility, api_post):
    try:
        response = api_post(endpoint="/api/facilities", json=health_facility)
        assert response.status_code == 201
        assert crud.read(HealthFacility,
                         healthFacilityName=facility_name) is not None

    finally:
        crud.delete_by(HealthFacility, healthFacilityName=facility_name)
コード例 #12
0
    def post():
        json: dict = request.get_json(force=True)
        error_message = associations.validate(json)
        if error_message is not None:
            abort(400, message=error_message)

        patient_id = json.get("patientId")
        facility_name = json.get("healthFacilityName")
        user_id = json.get("userId")

        patient = crud.read(Patient, patientId=patient_id)
        if not patient:
            abort(400, message=f"No patient exists with id: {patient_id}")

        if facility_name:
            facility = crud.read(HealthFacility,
                                 healthFacilityName=facility_name)
            if not facility:
                abort(400,
                      message=f"No health facility with name: {facility_name}")
        else:
            facility = None

        if user_id:
            user = crud.read(User, id=user_id)
            if not user:
                abort(400, message=f"No user with id: {user_id}")
            #     if user exists but no health facility then assign the patient to the user's health facility
            facility = user.healthFacility
        else:
            user = None

        if not facility_name and not user_id:
            # If neither facility_name or user_id are present in the request, create a
            # associate patient with the current user's health facility
            user = util.current_user()
            assoc.associate(patient, user.healthFacility, user)
        else:
            # Otherwise, simply associate the provided models together
            if not assoc.has_association(patient, facility, user):
                assoc.associate(patient, facility, user)

        return {}, 201
コード例 #13
0
def test_create_patient_with_nested_readings(database, api_post):
    patient_id = "5390160146141"
    reading_ids = [
        "65acfe28-b0d6-4a63-a484-eceb3277fb4e",
        "90293637-d763-494a-8cc7-85a88d023f3e",
    ]
    p = __make_patient(patient_id, reading_ids)
    response = api_post(endpoint="/api/patients", json=p)
    database.session.commit()

    try:
        assert response.status_code == 201
        assert crud.read(Patient, patientId=patient_id) is not None

        for r in reading_ids:
            reading = crud.read(Reading, readingId=r)
            assert reading is not None
            assert reading.trafficLightStatus == TrafficLightEnum.GREEN
    finally:
        for r in reading_ids:
            crud.delete_by(Reading, readingId=r)
        crud.delete_by(Patient, patientId=patient_id)
コード例 #14
0
    def put(patient_id: str):
        json = request.get_json(force=True)
        error_message = patients.validate_put_request(json, patient_id)
        if error_message is not None:
            abort(400, message=error_message)

        # If the inbound JSON contains a `base` field then we need to check if it is the
        # same as the `lastEdited` field of the existing patient. If it is then that
        # means that the patient has not been edited on the server since this inbound
        # patient was last synced and we can apply the changes. If they are not equal,
        # then that means the patient has been edited on the server after it was last
        # synced with the client. In these cases, we reject the changes for the client.
        #
        # You can think of this like aborting a git merge due to conflicts.
        base = json.get("base")
        if base:
            last_edited = crud.read(Patient, patientId=patient_id).lastEdited
            if base != last_edited:
                abort(409,
                      message="Unable to merge changes, conflict detected")

            # Delete the `base` field once we are done with it as to not confuse the
            # ORM as there is no "base" column in the database for patients.
            del json["base"]

        crud.update(Patient, json, patientId=patient_id)
        patient = crud.read(Patient, patientId=patient_id)

        # Update the patient's lastEdited timestamp only if there was no `base` field
        # in the request JSON. If there was then that means that this edit happened some
        # time in the past and is just being synced. In this case we want to keep the
        # `lastEdited` value which is present in the request.
        if not base:
            patient.lastEdited = get_current_time()
            data.db_session.commit()
            data.db_session.refresh(
                patient)  # Need to refresh the patient after commit

        return marshal.marshal(patient)
コード例 #15
0
def test_post_reading_with_referral_and_followup(reading_id,
                                                 reading_referral_followup,
                                                 patient_factory, api_post):
    patient_factory.create(patientId="123")
    try:
        response = api_post(endpoint="/api/readings",
                            json=reading_referral_followup)
        assert response.status_code == 201
        assert crud.read(Reading, readingId=reading_id) is not None
        assert crud.read(Referral, readingId=reading_id) is not None
        assert crud.read(FollowUp, readingId=reading_id) is not None

        # Reading should have it's traffic light computed
        reading = crud.read(Reading, readingId=reading_id)
        assert reading.trafficLightStatus.value == "GREEN"

        # Referral should be marked as assessed
        referral = crud.read(Referral, readingId=reading_id)
        assert referral.isAssessed
    finally:
        crud.delete_by(FollowUp, readingId=reading_id)
        crud.delete_by(Referral, readingId=reading_id)
        crud.delete_by(Reading, readingId=reading_id)
コード例 #16
0
def test_update_patient_with_base(patient_factory, api_put):
    patient_id = "45642677524614"
    patient_factory.create(patientId=patient_id, patientName="AB", lastEdited=5)

    json = {
        "patientName": "CD",
        "lastEdited": 6,
        "base": 5,  # base == lastEdited -> request is accepted
    }
    response = api_put(endpoint=f"/api/patients/{patient_id}/info", json=json)

    assert response.status_code == 200
    patient = crud.read(Patient, patientId=patient_id)
    assert patient.patientName == "CD"
    assert patient.lastEdited == 6
コード例 #17
0
def test_update_patient_abort_due_to_conflict(patient_factory, api_put):
    patient_id = "45642677524614"
    patient_factory.create(patientId=patient_id, patientName="AB", lastEdited=7)

    json = {
        "patientName": "CD",
        "lastEdited": 6,
        "base": 5,  # base != lastEdited -> request is rejected
    }
    response = api_put(endpoint=f"/api/patients/{patient_id}/info", json=json)

    assert response.status_code == 409
    patient = crud.read(Patient, patientId=patient_id)
    assert patient.patientName == "AB"
    assert patient.lastEdited == 7
コード例 #18
0
    def post():

        # Get key-value pairs from parser and remove pairs with a None value
        data = Root.parser.parse_args()
        data = util.filterPairsWithNone(data)

        # Create a DB Model instance for the new facility and load into DB
        facility = marshal.unmarshal(HealthFacility, data)
        crud.create(facility)

        # Get back a dict for return
        facilityDict = marshal.marshal(
            crud.read(HealthFacility,
                      healthFacilityName=data["healthFacilityName"]))
        return facilityDict, 201
コード例 #19
0
def test_invalid_patient_not_created(patient_factory, api_post):
    patient_id = "48375354"
    # invalid as patientName is missing
    patient = {
        "patientId": patient_id,
        "patientSex": "FEMALE",
        "isPregnant": False,
        "zone": "37",
        "villageNumber": "37",
        "created": 1,
        "lastEdited": 5,
        "base": 5,
        "readings": [],
    }
    response = api_post(endpoint="/api/patients", json=patient)
    assert response.status_code == 400
    assert crud.read(Patient, patientId=patient_id) is None
コード例 #20
0
    def post():
        json = request.get_json(force=True)
        error_message = readings.validate(json)
        if error_message is not None:
            abort(400, message=error_message)

        reading = marshal.unmarshal(Reading, json)

        if crud.read(Reading, readingId=reading.readingId):
            abort(
                409,
                message=f"A reading already exists with id: {reading.readingId}"
            )

        invariant.resolve_reading_invariants(reading)
        crud.create(reading, refresh=True)
        return marshal.marshal(reading), 201
コード例 #21
0
    def _do_create(self, **kwargs) -> Any:
        import data
        from config import flask_bcrypt
        from models import User, Role

        d = dict(**kwargs)
        role_name = d["role"]
        del d["role"]  # not an actual user field so delete if from the args

        # Hash the user's password so that they can login
        d["password"] = flask_bcrypt.generate_password_hash(d["password"])

        user = marshal.unmarshal(User, d)
        crud.create(user)
        role = crud.read(Role, name=role_name)
        user.roleIds = [role]
        data.db_session.commit()
        return user
コード例 #22
0
    def post(assessment_id: int):
        if not assessment_id:
            abort(404, message=f"Assessment id is required")
        json = request.get_json(force=True)

        json["dateAssessed"] = get_current_time()

        # get current UserID
        user = util.current_user()
        json["healthcareWorkerId"] = user.id

        assessment = crud.read(FollowUp, id=assessment_id)
        if not assessment:
            abort(404, message=f"No assessment with id {assessment_id}")

        json["readingId"] = assessment.readingId

        error_message = assessments.validate(json)
        if error_message is not None:
            abort(400, message=error_message)

        crud.update(FollowUp, json, id=assessment.id)

        return assessment.id, 201
コード例 #23
0
 def get(patient_id: str):
     patient = crud.read(Patient, patientId=patient_id)
     return [marshal.marshal(r) for r in patient.readings]
コード例 #24
0
def test_read(patient_factory):
    expected = patient_factory.create(patientId="abc", patientName="ABC")
    actual = crud.read(Patient, patientId="abc")
    assert actual == expected
コード例 #25
0
    def get(assessment_id: int):
        follow_up = crud.read(FollowUp, id=assessment_id)
        if not follow_up:
            abort(404, message=f"No assessment with id {id}")

        return marshal.marshal(follow_up)
コード例 #26
0
def test_get_mobile_patient(database, api_post, api_get):
    patient_ids = []
    reading_ids = []
    try:
        p = __make_patient("222266667",
                           ["893ddaad-1ebd-46fb-928b-ad0640115aa1"])
        patient_ids.append("222266667")
        reading_ids.append("893ddaad-1ebd-46fb-928b-ad0640115aa1")
        response = api_post(endpoint="/api/patients", json=p)
        database.session.commit()
        assert response.status_code == 201

        # Make the patient IDs so that they're on both sides of the patient IDs.
        p = __make_full_patient("9999",
                                ["7f60bbb3-c49d-425f-825c-681c8330b61d"])
        patient_ids.append("9999")
        reading_ids.append("7f60bbb3-c49d-425f-825c-681c8330b61d")
        response = api_post(endpoint="/api/patients", json=p)
        database.session.commit()
        assert response.status_code == 201

        # Make the patient IDs so that they're on both sides of the patient IDs
        p = __make_full_patient("999955551",
                                ["978e870e-c542-428a-a8bf-dabb0e52bff3"])
        patient_ids.append("999955551")
        reading_ids.append("978e870e-c542-428a-a8bf-dabb0e52bff3")
        response = api_post(endpoint="/api/patients", json=p)
        database.session.commit()
        assert response.status_code == 201

        for p in patient_ids:
            patient = crud.read(Patient, patientId=p)
            assert patient is not None

        # Add a more fleshed-out reading to the first patient.
        reading = __make_reading(
            reading_id="123dabdd-5des-7ufh-23fd-qd4308143651",
            patient_id=patient_ids[0])
        reading_ids.append("123dabdd-5des-7ufh-23fd-qd4308143651")
        reading_response = api_post(endpoint="/api/readings", json=reading)
        database.session.commit()
        assert reading_response.status_code == 201

        # Add a more minimal reading to the first patient.
        reading = __make_reading_no_extra_vitals(
            reading_id="526292b7-53d0-4e7e-8a96-f66f061477ff",
            patient_id=patient_ids[0])
        reading_ids.append("526292b7-53d0-4e7e-8a96-f66f061477ff")
        reading_response = api_post(endpoint="/api/readings", json=reading)
        database.session.commit()
        assert reading_response.status_code == 201

        # Add another fleshed-out reading to the first patient.
        reading = __make_reading(
            reading_id="2ab4f830-3cc0-4e98-bff3-174a9dcc630a",
            patient_id=patient_ids[0])
        reading_ids.append("2ab4f830-3cc0-4e98-bff3-174a9dcc630a")
        reading_response = api_post(endpoint="/api/readings", json=reading)
        database.session.commit()
        assert reading_response.status_code == 201

        for r in reading_ids:
            reading = crud.read(Reading, readingId=r)
            assert reading is not None

        # Get all the patients from /api/mobile/patients.
        responseMobile = api_get(endpoint="/api/mobile/patients")
        assert responseMobile.status_code == 200

        # Setup an error message to return when an assert fails.
        # Note: Since this is usually tested with the test seed data, there will
        # be more than just 1 patient here.
        patient_number_info = (
            f"There were {len(responseMobile.json())} patients " +
            "returned by api/mobile/patients. Dumping them all now:\n" +
            pformat(responseMobile.json(), width=48) + "\n" +
            "========================================================")

        # Loop through every single patient in the database.
        # For every patient in the database (as admin user, /api/mobile/patients returns
        # all the patients), get the patient info from the /api/patients/:id endpont
        # and then determine if they match.
        for patient_from_mobile_patients in responseMobile.json():
            patient_id = patient_from_mobile_patients["patientId"]
            # Validate that the GET requests for /api/patients/{patient_id} and
            # /api/mobile/patients give back the same information.
            # We first validate that the patient info returned is consistent.

            # Get the patient from the /api/patients/:id endpoint.
            response_patients_get = api_get(
                endpoint=f"/api/patients/{patient_id}")
            assert response_patients_get.status_code == 200
            patient_from_patients_api = response_patients_get.json()

            # Check that both results are basically equal.
            __assert_dicts_are_equal(
                patient_from_mobile_patients,
                patient_from_patients_api,
                f"patient {patient_id} from api/mobile/patients",
                f"patient {patient_id} from api/patients/:id",
                other_error_messages=patient_number_info,
                # Validate the readings later.
                ignored_keys=["readings"],
            )

            # Validate the readings now. We check that they both have the same readings.
            # Loop through both of them in case one readings list is different from the other.
            for readingFromMobile in patient_from_mobile_patients["readings"]:
                # From the reading from the api/mobile/patients, find the corresponding reading
                # from the api/patients/:id endpoint
                current_reading_id = readingFromMobile["readingId"]
                readingFromNormalApi = [
                    r for r in patient_from_patients_api["readings"]
                    if r["readingId"] == current_reading_id
                ][0]
                # Check that they give the exact same information.
                __assert_dicts_are_equal(
                    readingFromMobile,
                    readingFromNormalApi,
                    f"reading {current_reading_id} from api/mobile/patients",
                    f"reading {current_reading_id} from api/patients/:id",
                    other_error_messages=patient_number_info,
                    ignored_keys=["userId"],
                )
            for readingFromNormalApi in patient_from_patients_api["readings"]:
                # From the reading from the api/patients/:id, find the corresponding reading
                # from the api/mobile/patients endpoint
                current_reading_id = readingFromNormalApi["readingId"]
                readingFromMobile = [
                    r for r in patient_from_mobile_patients["readings"]
                    if r["readingId"] == current_reading_id
                ][0]
                # Check that they give the exact same information.
                __assert_dicts_are_equal(
                    readingFromMobile,
                    readingFromNormalApi,
                    f"reading {current_reading_id} from api/mobile/patients",
                    f"reading {current_reading_id} from api/patients/:id",
                    other_error_messages=patient_number_info,
                    ignored_keys=["userId"],
                )

    finally:
        for r in reading_ids:
            crud.delete_by(Reading, readingId=r)
        for p in patient_ids:
            crud.delete_by(Patient, patientId=p)
コード例 #27
0
    def get(referral_id: int):
        referral = crud.read(Referral, id=referral_id)
        if not referral:
            abort(404, message=f"No referral with id {id}")

        return marshal.marshal(referral)
コード例 #28
0
    def get(reading_id: str):
        reading = crud.read(Reading, readingId=reading_id)
        if not reading:
            abort(404, message=f"No reading with id {reading_id}")

        return marshal.marshal(reading)
コード例 #29
0
 def get(patient_id: str):
     patient = crud.read(Patient, patientId=patient_id)
     if not patient:
         abort(404, message=f"No patient with id {patient_id}")
     return marshal.marshal(patient)
コード例 #30
0
    def post():
        # Get all patients for this user
        user = util.current_user()
        timestamp: int = request.args.get("since", None, type=int)
        if not timestamp:
            abort(400, message="'since' query parameter is required")

        patients_to_be_added: [Patient] = []
        #  ~~~~~~~~~~~~~~~~~~~~~~ new Logic ~~~~~~~~~~~~~~~~~~~~~~~~~~
        json = request.get_json(force=True)
        for p in json:
            patient_on_server = crud.read(Patient,
                                          patientId=p.get("patientId"))
            if patient_on_server is None:
                error_message = patients.validate(p)
                if error_message is not None:
                    abort(400, message=error_message)

                patient = marshal.unmarshal(Patient, p)
                # # Resolve invariants and set the creation timestamp for the patient ensuring
                # # that both the created and lastEdited fields have the exact same value.
                invariant.resolve_reading_invariants_mobile(patient)
                creation_time = get_current_time()
                patient.created = creation_time
                patient.lastEdited = creation_time
                patients_to_be_added.append(patient)
            else:
                if (int(patient_on_server.lastEdited) < int(
                        p.get("lastEdited")) < timestamp):
                    if p.get("base"):
                        if p.get("base") != p.get("lastEdited"):
                            abort(
                                409,
                                message=
                                "Unable to merge changes, conflict detected",
                            )
                        del p["base"]

                    p["lastEdited"] = get_current_time()
                    crud.update(Patient, p, patientId=p["patientId"])
                #     TODO: revisit association logic
                if not assoc.has_association(patient_on_server, user=user):
                    assoc.associate(patient_on_server, user.healthFacility,
                                    user)

        # update association
        if patients_to_be_added:
            crud.create_all_patients(patients_to_be_added)
            for new_patient in patients_to_be_added:
                #     TODO: revisit association logic
                if not assoc.has_association(new_patient, user=user):
                    assoc.associate(new_patient, user.healthFacility, user)

        # read all the patients from the DB
        #     TODO: optimize to get only patients
        all_patients = view.patient_view_for_user(user)
        all_patients_edited_or_new = [
            p for p in all_patients if p["lastEdited"] > timestamp
        ]

        #  ~~~~~~~~~~~~~~~~~ old logic ~~~~~~~~~~~~~~~~~~~~
        # New patients are patients who are created after the timestamp
        # new_patients = [
        #     p["patientId"] for p in all_patients if p["created"] > timestamp
        # ]

        # Edited patients are patients who were created before the timestamp but
        # edited after it
        # edited_patients = [
        #     p["patientId"]
        #     for p in all_patients
        #     if p["created"] < p["lastEdited"]
        #     and p["created"] <= timestamp < p["lastEdited"]
        # ]

        # New readings created after the timestamp for patients who where created before
        # the timestamp
        # readings = []

        # New followups which were created after the timestamp for readings which were
        # created before the timestamp
        # followups = []
        #
        # for p in all_patients:
        #     for r in p["readings"]:
        #         r_time = int(r["dateTimeTaken"])
        #         if p["created"] <= timestamp < r_time:
        #             readings.append(r["readingId"])
        #
        #         if r["followup"] and r_time < timestamp < int(
        #             r["followup"]["dateAssessed"]
        #         ):
        #             followups.append(r["followup"]["id"])

        return {
            "total": len(all_patients_edited_or_new),
            "patients": all_patients_edited_or_new,
        }