Completed
Pull Request — master (#47)
by
unknown
53s
created

Patient.getPatientAnalysisRequestsURL()   A

Complexity

Conditions 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 6
rs 9.4285
cc 1
1
# -*- coding: utf-8 -*-
2
#
3
# This file is part of SENAITE.HEALTH
4
#
5
# Copyright 2018 by it's authors.
6
# Some rights reserved. See LICENSE.rst, CONTRIBUTORS.rst.
7
8
from Products.ATContentTypes.content import schemata
9
from AccessControl import ClassSecurityInfo
10
from Products.ATContentTypes.utils import DT2dt
11
from Products.ATExtensions.ateapi import RecordsField
12
from Products.Archetypes import atapi
13
from Products.Archetypes.public import *
14
from Products.CMFCore.utils import getToolByName
15
from Products.CMFPlone.utils import safe_unicode
16
from bika.lims import bikaMessageFactory as _b
17
from bika.health import bikaMessageFactory as _
18
from bika.lims.browser.fields import AddressField
19
from bika.lims.browser.fields import DateTimeField as DateTimeField_bl
20
from bika.lims.browser.widgets import AddressWidget
21
from bika.lims.browser.widgets import DateTimeWidget as DateTimeWidget_bl
22
from bika.lims.browser.widgets import RecordsWidget
23
from bika.health.widgets import SplittedDateWidget
24
from bika.health.config import *
25
from bika.lims.content.person import Person
26
from bika.health.interfaces import IPatient
27
from bika.health.permissions import *
28
from bika.health.widgets import ReadonlyStringWidget
29
from datetime import datetime
30
from zope.component import getAdapters
31
from zope.interface import implements
32
from Products.Archetypes.references import HoldingReference
33
from bika.health.widgets.patientmenstrualstatuswidget import PatientMenstrualStatusWidget
34
from bika.lims.vocabularies import CustomPubPrefVocabularyFactory
35
36
schema = Person.schema.copy() + Schema((
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Schema'
Loading history...
37
    StringField('PatientID',
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'StringField'
Loading history...
38
                searchable=1,
39
                required=0,
40
                widget=ReadonlyStringWidget(
41
                    visible={'view': 'visible', 'edit': 'hidden'},
42
                    label=_('Patient ID'),
43
                    css='readonly-emphasize',
44
                ),
45
    ),
46
    ReferenceField('PrimaryReferrer',
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ReferenceField'
Loading history...
47
                   vocabulary='get_clients',
48
                   allowed_types=('Client',),
49
                   relationship='PatientClient',
50
                   required=1,
51
                   widget=SelectionWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'SelectionWidget'
Loading history...
52
                       format='select',
53
                       label=_('Client'),
54
                   ),
55
    ),
56
    ComputedField('PrimaryReferrerID',
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ComputedField'
Loading history...
57
                  expression="context.Schema()['PrimaryReferrer'].get(context) and context.Schema()['PrimaryReferrer'].get(context).getId() or None",
58
                  widget=ComputedWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ComputedWidget'
Loading history...
59
                  ),
60
    ),
61
    ComputedField('PrimaryReferrerTitle',
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ComputedField'
Loading history...
62
                  expression="context.Schema()['PrimaryReferrer'].get(context) and context.Schema()['PrimaryReferrer'].get(context).Title() or None",
63
                  widget=ComputedWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ComputedWidget'
Loading history...
64
                  ),
65
    ),
66
    ComputedField('PrimaryReferrerUID',
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ComputedField'
Loading history...
67
                  expression="context.Schema()['PrimaryReferrer'].get(context) and context.Schema()['PrimaryReferrer'].get(context).UID() or None",
68
                  widget=ComputedWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ComputedWidget'
Loading history...
69
                  ),
70
    ),
71
    ComputedField(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ComputedField'
Loading history...
72
        'PrimaryReferrerURL',
73
        expression="context.getPrimaryReferrer().absolute_url_path() if context.getPrimaryReferrer() else ''",
74
        widget=ComputedWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ComputedWidget'
Loading history...
75
            visible=False
76
        ),
77
    ),
78
    StringField('Gender',
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'StringField'
Loading history...
79
                vocabulary=GENDERS,
80
                index='FieldIndex',
81
                default='dk',
82
                widget=SelectionWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'SelectionWidget'
Loading history...
83
                    format='select',
84
                    label=_('Gender'),
85
                ),
86
    ),
87
    StringField('Age',
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'StringField'
Loading history...
88
                widget=StringWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'StringWidget'
Loading history...
89
                    label=_('Age'),
90
                    visible=0,
91
                    width=3,
92
                ),
93
    ),
94
    DateTimeField_bl('BirthDate',
95
        required=0,
96
        validators=('isDateFormat',),
97
        widget=DateTimeWidget_bl(
98
          label=_('Birth date'),
99
          datepicker_nofuture=1,
100
        ),
101
    ),
102
    BooleanField('BirthDateEstimated',
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'BooleanField'
Loading history...
103
                 default=False,
104
                 widget=BooleanWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'BooleanWidget'
Loading history...
105
                     label=_('Birth date is estimated'),
106
                 ),
