19.1.45. camcops_server.cc_modules.cc_task


Copyright (C) 2012-2018 Rudolf Cardinal (rudolf@pobox.com).

This file is part of CamCOPS.

CamCOPS 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.

CamCOPS 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 CamCOPS. If not, see <http://www.gnu.org/licenses/>.


Core task export methods:

—— ———————————————————————– Format Comment —— ———————————————————————– HTML The task in a user-friendly format PDF Essentially the HTML output XML Centres on the task with its subdata integrated TSV Tab-separated value format SQL As part of an SQL or SQLite download —— ———————————————————————–

class camcops_server.cc_modules.cc_task.Task(**kwargs)[source]

Abstract base class for all tasks.

  • Column definitions:

    Use CamcopsColumn, not Column, if you have fields that need to define permitted values, mark them as BLOB-referencing fields, or do other CamCOPS-specific things.

all_true(fields: List[str]) → bool[source]

Do all fields evaluate to True?

apply_special_note(req: camcops_server.cc_modules.cc_request.CamcopsRequest, note: str, from_console: bool = False) → None[source]

Manually applies a special note to a task.

Applies it to all predecessor/successor versions as well. WRITES TO DATABASE.

are_all_fields_complete(fields: List[str]) → bool[source]

Are all fields not None?

audit(req: camcops_server.cc_modules.cc_request.CamcopsRequest, details: str, from_console: bool = False) → None[source]

Audits actions to this task.

count_booleans(fields: List[str]) → int[source]

How many fields evaluate to True?

count_where(fields: List[str], wherevalues: List[Any]) → int[source]

Count how many field values are in wherevalues.

count_wherenot(fields: List[str], notvalues: List[Any]) → int[source]

Count how many field values are NOT in notvalues.

delete_entirely(req: camcops_server.cc_modules.cc_request.CamcopsRequest) → None[source]

Completely delete this task, its lineage, and its dependents.

delete_from_hl7_message_log(req: camcops_server.cc_modules.cc_request.CamcopsRequest, from_console: bool = False) → None[source]

Erases the object from the HL7 message log (so it will be resent).

dump() → None[source]

Dump to log.

field_contents_invalid_because() → List[str][source]

Explains why contents are invalid.

field_contents_valid() → bool[source]

Checks field contents validity against fieldspecs. This is a high-speed function that doesn’t bother with explanations, since we use it for lots of task is_complete() calculations.

classmethod gen_all_subclasses() → Generator[[Type[Task], NoneType], NoneType][source]

We require that actual tasks are subclasses of both Task and Base

… so we can (a) inherit from Task to make a base class for actual tasks, as with PCL, HADS, HoNOS, etc.; and (b) not have those intermediate classes appear in the task list. Since all actual classes must be SQLAlchemy ORM objects inheriting from Base, that common inheritance is an excellent way to define them.

… CHANGED: things now inherit from Base/Task without necessarily being actual tasks; we discriminate using __abstract__ and/or __tablename__.

classmethod gen_text_filter_columns() → Generator[[Tuple[str, sqlalchemy.sql.schema.Column], NoneType], NoneType][source]

Yields tuples of (attr_name, Column), for columns that are suitable for text filtering.

get_clinical_text(req: camcops_server.cc_modules.cc_request.CamcopsRequest) → Union[List[camcops_server.cc_modules.cc_ctvinfo.CtvInfo], NoneType][source]

Tasks that provide clinical text information should override this to provide a list of dictionaries.

Return None (default) for a task that doesn’t provide clinical text, or [] for one with no information, or a list of CtvInfo objects.

get_clinician_name() → str[source]

Get the clinician’s name. May be overridden by TaskHasClinicianMixin.

get_creation_datetime() → Union[pendulum.datetime.DateTime, NoneType][source]

Creation datetime, or None.

get_creation_datetime_utc() → Union[pendulum.datetime.DateTime, NoneType][source]

Creation datetime in UTC, or None.

classmethod get_cris_dd_rows(req: camcops_server.cc_modules.cc_request.CamcopsRequest) → List[Dict][source]

