Passed
Push — master ( 32807f...314925 )
by Jordi
03:12
created

bika.health.content.batch.getClientID()   A

Complexity

Conditions 1

Size

Total Lines 5
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 5
rs 10
c 0
b 0
f 0
cc 1
nop 1
1
# -*- coding: utf-8 -*-
2
#
3
# This file is part of SENAITE.HEALTH.
4
#
5
# SENAITE.HEALTH is free software: you can redistribute it and/or modify it
6
# under the terms of the GNU General Public License as published by the Free
7
# Software Foundation, version 2.
8
#
9
# This program is distributed in the hope that it will be useful, but WITHOUT
10
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
# details.
13
#
14
# You should have received a copy of the GNU General Public License along with
15
# this program; if not, write to the Free Software Foundation, Inc., 51
16
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
#
18
# Copyright 2018-2019 by it's authors.
19
# Some rights reserved, see README and LICENSE.
20
21
""" http://pypi.python.org/pypi/archetypes.schemaextender
22
"""
23
from Products.ATContentTypes.interface import IATDocument
24
from Products.Archetypes.interfaces import IVocabulary
25
from Products.Archetypes.public import *
26
from Products.Archetypes.public import BooleanWidget
27
from Products.Archetypes.references import HoldingReference
28
from Products.CMFCore.interfaces import ISiteRoot
29
from Products.CMFCore.utils import getToolByName
30
from bika.lims.browser.widgets import RecordsWidget
31
from archetypes.schemaextender.interfaces import ISchemaExtender
32
from archetypes.schemaextender.interfaces import IOrderableSchemaExtender
33
from archetypes.schemaextender.interfaces import ISchemaModifier
34
from bika.lims.fields import *
35
from bika.lims.interfaces import IBatch
36
from bika.lims.browser.widgets import DateTimeWidget
37
from bika.lims.browser.widgets import ReferenceWidget
38
from bika.health import bikaMessageFactory as _
39
from bika.lims import bikaMessageFactory as _b
40
from bika.health.widgets import *
41
from plone.indexer.decorator import indexer
42
from zope.component import adapts
43
from zope.interface import implements
44
from bika.health.widgets.casepatientconditionwidget import CasePatientConditionWidget
45
try:
46
    from zope.component.hooks import getSite
47
except:
48
    # Plone < 4.3
49
    from zope.app.component.hooks import getSite
50
51
class getCaseSyndromicClassification:
52
    implements(IVocabulary)
53
    def getDisplayList(self, instance):
54
        """ return all case syndromic classifications """
55
        bsc = getToolByName(instance, 'bika_setup_catalog')
56
        ret = []
57
        for p in bsc(portal_type = 'CaseSyndromicClassification',
58
                      is_active = True,
59
                      sort_on = 'sortable_title'):
60
            ret.append((p.UID, p.Title))
61
        return DisplayList(ret)
62
63
class getCaseStatus:
64
    implements(IVocabulary)
65
    def getDisplayList(self, instance):
66
        """ return all case statuses"""
67
        bsc = getToolByName(instance, 'bika_setup_catalog')
68
        ret = []
69
        for p in bsc(portal_type = 'CaseStatus',
70
                      is_active = True,
71
                      sort_on = 'sortable_title'):
72
            ret.append((p.Title, p.Title))
73
        return DisplayList(ret)
74
75
class getCaseOutcome:
76
    implements(IVocabulary)
77
    def getDisplayList(self, instance):
78
        """ return all case Outcomes"""
79
        bsc = getToolByName(instance, 'bika_setup_catalog')
80
        ret = []
81
        for p in bsc(portal_type = 'CaseOutcome',
82
                      is_active = True,
83
                      sort_on = 'sortable_title'):
84
            ret.append((p.Title, p.Title))
85
        return DisplayList(ret)
86
87
@indexer(IBatch)
88
def getPatientID(instance):
89
    item = instance.Schema()['Patient'].get(instance)
90
    value = item and item.getPatientID() or ''
91
    return value
92
93
@indexer(IBatch)
94
def getPatientUID(instance):
95
    item = instance.Schema()['Patient'].get(instance)