107
    ),
108
    RecordsField('AgeSplitted',
109
                 required=1,
110
                 widget=SplittedDateWidget(
111
                     label=_('Age'),
112
                 ),
113
    ),
114
    ComputedField(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ComputedField'
Loading history...
115
        'AgeSplittedStr',
116
        expression="context.getAgeSplittedStr()",
117
        widget=ComputedWidget(visible=False),
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ComputedWidget'
Loading history...
118
    ),
119
    AddressField('CountryState',
120
                 widget=AddressWidget(
121
                 searchable=True,
122
                 label=_("Country and state"),
123
                     showLegend=True,
124
                     showDistrict=True,
125
                     showCopyFrom=False,
126
                     showCity=False,
127
                     showPostalCode=False,
128
                     showAddress=False,
129
                 ),
130
    ),
131
    RecordsField('PatientIdentifiers',
132
                 type='patientidentifiers',
133
                 subfields=('IdentifierType',
134
                            'Identifier'),
135
                 subfield_labels={'IdentifierType': _('Identifier Type'),
136
                                  'Identifier': _('Identifier')},
137
                 subfield_sizes={'Identifier': 15,
138
                                 'Identifier Type': 25},
139
                 widget=RecordsWidget(
140
                 label=_('Additional identifiers'),
141
                 description=_('Patient additional identifiers'),
142
                     combogrid_options={
143
                         'IdentifierType': {
144
                             'colModel': [{'columnName':'IdentifierType', 'width':'30', 'label':_('Title')},
145
                                          {'columnName':'Description', 'width':'70', 'label':_('Description')}],
146
                             'url': 'getidentifiertypes',
147
                             'showOn': True,
148
                             'width': '550px'
149
                         },
150
                     },
151
                 ),
152
    ),
153
    ComputedField(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ComputedField'
Loading history...
154
        'PatientIdentifiersStr',
155
        expression="context.getPatientIdentifiersStr()",
156
        widget=ComputedWidget(visible=False),
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ComputedWidget'
Loading history...
157
    ),
158
    TextField('Remarks',
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'TextField'
Loading history...
159
              searchable=True,
160
              default_content_type='text/plain',
161
              allowable_content_types = ('text/plain', ),
162
              default_output_type="text/plain",
163
                  widget=TextAreaWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'TextAreaWidget'
Loading history...
164
                      macro="bika_widgets/remarks",
165
                  label=_('Remarks'),
166
                  append_only=True,
167
              ),
168
    ),
169
    RecordsField('TreatmentHistory',
170
                 type='treatmenthistory',
171
                 subfields=('Treatment',
172
                            'Drug',
173
                            'Start',
174
                            'End'),
175
                 required_subfields=('Drug',
176
                                     'Start',
177
                                     'End'),
178
                 subfield_labels={'Drug': _('Drug'),
179
                                  'Start': _('Start'),
180
                                  'End': _('End')},
181
                 subfield_sizes={'Drug': 40,
182
                                 'Start': 10,
183
                                 'End': 10},
184
                 subfield_types={'Start': 'datepicker_nofuture',
185
                                 'End': 'datepicker'},
186
                 widget=RecordsWidget(
187
                 label='Drug History',
188
                 description=_("A list of patient treatments and drugs administered."),
189
                     combogrid_options={
190
                          'Treatment': {
191
                              'colModel': [{'columnName':'Treatment', 'width':'30', 'label':_('Title')},
192
                                           {'columnName':'Description', 'width':'70', 'label':_('Description')}],
193
                              'url': 'gettreatments',
194
                              'showOn': True,
195
                              'width': '550px'
196
                          },
197
                         'Drug': {
198
                             'colModel': [{'columnName':'Drug', 'width':'30', 'label':_('Title')},
199
                                          {'columnName':'Description', 'width':'70', 'label':_('Description')}],
200
                             'url': 'getdrugs',
201
                             'showOn': True,
202
                             'width': '550px'
203
                         },
204
                     },
205
                 ),
206
    ),
207
    RecordsField('Allergies',
208
                 type='allergies',
209
                 subfields=('DrugProhibition',
210
                            'Drug',
211
                            'Remarks'),
212
                 required_subfields=('DrugProhibition',
213
                                     'Drug'),
214
                 subfield_labels={'DrugProhibition': _('Drug Prohibition Explanation'),
215
                                  'Drug': _('Drug'),
216
                                  'Remarks': _('Remarks')},
217
                 subfield_sizes={'DrugProhibition': 30,
218
                                 'Drug': 30,
219
                                 'Remarks': 30},
220
                 widget=RecordsWidget(
221
                     label='Allergies',
222
                     description=_("Known Patient allergies to keep information that can aid drug reaction interpretation"),
223
                     combogrid_options={
224
                         'Drug': {
225
                             'colModel': [{'columnName':'Title', 'width':'30', 'label':_('Title')},
226
                                          {'columnName':'Description', 'width':'70', 'label':_('Description')}],
227
                             'url': 'getdrugs',
228
                             'showOn': True,
229
                             'width': '550px'
230
                         },
231
                         'DrugProhibition': {
232
                             'colModel': [{'columnName':'DrugProhibition', 'width':'30', 'label':_('Title')},
233
                                          {'columnName':'Description', 'width':'70', 'label':_('Description')}],
234
                             'url': 'getdrugprohibitions',
235
                             'showOn': True,
236
                             'width': '550px'
237
                         },
238
                     },
239
                 ),
240
    ),