Todo

fix get_cris_dd_rows

get_extra_summary_tables(req: camcops_server.cc_modules.cc_request.CamcopsRequest) → List[camcops_server.cc_modules.cc_summaryelement.ExtraSummaryTable][source]

Override if you wish to create extra summary tables, not just add summary columns to task/ancillary tables.

get_hl7_data_segments(req: camcops_server.cc_modules.cc_request.CamcopsRequest, recipient_def: camcops_server.cc_modules.cc_recipdef.RecipientDefinition) → List[hl7.containers.Segment][source]

Returns a list of HL7 data segments.

These will be:
OBR segment OBX segment any extra ones offered by the task
get_hl7_extra_data_segments(recipient_def: camcops_server.cc_modules.cc_recipdef.RecipientDefinition) → List[hl7.containers.Segment][source]

Return a list of any extra HL7 data segments.

May be overridden.

get_html(req: camcops_server.cc_modules.cc_request.CamcopsRequest, anonymise: bool = False) → str[source]

Returns HTML representing task.

get_is_complete_td_pair(req: camcops_server.cc_modules.cc_request.CamcopsRequest) → str[source]

HTML to indicate whether task is complete or not, and to make it very obvious visually when it isn’t.

get_is_complete_tr(req: camcops_server.cc_modules.cc_request.CamcopsRequest) → str[source]

HTML table row to indicate whether task is complete or not, and to make it very obvious visually when it isn’t.

get_patient_address() → str[source]

Get the patient’s address, or “”.

get_patient_dob() → Union[pendulum.date.Date, NoneType][source]

Get the patient’s DOB, or None.

get_patient_dob_first11chars() → Union[str, NoneType][source]

For example: ‘29 Dec 1999’.

get_patient_forename() → str[source]

Get the patient’s forename, in upper case, or “”.

get_patient_hl7_pid_segment(req: camcops_server.cc_modules.cc_request.CamcopsRequest, recipient_def: camcops_server.cc_modules.cc_recipdef.RecipientDefinition) → Union[hl7.containers.Segment, str][source]

Get patient HL7 PID segment, or “”.

get_patient_idnum_object(which_idnum: int) → Union[camcops_server.cc_modules.cc_patientidnum.PatientIdNum, NoneType][source]

Get the patient’s ID number, or None.

get_patient_server_pk() → Union[int, NoneType][source]

Get the server PK of the patient, or None.

get_patient_sex() → str[source]

Get the patient’s sex, or “”.

get_patient_surname() → str[source]

Get the patient’s surname, in upper case, or “”.

get_pdf(req: camcops_server.cc_modules.cc_request.CamcopsRequest, anonymise: bool = False) → bytes[source]

Returns PDF representing task.

get_pdf_html(req: camcops_server.cc_modules.cc_request.CamcopsRequest, anonymise: bool = False) → str[source]

Gets HTML used to make PDF (slightly different from plain HTML).

get_rio_metadata(which_idnum: int, uploading_user_id: str, document_type: str) → str[source]

Called by cc_hl7.send_to_filestore().

From Servelec (Lee Meredith) to Rudolf Cardinal, 2014-12-04:

Batch Document Upload

The RiO batch document upload function can be used to upload
documents in bulk automatically.  RiO includes a Batch Upload
windows service which monitors a designated folder for new files.
Each file which is scanned must be placed in the designated folder
along with a meta-data file which describes the document.  So
essentially if a document had been scanned in and was called
‘ThisIsANewReferralLetterForAPatient.pdf’ then there would also
need to be a meta file in the same folder called
‘ThisIsANewReferralLetterForAPatient.metadata’.  The contents of
the meta file would need to include the following:

    Field Order; Field Name; Description; Data Mandatory (Y/N);
    Format

    1; ClientID; RiO Client ID which identifies the patient in RiO
    against which the document will be uploaded.; Y; 15
    Alphanumeric Characters

    2; UserID; User ID of the uploaded document, this is any user
    defined within the RiO system and can be a single system user
    called ‘AutomaticDocumentUploadUser’ for example.; Y; 10
    Alphanumeric Characters

        [NB example longer than that!]

    3; DocumentType; The RiO defined document type eg: APT; Y; 80
    Alphanumeric Characters

    4; Title; The title of the document; N; 40 Alphanumeric
    Characters

    5; Description; The document description.; N; 500 Alphanumeric
    Characters

    6; Author; The author of the document; N; 80 Alphanumeric
    Characters

    7; DocumentDate; The date of the document; N; dd/MM/yyyy HH:mm

    8; FinalRevision; The revision values are 0 Draft or 1 Final,
    this is defaulted to 1 which is Final revision.; N; 0 or 1