96
    value = item and item.UID() or ''
97
    return value
98
99
@indexer(IBatch)
100
def getPatientTitle(instance):
101
    return PatientTitleGetter(instance)
102
103
104
def PatientTitleGetter(obj):
105
    item = obj.Schema()['Patient'].get(obj)
106
    value = item and item.Title() or ''
107
    return value
108
109
@indexer(IBatch)
110
def getDoctorID(instance):
111
    item = instance.Schema()['Doctor'].get(instance)
112
    value = item and item.Schema()['DoctorID'].get(item) or ''
113
    return value
114
115
@indexer(IBatch)
116
def getDoctorUID(instance):
117
    item = instance.Schema()['Doctor'].get(instance)
118
    value = item and item.UID() or ''
119
    return value
120
121
@indexer(IBatch)
122
def getDoctorTitle(instance):
123
    item = instance.Schema()['Doctor'].get(instance)
124
    value = item and item.Title() or ''
125
    return value
126
127
@indexer(IBatch)
128
def getClientPatientID(instance):
129
    return ClientPatientIDGetter(instance)
130
131
132
def ClientPatientIDGetter(obj):
133
    item = obj.Schema()['Patient'].get(obj)
134
    value = item and item.getClientPatientID() or ''
135
    return value
136
137
138
class BatchSchemaExtender(object):
139
    adapts(IBatch)
140
    implements(IOrderableSchemaExtender)
