diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4ec2681..59f4d55 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -36,9 +36,9 @@ jobs: sudo apt-get -y update sudo apt-get install libcups2-dev wamerican - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} @@ -48,7 +48,7 @@ jobs: echo "dir=$(pip cache dir)" >>$GITHUB_OUTPUT - name: Cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ${{ steps.pip-cache.outputs.dir }} key: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6f3af91..a32918b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,32 +3,32 @@ exclude: tests/etc/user-* repos: - repo: https://github.com/PyCQA/bandit - rev: 1.7.5 + rev: 1.7.7 hooks: - id: bandit args: - "-x *test*.py" - repo: https://github.com/psf/black - rev: 23.9.1 + rev: 24.2.0 hooks: - id: black language_version: python3.11 - repo: https://github.com/pycqa/flake8 - rev: 6.1.0 + rev: 7.0.0 hooks: - id: flake8 args: - "--config=setup.cfg" - repo: https://github.com/PyCQA/isort - rev: 5.12.0 + rev: 5.13.2 hooks: - id: isort - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v4.5.0 hooks: - id: requirements-txt-fixer files: requirements/.*\.txt$ @@ -42,7 +42,7 @@ repos: - id: detect-private-key - repo: https://github.com/adrienverge/yamllint - rev: v1.32.0 + rev: v1.34.0 hooks: - id: yamllint args: diff --git a/edc_crf/crf_form_validator.py b/edc_crf/crf_form_validator.py index 94705cd..0584814 100644 --- a/edc_crf/crf_form_validator.py +++ b/edc_crf/crf_form_validator.py @@ -1,13 +1,13 @@ from __future__ import annotations import warnings -from datetime import datetime from typing import TYPE_CHECKING from django.utils.text import format_lazy from django.utils.translation import gettext_lazy as _ from edc_appointment.form_validator_mixins import WindowPeriodFormValidatorMixin from edc_consent import ConsentDefinitionDoesNotExist +from edc_consent.form_validators import ConsentDefinitionFormValidatorMixin from edc_form_validators import INVALID_ERROR, FormValidator from edc_registration import get_registered_subject_model_cls from edc_sites import site_sites @@ -28,6 +28,7 @@ class CrfFormValidatorError(Exception): class CrfFormValidator( WindowPeriodFormValidatorMixin, + ConsentDefinitionFormValidatorMixin, CrfFormValidatorMixin, FormValidator, ): @@ -77,9 +78,13 @@ def validate_crf_report_datetime(self) -> None: # falls within appointment's window period self.validate_crf_datetime_in_window_period() # not before consent date - if floor_secs(self.report_datetime) < floor_secs(self.consent_datetime): - msg = _("Invalid. Cannot be before date of consent. Participant consent on") - formatted_date = formatted_datetime(self.consent_datetime) + report_datetime = to_utc(self.report_datetime) + consent_datetime = self.get_consent_datetime_or_raise( + report_datetime=report_datetime, fldname="report_datetime" + ) + if floor_secs(report_datetime) < floor_secs(consent_datetime): + msg = _("Invalid. Cannot be before date of consent. Participant consented on") + formatted_date = formatted_datetime(consent_datetime) err_message = format_lazy( "{msg} {formatted_date}", msg=msg, formatted_date=formatted_date ) @@ -135,15 +140,6 @@ def related_visit(self) -> VisitModelMixin | None: except AttributeError as e: raise CrfFormValidatorError(f"{e}. See {self.__class__}") - @property - def consent_datetime(self) -> datetime: - dt = ( - get_registered_subject_model_cls() - .objects.get(subject_identifier=self.subject_identifier) - .consent_datetime - ) - return to_utc(dt) - def validate_datetime_against_report_datetime(self, field: str) -> None: """Datetime cannot be after report_datetime""" if (