As an example, this is what would be needed in a meta file:

    “1000001”,”TRUST1”,”APT”,”A title”, “A description of the
        document”, “An author”,”01/12/2012 09:45”,”1”

(on one line)

Clarification, from Lee Meredith to Rudolf Cardinal, 2015-02-18:

  • metadata files must be plain ASCII, not UTF-8

    • … here and cc_hl7.send_to_filestore()
  • line terminator is <CR>

    • … cc_hl7.send_to_filestore()
  • user name limit is 10 characters, despite incorrect example

    • … RecipientDefinition.check_valid()
  • DocumentType is a code that maps to a human-readable document type; for example, “APT” might map to “Appointment Letter”. These mappings are specific to the local system. (We will probably want one that maps to “Clinical Correspondence” in the absence of anything more specific.)

  • RiO will delete the files after it’s processed them.

  • Filenames should avoid spaces, but otherwise any other standard ASCII code is fine within filenames.

    • … cc_hl7.send_to_filestore()
get_seconds_from_creation_to_first_finish() → Union[float, NoneType][source]

Time in seconds from creation time to first finish (i.e. first exit if the first exit was a finish rather than an abort), or None.

get_standard_clinician_comments_block(req: camcops_server.cc_modules.cc_request.CamcopsRequest, comments: str) → str[source]

HTML DIV for clinician’s comments.

get_task_html(req: camcops_server.cc_modules.cc_request.CamcopsRequest) → str[source]

HTML for the main task content. Overridden by derived classes.

get_trackers(req: camcops_server.cc_modules.cc_request.CamcopsRequest) → List[camcops_server.cc_modules.cc_trackerhelpers.TrackerInfo][source]

Tasks that provide quantitative information for tracking over time should override this and return a list of TrackerInfo, one per tracker.

The information is read by get_all_plots_for_one_task_html() in cc_tracker.py – q.v.

Time information will be retrieved using the get_creation_datetime() function.

get_tsv_pages(req: camcops_server.cc_modules.cc_request.CamcopsRequest) → List[camcops_server.cc_modules.cc_tsv.TsvPage][source]

Returns information used for the basic research dump in TSV format.

get_twocol_bool_row(req: camcops_server.cc_modules.cc_request.CamcopsRequest, fieldname: str, label: str = None) → str[source]

HTML table row, two columns, with Boolean Y/N formatter.

get_twocol_bool_row_present_absent(req: camcops_server.cc_modules.cc_request.CamcopsRequest, fieldname: str, label: str = None) → str[source]

HTML table row, two columns, with Boolean P/A formatter.

get_twocol_bool_row_true_false(req: camcops_server.cc_modules.cc_request.CamcopsRequest, fieldname: str, label: str = None) → str[source]

HTML table row, two columns, with Boolean T/F formatter.

static get_twocol_picture_row(blob: Union[camcops_server.cc_modules.cc_blob.Blob, NoneType], label: str) → str[source]

HTML table row, two columns, with PNG on right.

get_twocol_string_row(fieldname: str, label: str = None) → str[source]

HTML table row, two columns, with web-safing of value.

get_twocol_val_row(fieldname: str, default: str = None, label: str = None) → str[source]

HTML table row, two columns, without web-safing of value.

get_values(fields: List[str]) → List[source]