141
142
    fields = [
143
        # ExtComputedField('ClientID',
144
        #     expression="context.Schema()['Client'].get(context) and context.Schema()['Client'].get(context).ID() or None",
145
        # ),
146
        # ExtComputedField('ClientUID',
147
        #     expression="context.Schema()['Client'].get(context) and context.Schema()['Client'].get(context).UID() or None",
148
        # ),
149
        # ExtComputedField('ClientTitle',
150
        #     expression="context.Schema()['Client'].get(context) and context.Schema()['Client'].get(context).Title() or None",
151
        # ),
152
        ExtReferenceField('Doctor',
153
            required=1,
154
            multiValued=0,
155
            allowed_types = ('Doctor',),
156
            referenceClass = HoldingReference,
157
            relationship = 'BatchDoctor',
158
            widget=ReferenceWidget(
159
                label=_("Doctor"),
160
                description="",
161
                render_own_label=False,
162
                visible={'edit': 'visible', 'view': 'visible'},
163
                base_query={'is_active': True},
164
                catalog_name='portal_catalog',
165
                showOn=True,
166
                colModel = [{'columnName':'DoctorID','width':'20','label':_('Doctor ID')},
167
                            {'columnName':'Title','width':'80','label':_('Full Name')},
168
                            ],
169
                add_button={
170
                    'visible': True,
171
                    'url': 'doctors/portal_factory/Doctor/new/edit',
172
                    'return_fields': ['Firstname', 'Surname'],
173
                    'js_controllers': ['#doctor-base-edit',],
174
                    'overlay_handler': 'HealthDoctorOverlayHandler',
175
                },
176
                edit_button={
177
                    'visible': True,
178
                    # url with the root to create/edit a object.
179
                    'url': 'doctors/portal_factory/Doctor',
180
                    'return_fields': ['Firstname', 'Surname'],
181
                    'js_controllers': ['#doctor-base-edit',],
182
                    'overlay_handler': 'HealthDoctorOverlayHandler',
183
                }
184
            ),
185
        ),
186
        # ExtComputedField('DoctorID',
187
        #     expression="context.Schema()['Doctor'].get(context) and context.Schema()['Doctor'].get(context).ID() or None",
188
        # ),
189
        # ExtComputedField('DoctorUID',
190
        #     expression="context.Schema()['Doctor'].get(context) and context.Schema()['Doctor'].get(context).UID() or None",
191
        # ),
192
        # ExtComputedField('DoctorTitle',
193
        #     expression="context.Schema()['Doctor'].get(context) and context.Schema()['Doctor'].get(context).Title() or None",
194
        # ),
195
        ExtReferenceField('Patient',
196
            required = 1,
197
            multiValued=0,
198
            allowed_types = ('Patient',),
199
            referenceClass = HoldingReference,
200
            relationship = 'BatchPatient',
201
            widget=ReferenceWidget(
202
                label=_("Patient"),
203
                description="",
204
                render_own_label=False,
205
                visible={'edit': 'visible',
206
                         'view': 'visible'},
207
                catalog_name='bikahealth_catalog_patient_listing',
208
                search_fields=('listing_searchable_text',),
209
                base_query={'is_active': True,
210
                            'sort_limit': 50,
211
                            'sort_on': 'getPatientID',
212
                            'sort_order': 'ascending'},
213
                colModel=[
214
                    {'columnName': "getPatientID",
215
                     'width': '30',
216
                     'label': _('PID'),
217
                     'align': 'left'},
218
                    {'columnName': "getClientPatientID",
219
                     'width': '30',
220
                     'label': _('CPID'),
221
                     'align': 'left'},
222
                    {'columnName': 'Title',
223
                     'width': '30',
224
                     'label': _('Title'),
225
                     'align': 'left'},
226
                ],
227
                showOn=True,
228
                add_button={
229
                    'visible': True,
230
                    'url': 'patients/portal_factory/Patient/new/edit',
231
                    'return_fields': ['Firstname', 'Surname'],
232
                    'js_controllers': ['#patient-base-edit',],
233
                    'overlay_handler': 'HealthPatientOverlayHandler',
234
                },
235
                edit_button={
236
                    'visible': True,
237
                    # url with the root to create/edit a object.
238
                    'url': 'patients/portal_factory/Patient',
239
                    'return_fields': ['Firstname', 'Surname'],
240
                    'js_controllers': ['#patient-base-edit',],
241
                    'overlay_handler': 'HealthPatientOverlayHandler',
242
                }
243
            ),
244
        ),
245
        # ExtComputedField('PatientID',
246
        #     expression="context.Schema()['Patient'].get(context) and context.Schema()['Patient'].get(context).ID() or None",
247
        # ),
248
        # ExtComputedField('PatientUID',
249
        #     expression="context.Schema()['Patient'].get(context) and context.Schema()['Patient'].get(context).UID() or None",
250
        # ),
251
        # ExtComputedField('PatientTitle',
252
        #     expression="context.Schema()['Patient'].get(context) and context.Schema()['Patient'].get(context).Title() or None",
253
        # ),
254
        ExtDateTimeField('OnsetDate',
255
              widget=DateTimeWidget(
256
                  label=_('Onset Date'),
257
              ),
258
        ),
259
        ExtStringField('PatientBirthDate',
260
              widget=StringWidget(
261
                  visible=False,
262
              ),
263
        ),
264
        ExtRecordsField('PatientAgeAtCaseOnsetDate',
265
            widget=SplittedDateWidget(
266
                label=_('Patient Age at Case Onset Date'),
267
            ),
268
        ),
269
        ExtBooleanField('OnsetDateEstimated',
270
            default=False,
271
            widget=BooleanWidget(
272
                label = _("Onset Date Estimated"),
273
            ),
274
        ),
275
        ExtRecordsField('ProvisionalDiagnosis',
276
            type='provisionaldiagnosis',
277
            subfields=('Code', 'Title', 'Description', 'Onset'),
278
            # Temporary fix: https://github.com/bikalabs/bika.health/issues/89
279
            #required_subfields=('Title'),
280
            subfield_sizes={'Code': 7,
281
                            'Title': 20,
282
                            'Description': 35,
283
                            'Onset': 10},
284
            subfield_labels={'Code': _('Code'),
285
                             'Title': _('Provisional diagnosis'),
286
                             'Description': _('Description'),
287
                             'Onset': _('Onset')},
288
             subfield_types={'Onset': 'datepicker_nofuture'},
289
             widget=RecordsWidget(
290
                 label='Provisional diagnosis',
291
                 combogrid_options={
292
                     'Title': {
293
                         'colModel': [{'columnName':'Code', 'width':'10', 'label':_('Code')},
294
                                      {'columnName':'Title', 'width':'30', 'label':_('Title')},
295
                                      {'columnName':'Description', 'width':'60', 'label':_('Description')}],
296
                         'url': 'getsymptomsbytitle',
297
                         'showOn': True,
298
                         'width': "650px",
299
                     },
300
                     'Code': {
301
                         'colModel': [{'columnName':'Code', 'width':'10', 'label':_('Code')},
302
                                      {'columnName':'Title', 'width':'30', 'label':_('Title')},
303
                                      {'columnName':'Description', 'width':'60', 'label':_('Description')}],
304
                         'url': 'getsymptomsbycode',
305
                         'showOn': True,
306
                         'width': "650px",
307
                     },
308
                     'Description': {
309
                         'colModel': [{'columnName':'Code', 'width':'10', 'label':_('Code')},
310
                                      {'columnName':'Title', 'width':'30', 'label':_('Title')},
311
                                      {'columnName':'Description', 'width':'60', 'label':_('Description')}],
312
                         'url': 'getsymptomsbydesc',
313
                         'showOn': True,
314
                         'width': "650px",
315
                     },
316
                 },
317
             ),
318
        ),
319
        ExtTextField('AdditionalNotes',
320
            default_content_type='text/plain',
321
            allowable_content_types = ('text/plain', ),
322
            default_output_type="text/plain",
323
            widget=TextAreaWidget(
324
                label=_('Additional notes'),
325
            ),
326
        ),
327
        ExtLinesField('CaseStatus',
328
            vocabulary=getCaseStatus(),
329
            widget=MultiSelectionWidget(
330
                format='checkbox',
331
                label=_("Case status")
332
            ),
333
        ),
334
        ExtLinesField('CaseOutcome',
335
            vocabulary=getCaseOutcome(),
336
            widget=MultiSelectionWidget(
337
                format='checkbox',
338
                label=_("Case outcome")
339
            ),
340
        ),
341
        ExtRecordsField('Symptoms',
342
            type='symptoms',
343
            subfields=('UID', 'Title', 'Description', 'Severity'),
344
            widget=CaseSymptomsWidget(
345
                label='Symptoms',
346
            ),
347
        ),
348
        ExtRecordsField('AetiologicAgents',
349
            type='aetiologicagents',
350
            subfields=('Title', 'Description', 'Subtype'),
351
            subfield_sizes={'Title': 15,
352
                            'Description': 25,
353
                            'Subtype': 10},
354
            subfield_labels={'Title': _('Aetiologic agent'),
355
                             'Description': _b('Description'),
356
                             'Subtype': _('Subtype')},
357
            # Temporary fix: https://github.com/bikalabs/bika.health/issues/89
358
            # required_subfields=('Title'),
359
            widget=RecordsWidget(
360
                label='Aetiologic agents',
361
                combogrid_options={
362
                    'Title': {
363
                        'colModel': [{'columnName':'Title', 'width':'30', 'label':_('Aetiologic agent')},
364
                                     {'columnName':'Description', 'width':'60', 'label':_b('Description')},
365
                                     {'columnName':'Subtype', 'width':'30', 'label':_('Subtype')}],
366
                        'url': 'getaetiologicagents',
367
                        'showOn': True,
368
                        'width': "650px",
369
                    },
370
                },
371
            ),
372
        ),
373
        ExtIntegerField('HoursFasting',
374
            required = 0,
375
            widget=IntegerWidget(
376
                label=_('Hours fasting'),
377
            ),
378
        ),
379
        ExtRecordsField('PatientCondition',
380
            widget=CasePatientConditionWidget(
381
                label='Patient condition',
382
            ),
383
        ),
384
        ExtRecordsField('MenstrualStatus',
385
            widget=CaseMenstrualStatusWidget(
386
                label='Menstrual status',
387
            ),
388
        ),
389
        ExtRecordsField('BasalBodyTemperature',
390
            widget=CaseBasalBodyTempWidget(
391
                label='Basal body temperature',
392
            ),
393
        ),
394
        ExtStringField(
395
            'ClientPatientID',
396
            required=0,
397
            widget=ReferenceWidget(
398
                label=_b("Client Patient ID"),
399
                size=20,
400
                visible={'edit': 'visible',
401
                         'view': 'visible',
402
                         'add': 'edit'},
403
                catalog_name='bikahealth_catalog_patient_listing',
404
                portal_types=('Patient',),
405
                search_fields=('getClientPatientID',),
406
                base_query={'is_active': True,
407
                            'sort_limit': 50,
408
                            'sort_on': 'getClientPatientID',
409
                            'sort_order': 'ascending'},
410
                force_all = False,
411
                colModel = [
412
                    {'columnName': "getPatientID",
413
                     'width': '30',
414
                     'label': _('PID'),
415
                     'align': 'left'},
416
                    {'columnName': "getClientPatientID",
417
                     'width': '30',
418
                     'label': _('CPID'),
419
                     'align': 'left'},
420
                    {'columnName': 'Title',
421
                     'width': '30',
422
                     'label': _('Fullname'),
423
                     'align': 'left'},
424
                    # UID is required in colModel
425
                    {'columnName': 'UID', 'hidden': True},
426
                ],
427
                ui_item="getClientPatientID",
428
                showOn=False,
429
            ),
430
        ),
431
    ]
