summaryrefslogtreecommitdiff
path: root/python-edc-visit-tracking.spec
diff options
context:
space:
mode:
Diffstat (limited to 'python-edc-visit-tracking.spec')
-rw-r--r--python-edc-visit-tracking.spec432
1 files changed, 432 insertions, 0 deletions
diff --git a/python-edc-visit-tracking.spec b/python-edc-visit-tracking.spec
new file mode 100644
index 0000000..3c88253
--- /dev/null
+++ b/python-edc-visit-tracking.spec
@@ -0,0 +1,432 @@
+%global _empty_manifest_terminate_build 0
+Name: python-edc-visit-tracking
+Version: 0.3.52
+Release: 1
+Summary: Base classes for visit reports/tracking in clinicedc/edc
+License: GPL license, see LICENSE
+URL: https://github.com/clinicedc/edc-visit-tracking
+Source0: https://mirrors.aliyun.com/pypi/web/packages/df/55/14fac39c639c9d0b852875a130a6b511fea3ac221b252f555c0bcd9c29ec/edc-visit-tracking-0.3.52.tar.gz
+BuildArch: noarch
+
+
+%description
+Track study participant visit reports.
+Declaring a visit model
++++++++++++++++++++++++
+A **visit_model** is declared using the model mixin `VisitModelMixin`. Normally, a **visit_model** will be declared with additional model mixins, but `VisitModelMixin` must be there.
+ class SubjectVisit(VisitModelMixin, BaseUuidModel):
+Also, ensure the `Meta` class attributes of `VisitModelMixin` are inherited. These include required constraints and ordering.
+ class SubjectVisit(VisitModelMixin, BaseUuidModel):
+ class Meta(VisitModelMixin.Meta):
+ pass
+Among other features, `VisitModelMixin` adds a `OneToOneField` foreign key to the **visit_model** that points to `edc_appointment.Appointment`.
+ Important: A **visit model** is a special model in the EDC. A model declared with the model mixin, `VisitModelMixin`, is the definition of a **visit model**. CRFs and Requisitions have a foreign key pointing to a **visit model**. A number of methods on CRFs and Requisitions detect their **visit model** foreign key name, model class and value by looking for the FK declared with `VisitModelMixin`.
+For a subject that requires ICF the **visit model** would use the `RequiresConsentModelMixin`:
+ class SubjectVisit(
+ VisitModelMixin,
+ RequiresConsentFieldsModelMixin,
+ BaseUuidModel,
+ ):
+ class Meta(VisitModelMixin.Meta, BaseUuidModel.Meta):
+ pass
+If the subject does not require ICF, such as an infant, don't include the `RequiresConsentModelMixin`:
+ class InfantVisit(
+ VisitModelMixin,
+ BaseUuidModel
+ ):
+ class Meta(VisitModelMixin.Meta, , BaseUuidModel.Meta):
+ pass
+A more complete declaration will include model mixins from other libraries. For example:
+ from edc_consent.model_mixins import RequiresConsentFieldsModelMixin
+ from edc_metadata.model_mixins.creates import CreatesMetadataModelMixin
+ from edc_model.models import BaseUuidModel
+ from edc_offstudy.model_mixins import OffstudyVisitModelMixin
+ from edc_reference.model_mixins import ReferenceModelMixin
+ from edc_sites.models import CurrentSiteManager
+ from edc_sites.models import SiteModelMixin
+ from edc_visit_tracking.managers import VisitModelManager
+ from edc_visit_tracking.model_mixins import VisitModelMixin
+ class SubjectVisit(
+ SiteModelMixin,
+ VisitModelMixin,
+ ReferenceModelMixin,
+ CreatesMetadataModelMixin,
+ RequiresConsentFieldsModelMixin,
+ OffstudyNonCrfModelMixin,
+ BaseUuidModel,
+ ):
+ on_site = CurrentSiteManager()
+ objects = VisitModelManager()
+ history = edc_models.HistoricalRecords()
+ class Meta(VisitModelMixin.Meta, BaseUuidModel.Meta):
+ pass
+Declaring a CRF
++++++++++++++++
+The `CrfModelMixin` is required for all CRF models. CRF models have a `OneToOneField` key to a **visit model**.
+ class CrfOne(CrfModelMixin, OffstudyCrfModelMixin, RequiresConsentModelMixin,
+ UpdatesCrfMetadataModelMixin, BaseUuidModel):
+ subject_visit = models.OneToOneField(SubjectVisit)
+ f1 = models.CharField(max_length=10, default='erik')
+ vl = models.CharField(max_length=10, default=NO)
+ rdb = models.CharField(max_length=10, default=NO)
+ class Meta:
+ consent_model = 'myapp.subjectconsent' # for RequiresConsentModelMixin
+Declaring forms:
+++++++++++++++++
+The `VisitFormMixin` includes a number of common validations in the `clean` method:
+ class SubjectVisitForm(VisitFormMixin, FormValidatorMixin, forms.ModelForm):
+ form_validator_cls = VisitFormValidator
+ class Meta:
+ model = SubjectVisit
+`PreviousVisitModelMixin`
++++++++++++++++++++++++++
+The `PreviousVisitModelMixin` ensures that visits are entered in sequence. It is included with the `VisitModelMixin`.
+`VisitTrackingModelFormMixin`
++++++++++++++++++++++++++++++
+ see `DEFAULT_REPORT_DATETIME_ALLOWANCE`
+Missed Visit Report
++++++++++++++++++++
+A detail report should be submitted for scheduled visits that are missed.
+By selecting the reason ``missed visit`` on ``SubjectVisit``, only the missed visit CRF will be required
+for the timepoint. All other CRFs and requisitions will be excluded.
+Unscheduled visits cannot be missed. (To change this behaviour see `settings` attrubute `EDC_VISIT_TRACKING_ALLOW_MISSED_UNSCHEDULED`)
+The model mixin ``SubjectVisitMissedModelMixin`` provides the basic features of a `SubjectVisitMissed` model.
+In your subject app declare:
+ from django.db.models import PROTECT
+ from edc_crf.model_mixins import CrfWithActionModelMixin
+ from edc_model import models as edc_models
+ from edc_visit_tracking.model_mixins import SubjectVisitMissedModelMixin
+ class SubjectVisitMissed(SubjectVisitMissedModelMixin, edc_models.BaseUuidModel):
+ missed_reasons = models.ManyToManyField(
+ SubjectVisitMissedReasons, blank=True, related_name="+"
+ )
+ class Meta(CrfWithActionModelMixin.Meta, edc_models.BaseUuidModel.Meta):
+ verbose_name = "Missed Visit Report"
+ verbose_name_plural = "Missed Visit Report"
+In your list model app, e.g. ``meta_lists``, declare the list model:
+ class SubjectVisitMissedReasons(ListModelMixin):
+ class Meta(ListModelMixin.Meta):
+ verbose_name = "Subject Missed Visit Reasons"
+ verbose_name_plural = "Subject Missed Visit Reasons"
+ list_data = {
+ "meta_lists.subjectvisitmissedreasons": [
+ ("forgot", "Forgot / Can’t remember being told about appointment"),
+ ("family_emergency", "Family emergency (e.g. funeral) and was away"),
+ ("travelling", "Away travelling/visiting"),
+ ("working_schooling", "Away working/schooling"),
+ ("too_sick", "Too sick or weak to come to the centre"),
+ ("lack_of_transport", "Transportation difficulty"),
+ (OTHER, "Other reason (specify below)",),
+ ],
+ }
+Window period
++++++++++++++
+By default, the visit `report_datetime` is validated to stay within the same window period as the appointment.
+This may be too restrictive in some cases.
+To bypass this override ```validate_visit_datetime_in_window_period``` in the ```VisitFormValidator```
+ from edc_visit_tracking.form_validators import VisitFormValidator as BaseVisitFormValidator
+ class VisitFormValidator(BaseVisitFormValidator):
+ def validate_visit_datetime_in_window_period():
+ pass
+Be sure that your appointment form validator is enforcing window periods before
+bypassing this check.
+See also `edc_appointment`.
+
+%package -n python3-edc-visit-tracking
+Summary: Base classes for visit reports/tracking in clinicedc/edc
+Provides: python-edc-visit-tracking
+BuildRequires: python3-devel
+BuildRequires: python3-setuptools
+BuildRequires: python3-pip
+%description -n python3-edc-visit-tracking
+Track study participant visit reports.
+Declaring a visit model
++++++++++++++++++++++++
+A **visit_model** is declared using the model mixin `VisitModelMixin`. Normally, a **visit_model** will be declared with additional model mixins, but `VisitModelMixin` must be there.
+ class SubjectVisit(VisitModelMixin, BaseUuidModel):
+Also, ensure the `Meta` class attributes of `VisitModelMixin` are inherited. These include required constraints and ordering.
+ class SubjectVisit(VisitModelMixin, BaseUuidModel):
+ class Meta(VisitModelMixin.Meta):
+ pass
+Among other features, `VisitModelMixin` adds a `OneToOneField` foreign key to the **visit_model** that points to `edc_appointment.Appointment`.
+ Important: A **visit model** is a special model in the EDC. A model declared with the model mixin, `VisitModelMixin`, is the definition of a **visit model**. CRFs and Requisitions have a foreign key pointing to a **visit model**. A number of methods on CRFs and Requisitions detect their **visit model** foreign key name, model class and value by looking for the FK declared with `VisitModelMixin`.
+For a subject that requires ICF the **visit model** would use the `RequiresConsentModelMixin`:
+ class SubjectVisit(
+ VisitModelMixin,
+ RequiresConsentFieldsModelMixin,
+ BaseUuidModel,
+ ):
+ class Meta(VisitModelMixin.Meta, BaseUuidModel.Meta):
+ pass
+If the subject does not require ICF, such as an infant, don't include the `RequiresConsentModelMixin`:
+ class InfantVisit(
+ VisitModelMixin,
+ BaseUuidModel
+ ):
+ class Meta(VisitModelMixin.Meta, , BaseUuidModel.Meta):
+ pass
+A more complete declaration will include model mixins from other libraries. For example:
+ from edc_consent.model_mixins import RequiresConsentFieldsModelMixin
+ from edc_metadata.model_mixins.creates import CreatesMetadataModelMixin
+ from edc_model.models import BaseUuidModel
+ from edc_offstudy.model_mixins import OffstudyVisitModelMixin
+ from edc_reference.model_mixins import ReferenceModelMixin
+ from edc_sites.models import CurrentSiteManager
+ from edc_sites.models import SiteModelMixin
+ from edc_visit_tracking.managers import VisitModelManager
+ from edc_visit_tracking.model_mixins import VisitModelMixin
+ class SubjectVisit(
+ SiteModelMixin,
+ VisitModelMixin,
+ ReferenceModelMixin,
+ CreatesMetadataModelMixin,
+ RequiresConsentFieldsModelMixin,
+ OffstudyNonCrfModelMixin,
+ BaseUuidModel,
+ ):
+ on_site = CurrentSiteManager()
+ objects = VisitModelManager()
+ history = edc_models.HistoricalRecords()
+ class Meta(VisitModelMixin.Meta, BaseUuidModel.Meta):
+ pass
+Declaring a CRF
++++++++++++++++
+The `CrfModelMixin` is required for all CRF models. CRF models have a `OneToOneField` key to a **visit model**.
+ class CrfOne(CrfModelMixin, OffstudyCrfModelMixin, RequiresConsentModelMixin,
+ UpdatesCrfMetadataModelMixin, BaseUuidModel):
+ subject_visit = models.OneToOneField(SubjectVisit)
+ f1 = models.CharField(max_length=10, default='erik')
+ vl = models.CharField(max_length=10, default=NO)
+ rdb = models.CharField(max_length=10, default=NO)
+ class Meta:
+ consent_model = 'myapp.subjectconsent' # for RequiresConsentModelMixin
+Declaring forms:
+++++++++++++++++
+The `VisitFormMixin` includes a number of common validations in the `clean` method:
+ class SubjectVisitForm(VisitFormMixin, FormValidatorMixin, forms.ModelForm):
+ form_validator_cls = VisitFormValidator
+ class Meta:
+ model = SubjectVisit
+`PreviousVisitModelMixin`
++++++++++++++++++++++++++
+The `PreviousVisitModelMixin` ensures that visits are entered in sequence. It is included with the `VisitModelMixin`.
+`VisitTrackingModelFormMixin`
++++++++++++++++++++++++++++++
+ see `DEFAULT_REPORT_DATETIME_ALLOWANCE`
+Missed Visit Report
++++++++++++++++++++
+A detail report should be submitted for scheduled visits that are missed.
+By selecting the reason ``missed visit`` on ``SubjectVisit``, only the missed visit CRF will be required
+for the timepoint. All other CRFs and requisitions will be excluded.
+Unscheduled visits cannot be missed. (To change this behaviour see `settings` attrubute `EDC_VISIT_TRACKING_ALLOW_MISSED_UNSCHEDULED`)
+The model mixin ``SubjectVisitMissedModelMixin`` provides the basic features of a `SubjectVisitMissed` model.
+In your subject app declare:
+ from django.db.models import PROTECT
+ from edc_crf.model_mixins import CrfWithActionModelMixin
+ from edc_model import models as edc_models
+ from edc_visit_tracking.model_mixins import SubjectVisitMissedModelMixin
+ class SubjectVisitMissed(SubjectVisitMissedModelMixin, edc_models.BaseUuidModel):
+ missed_reasons = models.ManyToManyField(
+ SubjectVisitMissedReasons, blank=True, related_name="+"
+ )
+ class Meta(CrfWithActionModelMixin.Meta, edc_models.BaseUuidModel.Meta):
+ verbose_name = "Missed Visit Report"
+ verbose_name_plural = "Missed Visit Report"
+In your list model app, e.g. ``meta_lists``, declare the list model:
+ class SubjectVisitMissedReasons(ListModelMixin):
+ class Meta(ListModelMixin.Meta):
+ verbose_name = "Subject Missed Visit Reasons"
+ verbose_name_plural = "Subject Missed Visit Reasons"
+ list_data = {
+ "meta_lists.subjectvisitmissedreasons": [
+ ("forgot", "Forgot / Can’t remember being told about appointment"),
+ ("family_emergency", "Family emergency (e.g. funeral) and was away"),
+ ("travelling", "Away travelling/visiting"),
+ ("working_schooling", "Away working/schooling"),
+ ("too_sick", "Too sick or weak to come to the centre"),
+ ("lack_of_transport", "Transportation difficulty"),
+ (OTHER, "Other reason (specify below)",),
+ ],
+ }
+Window period
++++++++++++++
+By default, the visit `report_datetime` is validated to stay within the same window period as the appointment.
+This may be too restrictive in some cases.
+To bypass this override ```validate_visit_datetime_in_window_period``` in the ```VisitFormValidator```
+ from edc_visit_tracking.form_validators import VisitFormValidator as BaseVisitFormValidator
+ class VisitFormValidator(BaseVisitFormValidator):
+ def validate_visit_datetime_in_window_period():
+ pass
+Be sure that your appointment form validator is enforcing window periods before
+bypassing this check.
+See also `edc_appointment`.
+
+%package help
+Summary: Development documents and examples for edc-visit-tracking
+Provides: python3-edc-visit-tracking-doc
+%description help
+Track study participant visit reports.
+Declaring a visit model
++++++++++++++++++++++++
+A **visit_model** is declared using the model mixin `VisitModelMixin`. Normally, a **visit_model** will be declared with additional model mixins, but `VisitModelMixin` must be there.
+ class SubjectVisit(VisitModelMixin, BaseUuidModel):
+Also, ensure the `Meta` class attributes of `VisitModelMixin` are inherited. These include required constraints and ordering.
+ class SubjectVisit(VisitModelMixin, BaseUuidModel):
+ class Meta(VisitModelMixin.Meta):
+ pass
+Among other features, `VisitModelMixin` adds a `OneToOneField` foreign key to the **visit_model** that points to `edc_appointment.Appointment`.
+ Important: A **visit model** is a special model in the EDC. A model declared with the model mixin, `VisitModelMixin`, is the definition of a **visit model**. CRFs and Requisitions have a foreign key pointing to a **visit model**. A number of methods on CRFs and Requisitions detect their **visit model** foreign key name, model class and value by looking for the FK declared with `VisitModelMixin`.
+For a subject that requires ICF the **visit model** would use the `RequiresConsentModelMixin`:
+ class SubjectVisit(
+ VisitModelMixin,
+ RequiresConsentFieldsModelMixin,
+ BaseUuidModel,
+ ):
+ class Meta(VisitModelMixin.Meta, BaseUuidModel.Meta):
+ pass
+If the subject does not require ICF, such as an infant, don't include the `RequiresConsentModelMixin`:
+ class InfantVisit(
+ VisitModelMixin,
+ BaseUuidModel
+ ):
+ class Meta(VisitModelMixin.Meta, , BaseUuidModel.Meta):
+ pass
+A more complete declaration will include model mixins from other libraries. For example:
+ from edc_consent.model_mixins import RequiresConsentFieldsModelMixin
+ from edc_metadata.model_mixins.creates import CreatesMetadataModelMixin
+ from edc_model.models import BaseUuidModel
+ from edc_offstudy.model_mixins import OffstudyVisitModelMixin
+ from edc_reference.model_mixins import ReferenceModelMixin
+ from edc_sites.models import CurrentSiteManager
+ from edc_sites.models import SiteModelMixin
+ from edc_visit_tracking.managers import VisitModelManager
+ from edc_visit_tracking.model_mixins import VisitModelMixin
+ class SubjectVisit(
+ SiteModelMixin,
+ VisitModelMixin,
+ ReferenceModelMixin,
+ CreatesMetadataModelMixin,
+ RequiresConsentFieldsModelMixin,
+ OffstudyNonCrfModelMixin,
+ BaseUuidModel,
+ ):
+ on_site = CurrentSiteManager()
+ objects = VisitModelManager()
+ history = edc_models.HistoricalRecords()
+ class Meta(VisitModelMixin.Meta, BaseUuidModel.Meta):
+ pass
+Declaring a CRF
++++++++++++++++
+The `CrfModelMixin` is required for all CRF models. CRF models have a `OneToOneField` key to a **visit model**.
+ class CrfOne(CrfModelMixin, OffstudyCrfModelMixin, RequiresConsentModelMixin,
+ UpdatesCrfMetadataModelMixin, BaseUuidModel):
+ subject_visit = models.OneToOneField(SubjectVisit)
+ f1 = models.CharField(max_length=10, default='erik')
+ vl = models.CharField(max_length=10, default=NO)
+ rdb = models.CharField(max_length=10, default=NO)
+ class Meta:
+ consent_model = 'myapp.subjectconsent' # for RequiresConsentModelMixin
+Declaring forms:
+++++++++++++++++
+The `VisitFormMixin` includes a number of common validations in the `clean` method:
+ class SubjectVisitForm(VisitFormMixin, FormValidatorMixin, forms.ModelForm):
+ form_validator_cls = VisitFormValidator
+ class Meta:
+ model = SubjectVisit
+`PreviousVisitModelMixin`
++++++++++++++++++++++++++
+The `PreviousVisitModelMixin` ensures that visits are entered in sequence. It is included with the `VisitModelMixin`.
+`VisitTrackingModelFormMixin`
++++++++++++++++++++++++++++++
+ see `DEFAULT_REPORT_DATETIME_ALLOWANCE`
+Missed Visit Report
++++++++++++++++++++
+A detail report should be submitted for scheduled visits that are missed.
+By selecting the reason ``missed visit`` on ``SubjectVisit``, only the missed visit CRF will be required
+for the timepoint. All other CRFs and requisitions will be excluded.
+Unscheduled visits cannot be missed. (To change this behaviour see `settings` attrubute `EDC_VISIT_TRACKING_ALLOW_MISSED_UNSCHEDULED`)
+The model mixin ``SubjectVisitMissedModelMixin`` provides the basic features of a `SubjectVisitMissed` model.
+In your subject app declare:
+ from django.db.models import PROTECT
+ from edc_crf.model_mixins import CrfWithActionModelMixin
+ from edc_model import models as edc_models
+ from edc_visit_tracking.model_mixins import SubjectVisitMissedModelMixin
+ class SubjectVisitMissed(SubjectVisitMissedModelMixin, edc_models.BaseUuidModel):
+ missed_reasons = models.ManyToManyField(
+ SubjectVisitMissedReasons, blank=True, related_name="+"
+ )
+ class Meta(CrfWithActionModelMixin.Meta, edc_models.BaseUuidModel.Meta):
+ verbose_name = "Missed Visit Report"
+ verbose_name_plural = "Missed Visit Report"
+In your list model app, e.g. ``meta_lists``, declare the list model:
+ class SubjectVisitMissedReasons(ListModelMixin):
+ class Meta(ListModelMixin.Meta):
+ verbose_name = "Subject Missed Visit Reasons"
+ verbose_name_plural = "Subject Missed Visit Reasons"
+ list_data = {
+ "meta_lists.subjectvisitmissedreasons": [
+ ("forgot", "Forgot / Can’t remember being told about appointment"),
+ ("family_emergency", "Family emergency (e.g. funeral) and was away"),
+ ("travelling", "Away travelling/visiting"),
+ ("working_schooling", "Away working/schooling"),
+ ("too_sick", "Too sick or weak to come to the centre"),
+ ("lack_of_transport", "Transportation difficulty"),
+ (OTHER, "Other reason (specify below)",),
+ ],
+ }
+Window period
++++++++++++++
+By default, the visit `report_datetime` is validated to stay within the same window period as the appointment.
+This may be too restrictive in some cases.
+To bypass this override ```validate_visit_datetime_in_window_period``` in the ```VisitFormValidator```
+ from edc_visit_tracking.form_validators import VisitFormValidator as BaseVisitFormValidator
+ class VisitFormValidator(BaseVisitFormValidator):
+ def validate_visit_datetime_in_window_period():
+ pass
+Be sure that your appointment form validator is enforcing window periods before
+bypassing this check.
+See also `edc_appointment`.
+
+%prep
+%autosetup -n edc-visit-tracking-0.3.52
+
+%build
+%py3_build
+
+%install
+%py3_install
+install -d -m755 %{buildroot}/%{_pkgdocdir}
+if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi
+if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi
+if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi
+if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi
+pushd %{buildroot}
+if [ -d usr/lib ]; then
+ find usr/lib -type f -printf "\"/%h/%f\"\n" >> filelist.lst
+fi
+if [ -d usr/lib64 ]; then
+ find usr/lib64 -type f -printf "\"/%h/%f\"\n" >> filelist.lst
+fi
+if [ -d usr/bin ]; then
+ find usr/bin -type f -printf "\"/%h/%f\"\n" >> filelist.lst
+fi
+if [ -d usr/sbin ]; then
+ find usr/sbin -type f -printf "\"/%h/%f\"\n" >> filelist.lst
+fi
+touch doclist.lst
+if [ -d usr/share/man ]; then
+ find usr/share/man -type f -printf "\"/%h/%f.gz\"\n" >> doclist.lst
+fi
+popd
+mv %{buildroot}/filelist.lst .
+mv %{buildroot}/doclist.lst .
+
+%files -n python3-edc-visit-tracking -f filelist.lst
+%dir %{python3_sitelib}/*
+
+%files help -f doclist.lst
+%{_docdir}/*
+
+%changelog
+* Fri Jun 09 2023 Python_Bot <Python_Bot@openeuler.org> - 0.3.52-1
+- Package Spec generated