Get list of object’s values from list of field names.

get_xml(req: camcops_server.cc_modules.cc_request.CamcopsRequest, include_calculated: bool = True, include_blobs: bool = True, include_patient: bool = True, indent_spaces: int = 4, eol: str = '\n', skip_fields: List[str] = None, include_comments: bool = False) → str[source]

Returns XML UTF-8 document representing task.

get_xml_core_branches(req: camcops_server.cc_modules.cc_request.CamcopsRequest, include_calculated: bool = True, include_blobs: bool = True, include_patient: bool = True, include_ancillary: bool = True, skip_fields: List[str] = None) → List[camcops_server.cc_modules.cc_xml.XmlElement][source]

Returns a list of XmlElementTuple elements representing stored, calculated, patient, and/or BLOB fields, depending on the options.

get_xml_root(req: camcops_server.cc_modules.cc_request.CamcopsRequest, include_calculated: bool = True, include_blobs: bool = True, include_patient: bool = True, include_ancillary: bool = True, skip_fields: List[str] = None) → camcops_server.cc_modules.cc_xml.XmlElement[source]

Returns XML tree. Return value is the root XmlElement.

Override to include other tables, or to deal with BLOBs, if the default methods are insufficient.

is_complete() → bool[source]

Is the task instance complete? Must be overridden.

is_female() → bool[source]

Is the patient female?

is_field_complete(field: str) → bool[source]

Is the field not None?

is_live_on_tablet() → bool[source]

Is the instance live on a tablet?

is_male() → bool[source]

Is the patient male?

is_preserved() → bool[source]

Is the task preserved and erased from the tablet?

is_respondent_complete() → bool[source]

May be overridden by TaskHasRespondentMixin.

classmethod make_cris_tables(req: camcops_server.cc_modules.cc_request.CamcopsRequest, db: DatabaseSupporter) → None[source]

Todo

fix make_cris_tables

manually_erase(req: camcops_server.cc_modules.cc_request.CamcopsRequest) → None[source]

Manually erases a task (including sub-tables). Also erases linked non-current records. This WIPES THE CONTENTS but LEAVES THE RECORD AS A PLACEHOLDER.

Audits the erasure. Propagates erase through to the HL7 log, so those records will be re-sent. WRITES TO DATABASE.

mean_fields(fields: List[str], ignorevalue: Any = None) → Union[int, float, NoneType][source]

Mean of values stored in all fields (skipping any whose value is ignorevalue).

n_complete(fields: List[str]) → int[source]

How many of the fields are not None?

n_incomplete(fields: List[str]) → int[source]

How many of the fields are None?

patient

Overridden by TaskHasPatientMixin.

suggested_pdf_filename(req: camcops_server.cc_modules.cc_request.CamcopsRequest) → str[source]

Suggested filename for PDF.

sum_fields(fields: List[str], ignorevalue: Any = None) → Union[int, float][source]

Sum values stored in all fields (skipping any whose value is ignorevalue; treating fields containing None as zero).

was_forcibly_preserved() → bool[source]

Was it forcibly preserved?

write_pdf_to_disk(req: camcops_server.cc_modules.cc_request.CamcopsRequest, filename: str) → None[source]

Writes PDF to disk, using filename.

class camcops_server.cc_modules.cc_task.TaskCountReport[source]

Report to count task instances.

class camcops_server.cc_modules.cc_task.TaskHasClinicianMixin[source]

Mixin to add clinician columns and override clinician-related methods. Must be to the LEFT of Task in the class’s base class list.

class camcops_server.cc_modules.cc_task.TaskHasRespondentMixin[source]

Mixin to add respondent columns and override respondent-related methods. Must be to the LEFT of Task in the class’s base class list.

If you don’t use declared_attr, the “comment” property doesn’t work.

class camcops_server.cc_modules.cc_task.TaskTests(methodName='runTest')[source]
camcops_server.cc_modules.cc_task.get_from_dict(d: Dict, key: str, default: Any = '[invalid_value]') → Any[source]

Returns a value from a dictionary.