Source code for crate_anon.crateweb.consent.management.commands.make_ethics_pack

"""
crate_anon/tools/make_ethics_pack.py

===============================================================================

    Copyright (C) 2015, University of Cambridge, Department of Psychiatry.
    Created by Rudolf Cardinal (rnc1001@cam.ac.uk).

    This file is part of CRATE.

    CRATE is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    CRATE is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with CRATE. If not, see <https://www.gnu.org/licenses/>.

===============================================================================

**Django management command to create a pack of PDFs for ethics submission.**

For CPFT.

"""

from argparse import ArgumentParser, Namespace
import logging
from os.path import join
from tempfile import TemporaryDirectory
from typing import Any
from zipfile import ZipFile, ZIP_DEFLATED

from django.contrib.auth import get_user_model
from django.core.management.base import BaseCommand
from django.http import HttpResponse, HttpRequest

from crate_anon.crateweb.extra.pdf import serve_pdf_from_html
from crate_anon.crateweb.consent.models import TEST_ID_STR, TEST_ID_TWO_STR
from crate_anon.crateweb.consent.views import (
    decision_form_to_pt_re_study,
    draft_approval_letter,
    draft_clinician_email,
    draft_confirm_traffic_light_letter,
    draft_first_traffic_light_letter,
    draft_letter_clinician_to_pt_re_study,
    draft_researcher_cover_letter,
    draft_traffic_light_decision_form,
    draft_traffic_light_decision_form_generic,
    draft_withdrawal_letter,
)
from crate_anon.crateweb.userprofile.models import UserProfile

log = logging.getLogger(__name__)


# =============================================================================
# Django debugging request
# =============================================================================


[docs]def mk_developer_debug_request() -> HttpRequest: """ Create a debugging HttpRequest with developer privileges. """ User = get_user_model() user = User() user.is_superuser = True user.is_staff = True profile = UserProfile() profile.is_developer = True user.profile = profile req = HttpRequest() req.user = user return req
# ============================================================================= # Save PDF responses to a zip file # ============================================================================= VIEWTYPE_PDF = "pdf"
[docs]def save_pdf_response( zipfile: ZipFile, response: HttpResponse, filename: str ) -> None: """ Args: zipfile: Open zip file object in which to save the PDF. response: HTTP response object with PDF contents. filename: Filename within the zip file. """ internal_filename = "tmp.pdf" with TemporaryDirectory() as d: # With a temporary file: tmp_fullpath = join(d, internal_filename) with open(tmp_fullpath, "wb") as f: # Write bytes from the response to the file f.write(response.content) # Then store that file in the zip file: zipfile.write(tmp_fullpath, filename)
[docs]def save_html_response_as_pdf( zipfile: ZipFile, response: HttpResponse, filename: str ) -> None: """ Args: zipfile: Open zip file object in which to save the PDF. response: HTTP response with HTML contents. filename: Filename within the zip file. """ html_str = response.content.decode("utf8") return save_pdf_response(zipfile, serve_pdf_from_html(html_str), filename)
[docs]def cli_make_ethics_pack( zip_filename: str, compression: int = ZIP_DEFLATED ) -> None: """ Make an ethics pack. Args: zip_filename: Name of zip file to create. compression: Type of compression to use. """ zipfile = ZipFile(zip_filename, mode="w", compression=compression) request = mk_developer_debug_request() log.info("draft_first_traffic_light_letter") save_pdf_response( zipfile, draft_first_traffic_light_letter(request, TEST_ID_STR, VIEWTYPE_PDF), "09_AUTO_Clinician_to_patient_cover_letter_re_traffic_light.pdf", ) log.info("draft_traffic_light_decision_form_generic") save_pdf_response( zipfile, draft_traffic_light_decision_form_generic(request, VIEWTYPE_PDF), "10_AUTO_Traffic_light_decision_form_GENERIC.pdf", ) log.info("draft_traffic_light_decision_form") save_pdf_response( zipfile, draft_traffic_light_decision_form(request, TEST_ID_STR, VIEWTYPE_PDF), "11_AUTO_Traffic_light_decision_form_PERSONALIZED.pdf", ) log.info("draft_confirm_traffic_light_letter") save_pdf_response( zipfile, draft_confirm_traffic_light_letter( request, TEST_ID_TWO_STR, VIEWTYPE_PDF ), "12_AUTO_RDBM_to_patient_confirming_traffic_light_choice.pdf", ) log.warning( "13_Researcher_requests_contact_details_screenshot.pdf: DO BY HAND" ) # ... CSS problems; looks better as a screenshot. log.info("draft_clinician_email") save_html_response_as_pdf( zipfile, draft_clinician_email(request, TEST_ID_STR), "14_AUTO_Email_to_clinician_requesting_contact.pdf", ) log.warning("15_Clinician_response_page.pdf: DO BY HAND") # ... involves CSS, which is normally fetched by the browser; but also, we # need to show interactive elements that are conditional on the clinician's # choice. log.info("draft_letter_clinician_to_pt_re_study: YELLOW") save_pdf_response( zipfile, draft_letter_clinician_to_pt_re_study( request, TEST_ID_TWO_STR, VIEWTYPE_PDF ), "16_AUTO_Clinician_to_patient_cover_letter_specific_study_YELLOW.pdf", ) log.info("draft_letter_clinician_to_pt_re_study: UNKNOWN") save_pdf_response( zipfile, draft_letter_clinician_to_pt_re_study( request, TEST_ID_STR, VIEWTYPE_PDF ), "17_AUTO_Clinician_to_patient_cover_letter_specific_study_UNKNOWN.pdf", ) log.info("decision_form_to_pt_re_study: ADULT") save_pdf_response( zipfile, decision_form_to_pt_re_study(request, TEST_ID_STR, VIEWTYPE_PDF), "18_AUTO_Decision_form_about_a_specific_study_ADULT.pdf", ) log.info("decision_form_to_pt_re_study: CHILD") save_pdf_response( zipfile, decision_form_to_pt_re_study(request, TEST_ID_TWO_STR, VIEWTYPE_PDF), "19_AUTO_Decision_form_about_a_specific_study_CHILD.pdf", ) log.info("draft_approval_letter") save_pdf_response( zipfile, draft_approval_letter(request, TEST_ID_STR, VIEWTYPE_PDF), "20_AUTO_RDBM_to_researcher_giving_permission_to_contact.pdf", ) log.info("draft_researcher_cover_letter") save_pdf_response( zipfile, draft_researcher_cover_letter(request, VIEWTYPE_PDF), "21_AUTO_Researcher_cover_letter_to_patient.pdf", ) log.info("draft_withdrawal_letter") save_pdf_response( zipfile, draft_withdrawal_letter(request, TEST_ID_STR, VIEWTYPE_PDF), "22_AUTO_RDBM_to_researcher_when_patient_withdraws_consent.pdf", ) log.info(f"Written to: {zip_filename}")
# ============================================================================= # Django management command # =============================================================================
[docs]class Command(BaseCommand): """ Django management command to make an ethics pack of PDFs. """ help = "Make CPFT ethics pack"
[docs] def add_arguments(self, parser: ArgumentParser) -> None: # docstring in superclass parser.add_argument("filename", help="ZIP filename") parser.add_argument( "--compression", type=int, default=ZIP_DEFLATED, help="Compression type", )
[docs] def handle(self, *args: str, **options: Any) -> None: # docstring in superclass opts = Namespace(**options) cli_make_ethics_pack( zip_filename=opts.filename, compression=opts.compression )
# ============================================================================= # Command-line entry point # ============================================================================= # Run as "crate_django_manage make_ethics_pack FILENAME"