432
433
    def __init__(self, context):
434
        self.context = context
435
436
    def getOrder(self, schematas):
437
        schematas['default'] = ['id',
438
                                'title',
439
                                'description',
440
                                'BatchID',
441
                                'ClientPatientID',
442
                                'Patient',
443
                                # 'PatientID',
444
                                # 'PatientUID',
445
                                # 'PatientTitle',
446
                                'Client',
447
                                # 'ClientID',
448
                                # 'ClientUID',
449
                                # 'ClientTitle',
450
                                'ClientBatchID',
451
                                'Doctor',
452
                                # 'DoctorID',
453
                                # 'DoctorUID',
454
                                # 'DoctorTitle',
455
                                'BatchDate',
456
                                'OnsetDate',
457
                                'PatientAgeAtCaseOnsetDate',
458
                                'OnsetDateEstimated',
459
                                'HoursFasting',
460
                                'PatientCondition',
461
                                'BasalBodyTemperature',
462
                                'MenstrualStatus',
463
                                'Symptoms',
464
                                'ProvisionalDiagnosis',
465
                                'CaseStatus',
466
                                'CaseOutcome',
467
                                'AetiologicAgents',
468
                                'AdditionalNotes',
469
                                'Remarks',
470
                                'PatientBirthDate',
471
                                'BatchLabels',]
