Passed
Push — master ( f31c62...c3750e )
by Jordi
07:28 queued 03:00
created

Method.getCalculationUID()   A

Complexity

Conditions 2

Size

Total Lines 14
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 6
dl 0
loc 14
rs 10
c 0
b 0
f 0
cc 2
nop 1
1
# -*- coding: utf-8 -*-
2
#
3
# This file is part of SENAITE.CORE
4
#
5
# Copyright 2018 by it's authors.
6
# Some rights reserved. See LICENSE.rst, CONTRIBUTORS.rst.
7
8
from AccessControl import ClassSecurityInfo
9
from bika.lims import api
10
from bika.lims import bikaMessageFactory as _
11
from bika.lims.browser.fields import UIDReferenceField
12
from bika.lims.config import PROJECTNAME
13
from bika.lims.content.bikaschema import BikaSchema
14
from bika.lims.interfaces import IDeactivable
15
from bika.lims.interfaces import IMethod
16
from bika.lims.utils import t
17
from plone.app.blob.field import FileField as BlobFileField
18
from Products.Archetypes.public import BaseFolder
19
from Products.Archetypes.public import BooleanField
20
from Products.Archetypes.public import BooleanWidget
21
from Products.Archetypes.public import ComputedField
22
from Products.Archetypes.public import FileWidget
23
from Products.Archetypes.public import LinesField
24
from Products.Archetypes.public import MultiSelectionWidget
25
from Products.Archetypes.public import Schema
26
from Products.Archetypes.public import SelectionWidget
27
from Products.Archetypes.public import StringField
28
from Products.Archetypes.public import StringWidget
29
from Products.Archetypes.public import TextAreaWidget
30
from Products.Archetypes.public import TextField
31
from Products.Archetypes.public import registerType
32
from Products.Archetypes.utils import DisplayList
33
from Products.CMFCore.utils import getToolByName
34
from zope.interface import implements
35
36
37
schema = BikaSchema.copy() + Schema((
38
39
    # Method ID should be unique, specified on MethodSchemaModifier
40
    StringField(
41
        "MethodID",
42
        searchable=1,
43
        required=0,
44
        validators=("uniquefieldvalidator",),
45
        widget=StringWidget(
46
            visible={"view": "visible", "edit": "visible"},
47
            label=_("Method ID"),
48
            description=_("Define an identifier code for the method. "
49
                          "It must be unique."),
50
        ),
51
    ),
52
53
    TextField(
54
        "Instructions",
55
        default_content_type="text/plain",
56
        allowed_content_types=("text/plain", ),
57
        default_output_type="text/plain",
58
        widget=TextAreaWidget(
59
            label=_("Instructions"),
60
            description=_("Technical description and instructions "
61
                          "intended for analysts"),
62
        ),
63
    ),
64
65
    BlobFileField(
66
        "MethodDocument",  # XXX Multiple Method documents please
67
        widget=FileWidget(
68
            label=_("Method Document"),
69
            description=_("Load documents describing the method here"),
70
        )
71
    ),
72
73
    # The instruments linked to this method. Don't use this
74
    # method, use getInstrumentUIDs() or getInstruments() instead
75
    LinesField(
76
        "_Instruments",
77
        vocabulary="getInstrumentsDisplayList",
78
        widget=MultiSelectionWidget(
79
            modes=("edit"),
80
            label=_("Instruments"),
81
            description=_(
82
                "The selected instruments have support for this method. "
83
                "Use the Instrument edit view to assign "
84
                "the method to a specific instrument"),
85
        ),
86
    ),
87
88
    # All the instruments available in the system. Don't use this
89
    # method to retrieve the instruments linked to this method, use
90
    # getInstruments() or getInstrumentUIDs() instead.
91
    LinesField(
92
        "_AvailableInstruments",
93
        vocabulary="_getAvailableInstrumentsDisplayList",
94
        widget=MultiSelectionWidget(
95
            modes=("edit"),
96
        )
97
    ),
98
99
    # If no instrument selected, always True. Otherwise, the user will
100
    # be able to set or unset the value. The behavior for this field
101
    # is controlled with javascript.
102
    BooleanField(
103
        "ManualEntryOfResults",
104
        default=False,
105
        widget=BooleanWidget(
106
            label=_("Manual entry of results"),
107
            description=_("The results for the Analysis Services that use "
108
                          "this method can be set manually"),
109
            modes=("edit"),
110
        )
111
    ),
112
113
    # Only shown in readonly view. Not in edit view
114
    ComputedField(
115
        "ManualEntryOfResultsViewField",
116
        expression="context.isManualEntryOfResults()",
117
        widget=BooleanWidget(
118
            label=_("Manual entry of results"),
119
            description=_("The results for the Analysis Services that use "
120
                          "this method can be set manually"),
121
            modes=("view"),
122
        ),
123
    ),
124
125
    # Calculations associated to this method. The analyses services
126
    # with this method assigned will use the calculation selected here.
127
    UIDReferenceField(
128
        "Calculation",
129
        vocabulary="_getCalculations",
130
        allowed_types=("Calculation",),
131
        accessor="getCalculationUID",
132
        widget=SelectionWidget(
133
            visible={"edit": "visible", "view": "visible"},
134
            format="select",
135
            checkbox_bound=0,
136
            label=_("Calculation"),
137
            description=_(
138
                "If required, select a calculation for the The analysis "
139
                "services linked to this method. Calculations can be "
140
                "configured under the calculations item in the LIMS set-up"),
141
            catalog_name="bika_setup_catalog",
142
            base_query={"is_active": True},
143
        )
144
    ),
145
    BooleanField(
146
        "Accredited",
147
        schemata="default",
148
        default=True,
149
        widget=BooleanWidget(
150
            label=_("Accredited"),
151
            description=_("Check if the method has been accredited"))
152
    ),
153
))
154
155
schema["description"].schemata = "default"
156
schema["description"].widget.visible = True
157
schema["description"].widget.label = _("Description")
158
schema["description"].widget.description = _(
159
    "Describes the method in layman terms. "
160
    "This information is made available to lab clients")
