Passed
Push — 2.x ( 7dbd5c...d2326f )
by Jordi
08:34
created

bika.lims.content.worksheettemplate   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 252
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 15
eloc 158
dl 0
loc 252
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A WorksheetTemplate.getAnalysisTypes() 0 5 1
A WorksheetTemplate._renameAfterCreation() 0 3 1
A WorksheetTemplate.getInstrumentsDisplayList() 0 16 3
A WorksheetTemplate.getRawInstruments() 0 23 4
A WorksheetTemplate.getMethodUID() 0 7 2
A WorksheetTemplate._getMethodsVoc() 0 13 3
A WorksheetTemplate.getInstruments() 0 6 1
1
# -*- coding: utf-8 -*-
2
#
3
# This file is part of SENAITE.CORE.
4
#
5
# SENAITE.CORE is free software: you can redistribute it and/or modify it under
6
# the terms of the GNU General Public License as published by the Free Software
7
# 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-2021 by it's authors.
19
# Some rights reserved, see README and LICENSE.
20
21
import sys
22
from AccessControl import ClassSecurityInfo
23
from bika.lims import api
24
from bika.lims import bikaMessageFactory as _
25
from bika.lims.browser.widgets import ServicesWidget
26
from bika.lims.browser.widgets import WorksheetTemplateLayoutWidget
27
from bika.lims.config import ANALYSIS_TYPES
28
from bika.lims.config import PROJECTNAME
29
from bika.lims.content.bikaschema import BikaSchema
30
from bika.lims.interfaces import IDeactivable
31
from bika.lims.interfaces import IHaveInstrument
32
from bika.lims.interfaces import IWorksheetTemplate
33
from Products.Archetypes.public import BaseContent
34
from Products.Archetypes.public import BooleanField
35
from Products.Archetypes.public import BooleanWidget
36
from Products.Archetypes.public import DisplayList
37
from Products.Archetypes.public import ReferenceField
38
from Products.Archetypes.public import ReferenceWidget
39
from Products.Archetypes.public import registerType
40
from Products.Archetypes.public import Schema
41
from Products.Archetypes.public import StringField
42
from Products.Archetypes.public import StringWidget
43
from Products.Archetypes.references import HoldingReference
44
from senaite.core.browser.fields.records import RecordsField
45
from senaite.core.catalog import SETUP_CATALOG
46
from senaite.core.p3compat import cmp
47
from zope.interface import implements
48
49
schema = BikaSchema.copy() + Schema((
50
    RecordsField(
51
        "Layout",
52
        schemata="Layout",
53
        required=1,
54
        type="templateposition",
55
        subfields=("pos", "type", "blank_ref", "control_ref", "dup"),
56
        required_subfields=("pos", "type"),
57
        subfield_labels={
58
            "pos": _("Position"),
59
            "type": _("Analysis Type"),
60
            "blank_ref": _("Reference"),
61
            "control_ref": _("Reference"),
62
            "dup": _("Duplicate Of")
63
        },
64
        widget=WorksheetTemplateLayoutWidget(
65
            label=_("Worksheet Layout"),
66
            description=_(
67
                "Specify the size of the Worksheet, e.g. corresponding to a "
68
                "specific instrument's tray size. "
69
                "Then select an Analysis 'type' per Worksheet position."
70
                "Where QC samples are selected, also select which Reference "
71
                "Sample should be used."
72
                "If a duplicate analysis is selected, indicate which sample "
73
                "position it should be a duplicate of"),
74
        )
75
    ),
76
77
    ReferenceField(
78
        "Service",
79
        schemata="Analyses",
80
        required=0,
81
        multiValued=1,
82
        allowed_types=("AnalysisService",),
83
        relationship="WorksheetTemplateAnalysisService",
84
        referenceClass=HoldingReference,
85
        widget=ServicesWidget(
86
            label=_("Analysis Service"),
87
            description=_(
88
                "Select which Analyses should be included on the Worksheet"
89
            ),
90
        )
91
    ),
92
93
    ReferenceField(
94
        "RestrictToMethod",
95
        schemata="Description",
96
        required=0,
97
        vocabulary_display_path_bound=sys.maxint,
98
        vocabulary="_getMethodsVoc",
99
        allowed_types=("Method",),
100
        relationship="WorksheetTemplateMethod",
101
        referenceClass=HoldingReference,
102
        widget=ReferenceWidget(
103
            checkbox_bound=0,
104
            label=_("Method"),
105
            description=_(
106
                "Restrict the available analysis services and instruments"
107
                "to those with the selected method."
108
                " In order to apply this change to the services list, you "
109
                "should save the change first."
110
            ),
111
        ),
112
    ),
113
114
    ReferenceField(
115
        "Instrument",
116
        schemata="Description",
117
        required=0,
118
        vocabulary_display_path_bound=sys.maxint,
119
        vocabulary="getInstrumentsDisplayList",
120
        allowed_types=("Instrument",),
121
        relationship="WorksheetTemplateInstrument",
122
        referenceClass=HoldingReference,
123
        widget=ReferenceWidget(
124
            checkbox_bound=0,
125
            label=_("Instrument"),
126
            description=_(
127
                "Select the preferred instrument"
128
            ),
129
        ),
130
    ),
131
132
    StringField(
133
        "InstrumentTitle",
134
        widget=StringWidget(
135
            visible=False
136
        )
137
    ),
138
139
    BooleanField(
140
        "EnableMultipleUseOfInstrument",
141
        default=True,
142
        schemata="Description",
143
        widget=BooleanWidget(
144
            label=_("Enable Multiple Use of Instrument in Worksheets."),
145
            description=_(
146
                "If unchecked, Lab Managers won't be able to assign the same "
147
                "Instrument more than one Analyses while creating a Worksheet."
148
            )
149
        )
150
    ),
151
152
))
153
154
schema["title"].schemata = "Description"
155
schema["title"].widget.visible = True
156
157
schema["description"].schemata = "Description"
158
schema["description"].widget.visible = True
159
160
161
class WorksheetTemplate(BaseContent):
162
    """Worksheet Templates
163
    """