241
    RecordsField('ImmunizationHistory',
242
                 type='immunizationhistory',
243
                 subfields=('EPINumber',
244
                            'Immunization',
245
                            'VaccinationCenter',
246
                            'Date',
247
                            'Remarks'),
248
                 required_subfields=('EPINumber',
249
                                     'Immunization',
250
                                     'Date'),
251
                 subfield_labels={'EPINumber': _('EPI Number'),
252
                                  'Immunization': _('Immunization'),
253
                                  'VaccinationCenter': _('Vaccination Center'),
254
                                  'Date': _('Date'),
255
                                  'Remarks': _('Remarks')},
256
                 subfield_sizes={'EPINumber': 12,
257
                                 'Immunization': 20,
258
                                 'VaccinationCenter': 10, 'Date': 10, 'Remarks': 25},
259
                 subfield_types={'Date':'datepicker_nofuture'},
260
                 widget=RecordsWidget(
261
                     label='Immunization History',
262
                     description=_("A list of immunizations administered to the patient."),
263
                     combogrid_options={
264
                         'Immunization': {
265
                             'colModel': [{'columnName':'Immunization', 'width':'30', 'label':_('Title')},
266
                                         {'columnName':'Description', 'width':'70', 'label':_('Description')}],
267
                             'url': 'getimmunizations',
268
                             'showOn': True,
269
                             'width': '550px'
270
                         },
271
                         'VaccinationCenter': {
272
                             'colModel': [{'columnName':'VaccinationCenter', 'width':'100', 'label':_('Title')}],
273
                             'url': 'getvaccinationcenters',
274
                             'showOn': True,
275
                             'width': '550px'
276
                         },
277
                     },
278
                 ),
279
    ),
280
    RecordsField('TravelHistory',
281
                 type='travelhistory',
282
                 subfields=('TripStartDate',
283
                            'TripEndDate',
284
                            'Country',
285
                            'Location',
286
                            'Remarks'),
287
                 required_subfields=('Country'),
288
                 subfield_labels={'TripStartDate': _('Trip Start Date', 'Start date'),
289
                                  'TripEndDate': _('Trip End Date', 'End date'),
290
                                  'Country': _('Country'),
291
                                  'Location': _('Location'),
292
                                  'Remarks': _('Remarks')},
293
                 subfield_sizes={'TripStartDate': 10,
294
                                 'TripEndDate': 10,
295
                                 'Country': 20,
296
                                 'Location': 20,
297
                                 'Remarks': 25},
298
                 subfield_types={'TripStartDate':'datepicker_nofuture',
299
                                 'TripEndDate':'datepicker'},
300
                 widget=RecordsWidget(
301
                     label='Travel History',
302
                     description=_("A list of places visited by the patient."),
303
                     combogrid_options={
304
                         'Country': {
305
                             'colModel': [{'columnName':'Code', 'width':'15', 'label':_('Code')},
306
                                          {'columnName':'Country', 'width':'85', 'label':_('Country')}],
307
                             'url': 'getCountries',
308
                             'showOn': True,
309
                             'width': "450px",
310
                         },
311
                     },
312
                 ),
313
    ),
314
    RecordsField('ChronicConditions',
315
                 type='chronicconditions',
316
                 subfields=('Code',
317
                            'Title',
318
                            'Description',
319
                            'Onset',
320
                            'End'),
321
                 required_subfields=('Title',
322
                                     'Onset'),
323
                 subfield_sizes={'Code': 7,
324
                                 'Title': 20,
325
                                 'Description': 35,
326
                                 'Onset': 10,
327
                                 'End': 10},
328
                 subfield_types={'Onset': 'datepicker_nofuture',
329
                                 'End': 'datepicker'},
330
                 widget=RecordsWidget(
331
                     label='Past Medical History',
332
                     description=_("Patient's past medical history."),
333
                     combogrid_options={
334
                         'Title': {
335
                             'colModel': [{'columnName':'Code', 'width':'10', 'label':_('Code')},
336
                                          {'columnName':'Title', 'width':'30', 'label':_('Title')},
337
                                          {'columnName':'Description', 'width':'60', 'label':_('Description')}],
338
                             'url': 'getdiseases',
339
                             'showOn': True,
340
                             'width': "650px",
341
                         },
342
                     },
343
                 ),
344
    ),
345
    StringField('BirthPlace', schemata='Personal',
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'StringField'
Loading history...
346
                widget=StringWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'StringWidget'
Loading history...
347
                    label=_('Birth place'),
348
                ),
349
    ),
350
    # TODO This field will be removed on release 319. We maintain this field on release 318
