|pypi| |actions| |codecov| |downloads|
edc-appointment
---------------
This module works closely with ``edc_visit_tracking`` and ``edc_visit_schedule``.
Subject data is collected on predefined timepoints. We describe these data collection timepoints in a ``visit_schedule`` as provided by ``edc-visit-schedule``. In ``edc-appointment`` timepoints are represented by appointments. ``edc-appointment`` provides classes for creating and managing appointments.
See also ``edc-visit-schedule``.
AppointmentModelMixin
+++++++++++++++++++++
A model mixin for the Appointment model. Each project may have one appointment model. For example:
.. code-block:: python
class Appointment(AppointmentModelMixin, RequiresConsentModelMixin, BaseUuidModel):
class Meta(AppointmentModelMixin.Meta):
consent_model = 'edc_example.subjectconsent'
app_label = 'edc_example'
Appointment is a required foreignkey for the visit report
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
The ``Appointment`` model is a required foreignkey for the visit report. Be sure to set ``on_delete=PROTECT``.
.. code-block:: python
class SubjectVisit(VisitModelMixin, OffstudyMixin, CreatesMetadataModelMixin,
RequiresConsentModelMixin, BaseUuidModel):
appointment = models.OneToOneField(Appointment, on_delete=PROTECT)
objects = VisitModelManager()
class Meta(VisitModelMixin.Meta):
consent_model = 'edc_example.subjectconsent'
app_label = 'edc_example'
CreatesAppointmentsModelMixin
+++++++++++++++++++++++++++++
A model mixin for the model that triggers the creation of appointments when the model is saved. This is typically an enrollment model.
Adds the model field ``facility``. The value of field ``facility`` tells the ``CreateAppointmentsMixin`` to create appointments for the subject on dates that are available at the ``facility``.
.. code-block:: python
class Enrollment(EnrollmentModelMixin, CreateAppointmentsMixin,
RequiresConsentModelMixin, BaseUuidModel):
class Meta(EnrollmentModelMixin.Meta):
visit_schedule_name = 'subject_visit_schedule.schedule1'
consent_model = 'edc_example.subjectconsent'
app_label = 'edc_example'
When ``Enrollment`` declared above is saved, one appointment will be created for the subject for each ``visit`` in schedule ``schedule1`` of visit_schedule ``subject_visit_schedule``.
Note: the value for ``facility`` must be provided by the user, either through the form interface or programmatically.
Customizing appointment scheduling by ``Facility``
++++++++++++++++++++++++++++++++++++++++++++++++++
see ``edc_facility``
Available Appointment Model Manager Methods
===========================================
The ``Appointment`` model is declared with ``AppointmentManager``. It has several useful methods.
first_appointment() last_appointment()
++++++++++++++++++++++++++++++++++++++
Returns the first (or last) appointment. If just the ``subject_identifier`` is provided, the first appointment of the protocol for the subject is returned. To be more specific, provide ``{subject_identifier=subject_identifier, visit_schedule_name=visit_schedule_name}``.
To be even more specific, ``{subject_identifier=subject_identifier, visit_schedule_name=visit_schedule_name, schedule_name=schedule_name}``.
The most common usage is to just provide these values with an appointment instance:
.. code-block:: python
first_appointment = Appointment.objects.first_appointment(appointment=appointment)
next_appointment() previous_appointment()
+++++++++++++++++++++++++++++++++++++++++
The next and previous appointment are relative to the schedule and a visit_code within that schedule. If next is called on the last appointment in the sequence ``None`` is returned. If previous is called on the first appointment in the sequence ``None`` is returned.
For example, in a sequence of appointment 1000, 2000, 3000, 4000:
.. code-block:: python
>>> appointment.visit_code
1000
>>> next_appointment = Appointment.objects.next_appointment(appointment=appointment)
>>> next_appointment.visit_code
2000
But you can also pass an appointment instance and pass the visit code:
.. code-block:: python
>>> appointment.visit_code
1000
>>> next_appointment = Appointment.objects.next_appointment(
appointment=appointment, visit_code=3000)
>>> next_appointment.visit_code
4000
If you ask for the next appointment from the last, ``None`` is returned:
.. code-block:: python
>>> appointment.visit_code
4000
>>> next_appointment = Appointment.objects.next_appointment(
appointment=appointment, visit_code=3000)
>>> next_appointment.visit_code
AttributeError: 'NoneType' object has no attribute 'visit_code'
The ``previous_appointment`` acts as expected:
.. code-block:: python
>>> appointment.visit_code
1000
>>> previous_appointment = Appointment.objects.previous_appointment(appointment=appointment)
>>> previous_appointment.visit_code
AttributeError: 'NoneType' object has no attribute 'visit_code'
delete_for_subject_after_date()
+++++++++++++++++++++++++++++++
This method will delete all appointments for a subject after a given datetime. See also ``edc-offstudy``.
``Appointment`` is usually a foreignkey of a visit model. It's important when using this method to ensure that when declaring ``Appointment`` as a foreignkey you explicitly set ``on_delete=PROTECT``. If you don't, the deletion will cascade to other related instances -- and that's bad.
.. code-block:: python
appointment = models.OneToOneField(Appointment, on_delete=PROTECT)
Allowing appointments to be skipped using SKIPPED_APPT
++++++++++++++++++++++++++++++++++++++++++++++++++++++
Set ``settings.EDC_APPOINTMENT_ALLOW_SKIPPED_APPT_USING`` to a list of tuples .. [(lower_label, field_name), ...]. The default is ``[]``::
EDC_APPOINTMENT_ALLOW_SKIPPED_APPT_USING = [("edc_appointment_app.nextappointment", "appt_date")]
When set, options to skip the appointment will be available on the Appointment form.
Note:
This option does not make sense for longitudinal trials following a protocol defined schedule. However
if part of the follow up is driven by routine care, for example, where patients do not follow a strict
schedule, then it may be useful.
Using a CRF to record the next appointment date
+++++++++++++++++++++++++++++++++++++++++++++++
For routine care, the next appointment date is not set by the protocol. The EDC will create appointments
according to the visit schedule as usual, but the dates will be approximate. You can administer a CRF at the
end of each visit to capture the next appointment date. A signal will update the appointment
that best matches the date given. Use this together with SKIPPED_APPT (see above).
Set ``settings.EDC_APPOINTMENT_MAX_MONTHS_TO_NEXT_APPT`` to a limit the number of months ahead for next appointment date::
EDC_APPOINTMENT_MAX_MONTHS_TO_NEXT_APPT = 6 # default
.. code-block:: python
# model.py
class NextAppointmentCrf(NextAppointmentCrfModelMixin, CrfModelMixin, BaseUuidModel):
class Meta(CrfModelMixin.Meta, BaseUuidModel.Meta):
verbose_name = "Next Appointment"
verbose_name_plural = "Next Appointments"
# forms.py
class NextAppointmentCrfForm(NextAppointmentCrfModelFormMixin, CrfModelFormMixin, forms.ModelForm):
form_validator_cls = NextAppointmentCrfFormValidator
class Meta:
model = NextAppointmentCrf
fields = "__all__"
# admin.py
@admin.register(NextAppointmentCrf, site=intecomm_subject_admin)
class NextAppointmentCrfAdmin(NextAppointmenCrftModelAdminMixin, CrfModelAdmin):
form = NextAppointmentCrfForm
.. |pypi| image:: https://img.shields.io/pypi/v/edc-appointment.svg
:target: https://pypi.python.org/pypi/edc-appointment
.. |actions| image:: https://github.com/clinicedc/edc-appointment/actions/workflows/build.yml/badge.svg
:target: https://github.com/clinicedc/edc-appointment/actions/workflows/build.yml
.. |codecov| image:: https://codecov.io/gh/clinicedc/edc-appointment/branch/develop/graph/badge.svg
:target: https://codecov.io/gh/clinicedc/edc-appointment
.. |downloads| image:: https://pepy.tech/badge/edc-appointment
:target: https://pepy.tech/project/edc-appointment
Raw data
{
"_id": null,
"home_page": "https://github.com/clinicedc/edc-appointment",
"name": "edc-appointment",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.12",
"maintainer_email": null,
"keywords": "django appointments data collection clinicedc clinical trials",
"author": "Erik van Widenfelt",
"author_email": "ew2789@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/f0/cc/1625bec96d9740bbe9e1746246ef727d6d840cb105c08b69c1c27d904da8/edc_appointment-0.4.33.tar.gz",
"platform": null,
"description": "|pypi| |actions| |codecov| |downloads|\n\nedc-appointment\n---------------\n\nThis module works closely with ``edc_visit_tracking`` and ``edc_visit_schedule``.\n\nSubject data is collected on predefined timepoints. We describe these data collection timepoints in a ``visit_schedule`` as provided by ``edc-visit-schedule``. In ``edc-appointment`` timepoints are represented by appointments. ``edc-appointment`` provides classes for creating and managing appointments.\n\nSee also ``edc-visit-schedule``.\n\n\nAppointmentModelMixin\n+++++++++++++++++++++\n\nA model mixin for the Appointment model. Each project may have one appointment model. For example:\n\n.. code-block:: python\n\n class Appointment(AppointmentModelMixin, RequiresConsentModelMixin, BaseUuidModel):\n\n class Meta(AppointmentModelMixin.Meta):\n consent_model = 'edc_example.subjectconsent'\n app_label = 'edc_example'\n\n\nAppointment is a required foreignkey for the visit report\n+++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\nThe ``Appointment`` model is a required foreignkey for the visit report. Be sure to set ``on_delete=PROTECT``.\n\n.. code-block:: python\n\n class SubjectVisit(VisitModelMixin, OffstudyMixin, CreatesMetadataModelMixin,\n RequiresConsentModelMixin, BaseUuidModel):\n\n appointment = models.OneToOneField(Appointment, on_delete=PROTECT)\n\n objects = VisitModelManager()\n\n class Meta(VisitModelMixin.Meta):\n consent_model = 'edc_example.subjectconsent'\n app_label = 'edc_example'\n\n\nCreatesAppointmentsModelMixin\n+++++++++++++++++++++++++++++\n\nA model mixin for the model that triggers the creation of appointments when the model is saved. This is typically an enrollment model.\n\nAdds the model field ``facility``. The value of field ``facility`` tells the ``CreateAppointmentsMixin`` to create appointments for the subject on dates that are available at the ``facility``.\n\n.. code-block:: python\n\n class Enrollment(EnrollmentModelMixin, CreateAppointmentsMixin,\n RequiresConsentModelMixin, BaseUuidModel):\n\n class Meta(EnrollmentModelMixin.Meta):\n visit_schedule_name = 'subject_visit_schedule.schedule1'\n consent_model = 'edc_example.subjectconsent'\n app_label = 'edc_example'\n\nWhen ``Enrollment`` declared above is saved, one appointment will be created for the subject for each ``visit`` in schedule ``schedule1`` of visit_schedule ``subject_visit_schedule``.\n\nNote: the value for ``facility`` must be provided by the user, either through the form interface or programmatically.\n\n\nCustomizing appointment scheduling by ``Facility``\n++++++++++++++++++++++++++++++++++++++++++++++++++\n\nsee ``edc_facility``\n\n\nAvailable Appointment Model Manager Methods\n===========================================\n\nThe ``Appointment`` model is declared with ``AppointmentManager``. It has several useful methods.\n\n\nfirst_appointment() last_appointment()\n++++++++++++++++++++++++++++++++++++++\n\nReturns the first (or last) appointment. If just the ``subject_identifier`` is provided, the first appointment of the protocol for the subject is returned. To be more specific, provide ``{subject_identifier=subject_identifier, visit_schedule_name=visit_schedule_name}``.\nTo be even more specific, ``{subject_identifier=subject_identifier, visit_schedule_name=visit_schedule_name, schedule_name=schedule_name}``.\n\nThe most common usage is to just provide these values with an appointment instance:\n\n.. code-block:: python\n\n first_appointment = Appointment.objects.first_appointment(appointment=appointment)\n\n\nnext_appointment() previous_appointment()\n+++++++++++++++++++++++++++++++++++++++++\n\nThe next and previous appointment are relative to the schedule and a visit_code within that schedule. If next is called on the last appointment in the sequence ``None`` is returned. If previous is called on the first appointment in the sequence ``None`` is returned.\n\nFor example, in a sequence of appointment 1000, 2000, 3000, 4000:\n\n.. code-block:: python\n\n >>> appointment.visit_code\n 1000\n >>> next_appointment = Appointment.objects.next_appointment(appointment=appointment)\n >>> next_appointment.visit_code\n 2000\n\n\nBut you can also pass an appointment instance and pass the visit code:\n\n.. code-block:: python\n\n >>> appointment.visit_code\n 1000\n >>> next_appointment = Appointment.objects.next_appointment(\n appointment=appointment, visit_code=3000)\n >>> next_appointment.visit_code\n 4000\n\n\nIf you ask for the next appointment from the last, ``None`` is returned:\n\n.. code-block:: python\n\n >>> appointment.visit_code\n 4000\n >>> next_appointment = Appointment.objects.next_appointment(\n appointment=appointment, visit_code=3000)\n >>> next_appointment.visit_code\n AttributeError: 'NoneType' object has no attribute 'visit_code'\n\n\nThe ``previous_appointment`` acts as expected:\n\n.. code-block:: python\n\n >>> appointment.visit_code\n 1000\n >>> previous_appointment = Appointment.objects.previous_appointment(appointment=appointment)\n >>> previous_appointment.visit_code\n AttributeError: 'NoneType' object has no attribute 'visit_code'\n\n\ndelete_for_subject_after_date()\n+++++++++++++++++++++++++++++++\n\nThis method will delete all appointments for a subject after a given datetime. See also ``edc-offstudy``.\n\n``Appointment`` is usually a foreignkey of a visit model. It's important when using this method to ensure that when declaring ``Appointment`` as a foreignkey you explicitly set ``on_delete=PROTECT``. If you don't, the deletion will cascade to other related instances -- and that's bad.\n\n.. code-block:: python\n\n appointment = models.OneToOneField(Appointment, on_delete=PROTECT)\n\nAllowing appointments to be skipped using SKIPPED_APPT\n++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\nSet ``settings.EDC_APPOINTMENT_ALLOW_SKIPPED_APPT_USING`` to a list of tuples .. [(lower_label, field_name), ...]. The default is ``[]``::\n\n EDC_APPOINTMENT_ALLOW_SKIPPED_APPT_USING = [(\"edc_appointment_app.nextappointment\", \"appt_date\")]\n\nWhen set, options to skip the appointment will be available on the Appointment form.\n\nNote:\n This option does not make sense for longitudinal trials following a protocol defined schedule. However\n if part of the follow up is driven by routine care, for example, where patients do not follow a strict\n schedule, then it may be useful.\n\nUsing a CRF to record the next appointment date\n+++++++++++++++++++++++++++++++++++++++++++++++\n\nFor routine care, the next appointment date is not set by the protocol. The EDC will create appointments\naccording to the visit schedule as usual, but the dates will be approximate. You can administer a CRF at the\nend of each visit to capture the next appointment date. A signal will update the appointment\nthat best matches the date given. Use this together with SKIPPED_APPT (see above).\n\nSet ``settings.EDC_APPOINTMENT_MAX_MONTHS_TO_NEXT_APPT`` to a limit the number of months ahead for next appointment date::\n\n EDC_APPOINTMENT_MAX_MONTHS_TO_NEXT_APPT = 6 # default\n\n.. code-block:: python\n\n # model.py\n class NextAppointmentCrf(NextAppointmentCrfModelMixin, CrfModelMixin, BaseUuidModel):\n\n class Meta(CrfModelMixin.Meta, BaseUuidModel.Meta):\n verbose_name = \"Next Appointment\"\n verbose_name_plural = \"Next Appointments\"\n\n\n # forms.py\n class NextAppointmentCrfForm(NextAppointmentCrfModelFormMixin, CrfModelFormMixin, forms.ModelForm):\n form_validator_cls = NextAppointmentCrfFormValidator\n\n class Meta:\n model = NextAppointmentCrf\n fields = \"__all__\"\n\n\n # admin.py\n @admin.register(NextAppointmentCrf, site=intecomm_subject_admin)\n class NextAppointmentCrfAdmin(NextAppointmenCrftModelAdminMixin, CrfModelAdmin):\n form = NextAppointmentCrfForm\n\n\n.. |pypi| image:: https://img.shields.io/pypi/v/edc-appointment.svg\n :target: https://pypi.python.org/pypi/edc-appointment\n\n.. |actions| image:: https://github.com/clinicedc/edc-appointment/actions/workflows/build.yml/badge.svg\n :target: https://github.com/clinicedc/edc-appointment/actions/workflows/build.yml\n\n.. |codecov| image:: https://codecov.io/gh/clinicedc/edc-appointment/branch/develop/graph/badge.svg\n :target: https://codecov.io/gh/clinicedc/edc-appointment\n\n.. |downloads| image:: https://pepy.tech/badge/edc-appointment\n :target: https://pepy.tech/project/edc-appointment\n",
"bugtrack_url": null,
"license": "GPL license, see LICENSE",
"summary": "Appointment module for clinicedc/edc projects",
"version": "0.4.33",
"project_urls": {
"Homepage": "https://github.com/clinicedc/edc-appointment"
},
"split_keywords": [
"django",
"appointments",
"data",
"collection",
"clinicedc",
"clinical",
"trials"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "96c903726c3f6d41f878fc9184d50292d853a676769859d9bd33f6ba6ecdb35e",
"md5": "f4aa01ad8799ae3446c3a1a9304330c0",
"sha256": "0b83f27b3fbe92b59ba05e98db4fd4af7cfbb0d2e469a944a9d9116a9d9ed787"
},
"downloads": -1,
"filename": "edc_appointment-0.4.33-py3-none-any.whl",
"has_sig": false,
"md5_digest": "f4aa01ad8799ae3446c3a1a9304330c0",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.12",
"size": 165194,
"upload_time": "2024-11-20T22:23:41",
"upload_time_iso_8601": "2024-11-20T22:23:41.558218Z",
"url": "https://files.pythonhosted.org/packages/96/c9/03726c3f6d41f878fc9184d50292d853a676769859d9bd33f6ba6ecdb35e/edc_appointment-0.4.33-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "f0cc1625bec96d9740bbe9e1746246ef727d6d840cb105c08b69c1c27d904da8",
"md5": "b938de7f2cb8472a4ea6f78a452d2cb7",
"sha256": "760fda25c5b7f74641f49687d3289a6f483305de848d61d14677d8377279ffe7"
},
"downloads": -1,
"filename": "edc_appointment-0.4.33.tar.gz",
"has_sig": false,
"md5_digest": "b938de7f2cb8472a4ea6f78a452d2cb7",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.12",
"size": 108274,
"upload_time": "2024-11-20T22:23:42",
"upload_time_iso_8601": "2024-11-20T22:23:42.999376Z",
"url": "https://files.pythonhosted.org/packages/f0/cc/1625bec96d9740bbe9e1746246ef727d6d840cb105c08b69c1c27d904da8/edc_appointment-0.4.33.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-11-20 22:23:42",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "clinicedc",
"github_project": "edc-appointment",
"travis_ci": false,
"coveralls": true,
"github_actions": true,
"lcname": "edc-appointment"
}