472
        return schematas
473
474
    def getFields(self):
475
        return self.fields
476
477
478
class BatchSchemaModifier(object):
479
    adapts(IBatch)
480
    implements(ISchemaModifier)
481
482
    def __init__(self, context):
483
        self.context = context
484
485
    def fiddle(self, schema):
486
        schema['title'].required = False
487
        schema['title'].widget.visible = False
488
        schema['description'].required = False
489
        schema['description'].widget.visible = False
490
        schema['BatchLabels'].widget.visible = False
491
        schema['ClientBatchID'].widget.label = _("Client Case ID")
492
        schema['BatchDate'].widget.visible = False
493
        schema['Doctor'].required = self.isCaseDoctorIsMandatory()
494
        return schema
495
496
    def isCaseDoctorIsMandatory(self):
497
        """
498
        Returns whether the Doctor field is mandatory or not in cases object.
499
        :return: boolean
500
        """
501
        if hasattr(self.context, 'bika_setup'):
502
            return self.context.bika_setup.CaseDoctorIsMandatory
503
504
        # If this object is being created right now, then it doesn't have bika_setup, get bika_setup from site root.
505
        plone = getSite()
506
        if not plone:
507
            plone = get_site_from_context(self.context)
508
        return plone.bika_setup.CaseDoctorIsMandatory
509
510
511
def get_site_from_context(context):
512
    """
513
    Sometimes getSite() method can return None, in that case we can find site root in parents of an object.
514
    :param context: context to go through parents of, until we reach the site root
515
    :return: site root
516
    """
517
    if not ISiteRoot.providedBy(context):
518
        return context
519
    else:
520
        for item in context.aq_chain:
521
            if ISiteRoot.providedBy(item):
522
                return item
523