351
    # because of the transference between string field and content type data.
352
    StringField('Ethnicity', schemata='Personal',
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'StringField'
Loading history...
353
            index='FieldIndex',
354
            vocabulary=ETHNICITIES,
355
            widget=ReferenceWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ReferenceWidget'
Loading history...
356
                label=_('Ethnicity'),
357
                description=_("Ethnicity eg. Asian, African, etc."),
358
                visible=False,
359
            ),
360
    ),
361
    # TODO This field will change its name on v319 and it'll be called Ethnicity
362
    ReferenceField('Ethnicity_Obj', schemata='Personal',
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ReferenceField'
Loading history...
363
                vocabulary='getEthnicitiesVocabulary',
364
                allowed_types = ('Ethnicity',),
365
                relationship = 'PatientEthnicity',
366
                widget=SelectionWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'SelectionWidget'
Loading history...
367
                    format='select',
368
                    label=_('Ethnicity'),
369
                    description=_("Ethnicity eg. Asian, African, etc."),
370
                ),
371
    ),
372
    StringField('Citizenship', schemata='Personal',
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'StringField'
Loading history...
373
                widget=StringWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'StringWidget'
Loading history...
374
                    label=_('Citizenship'),
375
                ),
376
    ),
377
    StringField('MothersName', schemata='Personal',
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'StringField'
Loading history...
378
                widget=StringWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'StringWidget'
Loading history...
379
                    label=_('Mothers name'),
380
                ),
381
    ),
382
    StringField('FathersName', schemata='Personal',
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'StringField'
Loading history...
383
            widget=StringWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'StringWidget'
Loading history...
384
                label=_('Fathers name'),
385
            ),
386
    ),
387
    StringField('CivilStatus', schemata='Personal',
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'StringField'
Loading history...
388
                widget=StringWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'StringWidget'
Loading history...
389
                    label=_('Civil status'),
390
                ),
391
    ),
392
    ImageField('Photo', schemata='Identification',
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ImageField'
Loading history...
393
               widget=ImageWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ImageWidget'
Loading history...
394
                   label=_('Photo'),
395
               ),
396
    ),
397
    ImageField('Feature', schemata='Identification',
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ImageField'
Loading history...
398
               multiValue=1,
399
               widget=ImageWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ImageWidget'
Loading history...
400
                   label=_('Feature'),
401
               ),
402
    ),
403
    RecordsField('MenstrualStatus',
404
            type='menstrualstatus',
405
            widget=PatientMenstrualStatusWidget(
406
                label='Menstrual status',
407
            ),
408
    ),
409
    StringField('ClientPatientID',
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'StringField'
Loading history...
410
            searchable=1,
411
            required=1,
412
            widget=StringWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'StringWidget'
Loading history...
413
                label=_('Client Patient ID'),
414
            ),
415
    ),
416
    BooleanField('Anonymous',
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'BooleanField'
Loading history...
417
             default=False,
418
             widget=BooleanWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'BooleanWidget'
Loading history...
419
                 label=_("Anonymous")
420
             ),
421
    ),
422
    BooleanField('DefaultResultsDistribution',
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'BooleanField'
Loading history...
423
        schemata="Publication preference",
424
        default=True,
425
        widget=BooleanWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'BooleanWidget'
Loading history...
426
            label=_("Inherit default settings"),
427
            description=_("If checked, settings will be inherited from "
428
                          "the Client, so further changes in Client for this "
429
                          "setting will be populated too."))
430
    ),
431
    BooleanField('AllowResultsDistribution',
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'BooleanField'
Loading history...
432
        schemata="Publication preference",
433
        default=False,
434
        widget=BooleanWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'BooleanWidget'
Loading history...
435
            label=_("Allow results distribution to this patient"),
436
            description=_("If checked, results reports will also be sent "
437
                          "to the Patient automatically."))
438
    ),
439
    LinesField('PublicationPreferences',
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'LinesField'
Loading history...
440
        vocabulary_factory='bika.lims.vocabularies.CustomPubPrefVocabularyFactory',
441
        schemata='Publication preference',
442
        widget=MultiSelectionWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'MultiSelectionWidget'
Loading history...
443
            label=_("Publication preference"),
444
            description=_("Select the preferred channels to be used for "
445
                          "sending the results reports to this Patient."))
446
    ),
447
    BooleanField('PublicationAttachmentsPermitted',
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'BooleanField'
Loading history...
448
        default=False,
449
        schemata='Publication preference',
450
        widget=BooleanWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'BooleanWidget'
Loading history...
451
            label=_("Results attachments permitted"),
452
            description=_("File attachments to results, e.g. microscope "
453
                          "photos, will be included in emails to patient "
454
                          "if this option is enabled"))
455
    ),
456
    ReferenceField('InsuranceCompany',
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ReferenceField'
Loading history...
457
        vocabulary='get_insurancecompanies',
458
        allowed_types=('InsuranceCompany',),
459
        relationship='InsuranceCompany',
460
        required=False,
461
        widget=SelectionWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'SelectionWidget'
Loading history...
462
            format='select',
463
            label=_('Insurance Company'),
464
            ),