164
    implements(IWorksheetTemplate, IHaveInstrument, IDeactivable)
165
    security = ClassSecurityInfo()
166
    displayContentsTab = False
167
    schema = schema
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable schema does not seem to be defined.
Loading history...
168
    _at_rename_after_creation = True
169
170
    def _renameAfterCreation(self, check_auto_id=False):
171
        from bika.lims.idserver import renameAfterCreation
172
        renameAfterCreation(self)
173
174
    @security.public
175
    def getAnalysisTypes(self):
176
        """Return Analysis type displaylist
177
        """
178
        return ANALYSIS_TYPES
179
180
    @security.public
181
    def getInstrumentsDisplayList(self):
182
        """Returns a display list with the instruments that are allowed for
183
        this worksheet template based on the method selected, sorted by title
184
        ascending. It also includes "No instrument" as the first option
185
        """
186
        items = []
187
        for instrument in self.getInstruments():
188
            uid = api.get_uid(instrument)
189
            title = api.get_title(instrument)
190
            items.append((uid, title))
191
192
        # Sort them alphabetically by title
193
        items.sort(lambda x, y: cmp(x[1], y[1]))
194
        items.insert(0, ("", _("No instrument")))
195
        return DisplayList(items)
196
197
    def getInstruments(self):
198
        """Returns the list of active Instrument objects that are allowed for
199
        this worksheet template based on the method selected
200
        """
201
        uids = self.getRawInstruments()
202
        return [api.get_object_by_uid(uid) for uid in uids]
203
204
    def getRawInstruments(self):
205
        """Returns the list of UIDs from active instruments that are allowed
206
        for this worksheet template based on the method selected, if any
207
        """
208
        uids = []
209
        method_uid = self.getRawRestrictToMethod()
210
        query = {
211
            "portal_type": "Instrument",
212
            "is_active": True,
213
        }
214
        brains = api.search(query, SETUP_CATALOG)
215
        for brain in brains:
216
            uid = api.get_uid(brain)
217
            if not method_uid:
218
                uids.append(uid)
219
                continue
220
221
            # Restrict available instruments to those with the selected method
222
            instrument = api.get_object(brain)
223
            if method_uid in instrument.getRawMethods():
224
                uids.append(uid)
225
226
        return uids
227
228
    def getMethodUID(self):
229
        """Return method UID
230
        """
231
        method = self.getRestrictToMethod()
232
        if method:
233
            return method.UID()
234
        return ""
235
236
    def _getMethodsVoc(self):
237
        """Return the registered methods as DisplayList
238
        """
239
        methods = api.search({
240
            "portal_type": "Method",
241
            "is_active": True
242
        }, "senaite_catalog_setup")
243
244
        items = map(lambda m: (api.get_uid(m), api.get_title(m)), methods)
245
        items.sort(lambda x, y: cmp(x[1], y[1]))
246
        items.insert(0, ("", _("Not specified")))
247
248
        return DisplayList(list(items))
249
250
251
registerType(WorksheetTemplate, PROJECTNAME)
252