161
162
163
class Method(BaseFolder):
164
    """Method content
165
    """
166
    implements(IMethod, IDeactivable)
167
168
    security = ClassSecurityInfo()
169
    displayContentsTab = False
170
    schema = schema
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable schema does not seem to be defined.
Loading history...
171
    _at_rename_after_creation = True
172
173
    def _renameAfterCreation(self, check_auto_id=False):
174
        from bika.lims.idserver import renameAfterCreation
175
        renameAfterCreation(self)
176
177
    @security.public
178
    def getCalculation(self):
179
        """Returns the assigned calculation
180
181
        :returns: Calculation object
182
        """
183
        return self.getField("Calculation").get(self)
184
185
    @security.public
186
    def getCalculationUID(self):
187
        """Returns the UID of the assigned calculation
188
189
        NOTE: This is the default accessor of the `Calculation` schema field
190
        and needed for the selection widget to render the selected value
191
        properly in _view_ mode.
192
193
        :returns: Calculation UID
194
        """
195
        calculation = self.getCalculation()
196
        if not calculation:
197
            return None
198
        return api.get_uid(calculation)
199
200
    def isManualEntryOfResults(self):
201
        """Indicates if manual entry of results is allowed.
202
203
        If no instrument is selected for this method, returns True. Otherwise,
204
        returns False by default, but its value can be modified using the
205
        ManualEntryOfResults Boolean Field
206
        """
207
        instruments = self.getInstruments()
208
        return len(instruments) == 0 or self.getManualEntryOfResults()
209
210 View Code Duplication
    def _getCalculations(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
211
        """Available Calculations registered in Setup
212
        """
213
        bsc = getToolByName(self, "bika_setup_catalog")
214
        items = [(c.UID, c.Title)
215
                 for c in bsc(portal_type="Calculation",
216
                              is_active=True)]
217
        items.sort(lambda x, y: cmp(x[1], y[1]))
218
        items.insert(0, ("", t(_("None"))))
219
        return DisplayList(items)
220
221
    def getInstruments(self):
222
        """Instruments capable to perform this method
223
        """
224
        return self.getBackReferences("InstrumentMethods")
225
226
    def getInstrumentUIDs(self):
227
        """UIDs of the instruments capable to perform this method
228
        """
229
        return map(api.get_uid, self.getInstruments())
230
231
    def getInstrumentsDisplayList(self):
232
        """Instruments capable to perform this method
233
        """
234
        items = [(i.UID(), i.Title()) for i in self.getInstruments()]
235
        return DisplayList(list(items))
236
237 View Code Duplication
    def _getAvailableInstrumentsDisplayList(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
238
        """Available instruments registered in the system
239
240
        Only instruments with state=active will be fetched
241
        """
242
        bsc = getToolByName(self, "bika_setup_catalog")
243
        items = [(i.UID, i.Title)
244
                 for i in bsc(portal_type="Instrument",
245
                              is_active=True)]
246
        items.sort(lambda x, y: cmp(x[1], y[1]))
247
        return DisplayList(list(items))
248
249
250
registerType(Method, PROJECTNAME)
251