465
        ),
466
    StringField('InsuranceNumber',
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'StringField'
Loading history...
467
                searchable=1,
468
                required=0,
469
                widget=StringWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'StringWidget'
Loading history...
470
                    label=_('Insurance Number'),
471
                ),
472
    ),
473
    BooleanField('InvoiceToInsuranceCompany',
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'BooleanField'
Loading history...
474
        default=False,
475
        widget=BooleanWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'BooleanWidget'
Loading history...
476
            label=_("Send invoices to the insurance company."),
477
            description=_("If it is checked the invoices will be send to the insurance company."
478
                          " In this case the insurance number will be mandatory."))
479
    ),
480
    BooleanField('PatientAsGuarantor',
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'BooleanField'
Loading history...
481
        schemata = 'Insurance',
482
        default=True,
483
        widget=BooleanWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'BooleanWidget'
Loading history...
484
            label=_("The patient is the guarantor."),
485
            description=_("The patient and the guarantor are the same."))
486
    ),
487
    StringField('GuarantorID',
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'StringField'
Loading history...
488
        searchable=1,
489
        schemata = 'Insurance',
490
        required=0,
491
        widget=StringWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'StringWidget'
Loading history...
492
            label=_('Guarantor ID'),
493
            description=_("The ID number (Insurance Number) from the person whose contract cover the current patient.")
494
        ),
495
    ),
496
    StringField('GuarantorSurname',
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'StringField'
Loading history...
497
        searchable=1,
498
        schemata = 'Insurance',
499
        required=0,
500
        widget=StringWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'StringWidget'
Loading history...
501
            label=_("Guarantor's Surname"),
502
        ),
503
    ),
504
    StringField('GuarantorFirstname',
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'StringField'
Loading history...
505
        searchable=1,
506
        schemata = 'Insurance',
507
        required=0,
508
        widget=StringWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'StringWidget'
Loading history...
509
            label=_("Guarantor's First Name"),
510
        ),
511
    ),
512
    AddressField('GuarantorPostalAddress',
513
        searchable=1,
514
        schemata = 'Insurance',
515
        required=0,
516
        widget=AddressWidget(
517
            label=_("Guarantor's postal address"),
518
        ),
519
    ),
520
    StringField('GuarantorBusinessPhone',
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'StringField'
Loading history...
521
        schemata = 'Insurance',
522
        widget = StringWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'StringWidget'
Loading history...
523
            label=_("Guarantor's Phone (business)"),
524
        ),
525
    ),
526
    StringField('GuarantorHomePhone',
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'StringField'
Loading history...
527
        schemata = 'Insurance',
528
        widget = StringWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'StringWidget'
Loading history...
529
            label=_("Guarantor's Phone (home)"),
530
        ),
531
    ),
532
    StringField('GuarantorMobilePhone',
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'StringField'
Loading history...
533
        schemata = 'Insurance',
534
        widget = StringWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'StringWidget'
Loading history...
535
            label=_("Guarantor's Phone (mobile)"),
536
        ),
537
    ),
538
    BooleanField('ConsentSMS',
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'BooleanField'
Loading history...
539
                 default=False,
540
                 widget=BooleanWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'BooleanWidget'
Loading history...
541
                     label=_('Consent to SMS'),
542
                 ),
543
    ),
544
    ComputedField(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ComputedField'
Loading history...
545
        'NumberOfSamples',
546
        expression="len(context.getSamples())",
547
        widget=ComputedWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ComputedWidget'
Loading history...
548
            visible=False
549
        ),
550
    ),
551
    ComputedField(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ComputedField'
Loading history...
552
        'NumberOfSamplesCancelled',
553
        expression="len(context.getSamplesCancelled())",
554
        widget=ComputedWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ComputedWidget'
Loading history...
555
            visible=False
556
        ),
557
    ),
558
    ComputedField(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ComputedField'
Loading history...
559
        'NumberOfSamplesOngoing',
560
        expression="len(context.getSamplesOngoing())",
561
        widget=ComputedWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ComputedWidget'
Loading history...
562
            visible=False
563
        ),
564
    ),
565
    ComputedField(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ComputedField'
Loading history...
566
        'NumberOfSamplesPublished',
567
        expression="len(context.getSamplesPublished())",
568
        widget=ComputedWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ComputedWidget'
Loading history...
569
            visible=False
570
        ),
571
    ),
572
    ComputedField(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ComputedField'
Loading history...
573
        'RatioOfSamplesOngoing',
574
        expression="context.getNumberOfSamplesOngoingRatio()",
575
        widget=ComputedWidget(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ComputedWidget'
Loading history...
576
            visible=False
577
        ),
578
    ),
579
))
580
581
schema['JobTitle'].widget.visible = False
582
schema['Department'].widget.visible = False
583
schema['BusinessPhone'].widget.visible = False
584
schema['BusinessFax'].widget.visible = False
585
# Don't make title required - it will be computed from the Person's Fullname
586
schema['title'].required = 0
587
schema['title'].widget.visible = False
588
schema['EmailAddress'].schemata = 'Personal'
589
schema['HomePhone'].schemata = 'Personal'
590
schema['MobilePhone'].schemata = 'Personal'
591
schema['InsuranceCompany'].schemata = 'Insurance'
592
schema['InsuranceNumber'].schemata = 'Insurance'
593
schema['InvoiceToInsuranceCompany'].schemata = 'Insurance'
594
schema.moveField('PrimaryReferrer', after='Surname')
595
schema.moveField('PatientID', before='title')
596
schema.moveField('ClientPatientID', after='PatientID')
597
schema.moveField('Anonymous', before='ClientPatientID')
598
schema.moveField('InsuranceCompany', after='PrimaryReferrer')
599
schema.moveField('InsuranceNumber', after='InsuranceCompany')
600
schema.moveField('PatientIdentifiers', after='InsuranceNumber')
601
schema.moveField('Gender', after='PatientIdentifiers')
602
schema.moveField('Age', after='Gender')
603
schema.moveField('BirthDate', after='Age')
604
schema.moveField('BirthDateEstimated', after='BirthDate')
605
schema.moveField('AgeSplitted', after='BirthDateEstimated')
606
schema.moveField('CountryState', after='AgeSplitted')
607
schema.moveField('MenstrualStatus', after='AgeSplitted')
608
schema.moveField('ConsentSMS', after='PrimaryReferrer')
609
610
611
class Patient(Person):
612
    implements(IPatient)
613
    security = ClassSecurityInfo()
614
    displayContentsTab = False
615
    schema = schema
616
617
    _at_rename_after_creation = True
618
619
    def _renameAfterCreation(self, check_auto_id=False):
620
        from bika.lims.idserver import renameAfterCreation
621
        renameAfterCreation(self)
622
623
    def Title(self):
624
        """ Return the Fullname as title """
625
        return safe_unicode(self.getFullname()).encode('utf-8')
626
627
    security.declarePublic('getPatientID')
628
629
    def getPatientID(self):
630
        return self.getId()
631
632
    security.declarePublic('getSamples')
633
    def getSamples(self):
634
        """ get all samples taken from this Patient """
635
        l = []
636
        for ar in self.getARs():
637
            sample = ar.getObject().getSample()
638
            if sample:
639
                l.append(sample)
640
        return l
641
642
    def getSamplesCancelled(self):
643
        """
644
        Cancelled Samples
645
        """
646
        workflow = getToolByName(self, 'portal_workflow')
647
        l = self.getSamples()
648
        return [sample for samples in l if
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'sample'
Loading history...
649
                workflow.getInfoFor(analysis, 'review_state') == 'cancelled']
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'analysis'
Loading history...
650
651 View Code Duplication
    def getSamplesPublished(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
652
        """
653
        Published Samples
654
        """
655
        workflow = getToolByName(self, 'portal_workflow')
656
        ars = self.getARs()
657
        samples = []
658
        samples_uids = []
659
        for ar in ars:
660
            if ar.review_state == 'published':
661
                # Getting the object now
662
                sample = ar.getObject().getSample()
663
                if sample and sample.UID() not in samples_uids:
664
                    samples.append(sample.UID())
665
                    samples_uids.append(sample)
666
        return samples
667
668 View Code Duplication
    def getSamplesOngoing(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
669
        """
670
        Ongoing on Samples
671
        """
672
        workflow = getToolByName(self, 'portal_workflow')
673
        ars = self.getARs()
674
        states = [
675
            'verified', 'to_be_sampled', 'scheduled_sampling', 'sampled',
676
            'to_be_preserved', 'sample_due', 'sample_prep', 'sample_received',
677
            'to_be_verified', ]
678
        samples = []
679
        samples_uids = []
680
        for ar in ars:
681
            if ar.review_state in states:
682
                # Getting the object now
683
                sample = ar.getObject().getSample()
684
                if sample and sample.UID() not in samples_uids:
685
                    samples.append(sample.UID())
686
                    samples_uids.append(sample)
687
        return samples
688
689
    def getNumberOfSamplesOngoingRatio(self):
690
        """
691
        Returns the ratio between NumberOfSamplesOngoing/NumberOfSamples
692
        """
693
        result = 0
694
        if self.getNumberOfSamples() > 0:
695
            result = self.getNumberOfSamplesOngoing()/self.getNumberOfSamples()
696
        return result
697
698
    security.declarePublic('getARs')
699
    def getARs(self, analysis_state=None):
700
        bc = getToolByName(self, 'bika_catalog')
701
        ars = bc(
702
            portal_type='AnalysisRequest',
703
            getPatientUID=self.UID())
704
        return ars
705
706
    def get_clients(self):
707
        ## Only show clients to which we have Manage AR rights.
708
        mtool = getToolByName(self, 'portal_membership')
709
        clientfolder = self.clients
710
        clients = []
711
        for client in clientfolder.objectValues("Client"):
712
            if not mtool.checkPermission(ManageAnalysisRequests, client):
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ManageAnalysisRequests'
Loading history...
713
                continue
714
            clients.append([client.UID(), client.Title()])
715
        clients.sort(lambda x, y: cmp(x[1].lower(), y[1].lower()))
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'cmp'
Loading history...
716
        clients.insert(0, ['', ''])
717
        return DisplayList(clients)
718
719
    def get_insurancecompanies(self):
720
        """
721
        Return all the registered insurance companies.
722
        """
723
        bsc = getToolByName(self, 'bika_setup_catalog')
724
        # Void selection
725
        ret = [('', '')]
726
        # Other selections
727
        for ic in bsc(portal_type = 'InsuranceCompany',
728
                      inactive_state = 'active',
729
                      sort_on = 'sortable_title'):
730
            ret.append((ic.UID, ic.Title))
731
        return DisplayList(ret)
732
733
    def getPatientIdentifiersStr(self):
734
        ids = self.getPatientIdentifiers()
735
        idsstr = ''
736
        for idx in ids:
737
            idsstr += idsstr == '' and idx.get('Identifier', '') or (', ' + idx.get('Identifier', ''))
738
        return idsstr
739
        #return self.getSendersPatientID()+" "+self.getSendersCaseID()+" "+self.getSendersSpecimenID()
740
741
    def getPatientIdentifiersStrHtml(self):
742
        ids = self.getPatientIdentifiers()
743
        idsstr = '<table cellpadding="0" cellspacing="0" border="0" class="patientsidentifiers" style="text-align:left;width: 100%;"><tr><td>'
744
        for idx in ids:
745
            idsstr += "<tr><td>" + idx['IdentifierType'] + ':</td><td>' + idx['Identifier'] + "</td></tr>"
746
        return "</table>" + idsstr
747
748
    def getAgeSplitted(self):
749
750
        if (self.getBirthDate()):
751
            dob = DT2dt(self.getBirthDate()).replace(tzinfo=None)
752
            now = datetime.today()
753
754
            currentday = now.day
755
            currentmonth = now.month
756
            currentyear = now.year
757
            birthday = dob.day
758
            birthmonth = dob.month
759
            birthyear = dob.year
760
            ageday = currentday - birthday
761
            agemonth = 0
762
            ageyear = 0
763
            months31days = [1, 3, 5, 7, 8, 10, 12]
764
765
            if (ageday < 0):
766
                currentmonth -= 1
767
                if (currentmonth < 1):
768
                    currentyear -= 1
769
                    currentmonth = currentmonth + 12
770
771
                dayspermonth = 30
772
                if currentmonth in months31days:
773
                    dayspermonth = 31
774
                elif currentmonth == 2:
775
                    dayspermonth = 28
776
                    if(currentyear % 4 == 0
777
                       and (currentyear % 100 > 0 or currentyear % 400 == 0)):
778
                        dayspermonth += 1
779
780
                ageday = ageday + dayspermonth
781
782
            agemonth = currentmonth - birthmonth
783
            if (agemonth < 0):
784
                currentyear -= 1
785
                agemonth = agemonth + 12
786
787
            ageyear = currentyear - birthyear
788
789
            return [{'year': ageyear,
790
                    'month': agemonth,
791
                    'day': ageday}]
792
        else:
793
            return [{'year': '',
794
                    'month': '',
795
                    'day': ''}]
796
797
    def getAge(self):
798
        return self.getAgeSplitted()[0]['year']
799
800
    def getAgeSplittedStr(self):
801
        splitted = self.getAgeSplitted()[0]
802
        arr = []
803
        arr.append(splitted['year'] and str(splitted['year']) + 'y' or '')
804
        arr.append(splitted['month'] and str(splitted['month']) + 'm' or '')
805
        arr.append(splitted['day'] and str(splitted['day']) + 'd' or '')
806
        return ' '.join(arr)
807
808
    def getCountryState(self):
809
        return self.getField('CountryState').get(self) \
810
            if self.getField('CountryState').get(self) \
811
            else self.getPhysicalAddress()
812
813
    def getGuarantorID(self):
814
        """
815
        If the patient is the guarantor, all the fields related with the guarantor are going to have the same value as
816
        the current patient fields.
817
        :return: The guarantor ID (insurance number) from
818
        """
819
        return self.getInsuranceNumber() if self.getPatientAsGuarantor() else self.getField('GuarantorID').get(self)
820
821
    def getGuarantorSurname(self):
822
        """
823
        If the patient is the guarantor, all the fields related with the guarantor are going to have the same value as
824
        the current patient fields.
825
        """
826
        return self.getSurname() if self.getPatientAsGuarantor() else self.getField('GuarantorSurname').get(self)
827
828
    def getGuarantorFirstname(self):
829
        """
830
        If the patient is the guarantor, all the fields related with the guarantor are going to have the same value as
831
        the current patient fields.
832
        """
833
        return self.getFirstname() if self.getPatientAsGuarantor() else self.getField('GuarantorFirstname').get(self)
834
835
    def getGuarantorPostalAddress(self):
836
        """
837
        If the patient is the guarantor, all the fields related with the guarantor are going to have the same value as
838
        the current patient fields.
839
        """
840
        return self.getPostalAddress() \
841
            if self.getPatientAsGuarantor() \
842
            else self.getField('GuarantorPostalAddress').get(self)
843
844
    def getGuarantorBusinessPhone(self):
845
        """
846
        If the patient is the guarantor, all the fields related with the guarantor are going to have the same value as
847
        the current patient fields.
848
        """
849
        return self.getBusinessPhone() \
850
            if self.getPatientAsGuarantor() \
851
            else self.getField('GuarantorBusinessPhone').get(self)
852
853
    def getGuarantorHomePhone(self):
854
        """
855
        If the patient is the guarantor, all the fields related with the guarantor are going to have the same value as
856
        the current patient fields.
857
        """
858
        return self.getHomePhone() if self.getPatientAsGuarantor() else self.getField('GuarantorHomePhone').get(self)
859
860
    def getGuarantorMobilePhone(self):
861
        """
862
        If the patient is the guarantor, all the fields related with the guarantor are going to have the same value as
863
        the current patient fields.
864
        """
865
        return self.getMobilePhone() \
866
            if self.getPatientAsGuarantor() \
867
            else self.getField('GuarantorMobilePhone').get(self)
868
869
    def getEthnicitiesVocabulary(self, instance=None):
870
        """
871
        Obtain all the ethnicities registered in the system and returns them as a list
872
        """
873
        bsc = getToolByName(self, 'bika_setup_catalog')
874
        items = [(c.UID, c.Title) \
875
                for c in bsc(portal_type='Ethnicity',
876
                             inactive_state = 'active')]
877
        items.sort(lambda x,y:cmp(x[1], y[1]))
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'cmp'
Loading history...
878
        items.insert(0, ('', t(_(''))))
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 't'
Loading history...
879
        return DisplayList(items)
880
881
    def getPatientAnalysisRequestsURL(self):
882
        """
883
        Return the url pointing to the analysis requests page of the patient
884
        :return: patient's analysis request url
885
        """
886
        return "/".join([self.absolute_url(), 'analysisrequests'])
887
888
    # TODO This function will will be removed on v319
889
    def getEthnicity(self):
890
        """
891
        This function exists because we are changing the construction of ethnicities. Until now, ethnicities options were
892
        hand-coded but now they are a new content type. So we need to pass all patient's ethnicity values, but to do
893
        such thing, we need to create new ethnicity types on upgrade step and edit patient ethnicity field to relate them
894
        with its corresponding ethnicity content type.
895
        :return:
896
        """
897
        return self.getEthnicity_Obj()
898
899
    # TODO This function will be removed on v319
900
    def setEthnicity(self, value):
901
        self.setEthnicity_Obj(value)
902
903
    def getDocuments(self):
904
        """
905
        Return all the multifile objects related with the patient
906
        """
907
        return self.objectValues('Multifile')
908
909
    def SearchableText(self):
910
        """
911
        Override searchable text logic based on the requirements.
912
913
        This method constructs a text blob which contains all full-text
914
        searchable text for this content item.
915
        https://docs.plone.org/develop/plone/searching_and_indexing/indexing.html#full-text-searching
916
        """
917
918
        # Speed up string concatenation ops by using a buffer
919
        entries = []
920
921
        # plain text fields we index from ourself,
922
        # a list of accessor methods of the class
923
        plain_text_fields = ("Title", "getFullname", "getId",
924
                             "getPrimaryReferrerID", "getPrimaryReferrerTitle", "getClientPatientID")
925
926
        def read(accessor):
927
            """
928
            Call a class accessor method to give a value for certain Archetypes
929
            field.
930
            """
931
            try:
932
                value = accessor()
933
            except:
934
                value = ""
935
936
            if value is None:
937
                value = ""
938
939
            return value
940
941
        # Concatenate plain text fields as they are
942
        for f in plain_text_fields:
943
            accessor = getattr(self, f)
944
            value = read(accessor)
945
            entries.append(value)
946
947
        # Adding HTML Fields to SearchableText can be uncommented if necessary
948
        # transforms = getToolByName(self, 'portal_transforms')
949
        #
950
        # # Run HTML valued fields through text/plain conversion
951
        # for f in html_fields:
952
        #     accessor = getattr(self, f)
953
        #     value = read(accessor)
954
        #
955
        #     if value != "":
956
        #         stream = transforms.convertTo('text/plain', value, mimetype='text/html')
957
        #         value = stream.getData()
958
        #
959
        #     entries.append(value)
960
961
        # Plone accessor methods assume utf-8
962
        def convertToUTF8(text):
963
            if type(text) == unicode:
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'unicode'
Loading history...
964
                return text.encode("utf-8")
965
            return text
966
967
        entries = [convertToUTF8(entry) for entry in entries]
968
969
        # Concatenate all strings to one text blob
970
        return " ".join(entries)
971
972
973
# schemata.finalizeATCTSchema(schema, folderish=True, moveDiscussion=False)
974
atapi.registerType(Patient, PROJECTNAME)
975