Passed
Push — master ( 0b6604...4c3d35 )
by Ramon
04:28
created

bika.lims.content.batch.Batch.getClient()   A

Complexity

Conditions 2

Size

Total Lines 12
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 12
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
# 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-2019 by it's authors.
19
# Some rights reserved, see README and LICENSE.
20
21
from AccessControl import ClassSecurityInfo
22
from bika.lims import api
23
from bika.lims import bikaMessageFactory as _
24
from bika.lims import deprecated
25
from bika.lims.browser.fields.remarksfield import RemarksField
26
from bika.lims.browser.widgets import DateTimeWidget
27
from bika.lims.browser.widgets import RecordsWidget as bikaRecordsWidget
28
from bika.lims.browser.widgets import ReferenceWidget
29
from bika.lims.browser.widgets import RemarksWidget
30
from bika.lims.catalog import CATALOG_ANALYSIS_REQUEST_LISTING
31
from bika.lims.config import PROJECTNAME
32
from bika.lims.content.bikaschema import BikaFolderSchema
33
from bika.lims.interfaces import IBatch
34
from bika.lims.interfaces import ICancellable
35
from bika.lims.interfaces import IClient
36
from plone.app.folder.folder import ATFolder
37
from plone.indexer import indexer
38
from Products.Archetypes.public import DateTimeField
39
from Products.Archetypes.public import DisplayList
40
from Products.Archetypes.public import LinesField
41
from Products.Archetypes.public import MultiSelectionWidget
42
from Products.Archetypes.public import ReferenceField
43
from Products.Archetypes.public import Schema
44
from Products.Archetypes.public import StringField
45
from Products.Archetypes.public import StringWidget
46
from Products.Archetypes.public import registerType
47
from Products.Archetypes.references import HoldingReference
48
from Products.ATExtensions.ateapi import RecordsField
49
from Products.CMFCore.utils import getToolByName
50
from Products.CMFPlone.utils import safe_unicode
51
from zope.interface import implements
52
53
54
@indexer(IBatch)
55
def BatchDate(instance):
56
    return instance.Schema().getField('BatchDate').get(instance)
57
58
59
schema = BikaFolderSchema.copy() + Schema((
60
61
    StringField(
62
        'BatchID',
63
        required=False,
64
        validators=('uniquefieldvalidator',),
65
        widget=StringWidget(
66
            # XXX This field can never hold a user value, because it is
67
            #     invisible (see custom getBatchID getter method)
68
            # => we should remove that field
69
            visible=False,
70
            label=_("Batch ID"),
71
        )
72
    ),
73
74
    ReferenceField(
75
        'Client',
76
        required=0,
77
        allowed_types=('Client',),
78
        relationship='BatchClient',
79
        widget=ReferenceWidget(
80
            label=_("Client"),
81
            size=30,
82
            visible=True,
83
            base_query={'review_state': 'active'},
84
            showOn=True,
85
            colModel=[
86
                {'columnName': 'UID', 'hidden': True},
87
                {'columnName': 'Title', 'width': '60', 'label': _('Title')},
88
                {'columnName': 'ClientID', 'width': '20', 'label': _('Client ID')}
89
            ],
90
        ),
91
    ),
92
93
    StringField(
94
        'ClientBatchID',
95
        required=0,
96
        widget=StringWidget(
97
            label=_("Client Batch ID")
98
        )
99
    ),
100
101
    DateTimeField(
102
        'BatchDate',
103
        required=False,
104
        widget=DateTimeWidget(
105
            label=_('Date'),
106
        ),
107
    ),
108
109
    LinesField(
110
        'BatchLabels',
111
        vocabulary="BatchLabelVocabulary",
112
        accessor="getLabelNames",
113
        widget=MultiSelectionWidget(
114
            label=_("Batch Labels"),
115
            format="checkbox",
116
        )
117
    ),
118
119
    RemarksField(
120
        'Remarks',
121
        searchable=True,
122
        widget=RemarksWidget(
123
            label=_('Remarks'),
124
        )
125
    ),
126
))
127
128
# Remove implicit `uniquefieldvalidator` coming from `BikaFolderSchema`
129
schema['title'].validators = ()
130
schema['title'].widget.description = _("If no value is entered, the Batch ID"
131
                                       " will be auto-generated.")
132
schema['title'].required = False
133
schema['title'].widget.visible = True
134
schema['title'].widget.description = _("If no Title value is entered,"
135
                                       " the Batch ID will be used.")
136
schema['description'].required = False
137
schema['description'].widget.visible = True
138
139
schema.moveField('ClientBatchID', before='description')
140
schema.moveField('BatchID', before='description')
141
schema.moveField('title', before='description')
142
schema.moveField('Client', after='title')
143
144
145
class Batch(ATFolder):
146
    """A Batch combines multiple ARs into a logical unit
147
    """
148
    implements(IBatch, ICancellable)
149
150
    schema = schema
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable schema does not seem to be defined.
Loading history...
151
    displayContentsTab = False
152
    security = ClassSecurityInfo()
153
    _at_rename_after_creation = True
154
155
    def _renameAfterCreation(self, check_auto_id=False):
156
        from bika.lims.idserver import renameAfterCreation
157
        renameAfterCreation(self)
158
159
    def getClient(self):
160
        """Retrieves the Client the current Batch is assigned to
161
        """
162
        # The schema's field Client is only used to allow the user to assign
163
        # the batch to a client in edit form. The entered value is used in
164
        # ObjectModifiedEventHandler to move the batch to the Client's folder,
165
        # so the value stored in the Schema's is not used anymore
166
        # See https://github.com/senaite/senaite.core/pull/1450
167
        client = self.aq_parent
168
        if IClient.providedBy(client):
169
            return client
170
        return None
171
172
    def getClientTitle(self):
173
        client = self.getClient()
174
        if client:
175
            return client.Title()
176
        return ""
177
178
    def getClientUID(self):
179
        """This index is required on batches so that batch listings can be
180
        filtered by client
181
        """
182
        client = self.getClient()
183
        if client:
184
            return client.UID()
185
186
    def getContactTitle(self):
187
        return ""
188
189
    def getProfilesTitle(self):
190
        return ""
191
192
    def getAnalysisService(self):
193
        analyses = set()
194
        for ar in self.getAnalysisRequests():
195
            for an in ar.getAnalyses():
196
                analyses.add(an)
197
        value = []
198
        for analysis in analyses:
199
            val = analysis.Title
200
            if val not in value:
201
                value.append(val)
202
        return list(value)
203
204 View Code Duplication
    def getAnalysts(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
205
        analyses = []
206
        for ar in self.getAnalysisRequests():
207
            analyses += list(ar.getAnalyses(full_objects=True))
208
        value = []
209
        for analysis in analyses:
210
            val = analysis.getAnalyst()
211
            if val not in value:
212
                value.append(val)
213
        return value
214
215
    security.declarePublic('getBatchID')
216
217
    @deprecated("Please use getId instead")
218
    def getBatchID(self):
219
        # NOTE This method is a custom getter of the invisible field "BatchID".
220
        #      Therefore, it is unlikely that it returns anything else than `getId`.
221
        if self.BatchID:
222
            return self.BatchID
223
        if self.checkCreationFlag():
224
            return self.BatchID
225
        return self.getId()
226
227
    def BatchLabelVocabulary(self):
228
        """Return all batch labels as a display list
229
        """
230
        bsc = getToolByName(self, 'bika_setup_catalog')
231
        ret = []
232
        for p in bsc(portal_type='BatchLabel',
233
                     is_active=True,
234
                     sort_on='sortable_title'):
235
            ret.append((p.UID, p.Title))
236
        return DisplayList(ret)
237
238
    def getAnalysisRequestsBrains(self, **kwargs):
239
        """Return all the Analysis Requests brains linked to the Batch
240
        kargs are passed directly to the catalog.
241
        """
242
        kwargs['getBatchUID'] = self.UID()
243
        catalog = getToolByName(self, CATALOG_ANALYSIS_REQUEST_LISTING)
244
        brains = catalog(kwargs)
245
        return brains
246
247
    def getAnalysisRequests(self, **kwargs):
248
        """Return all the Analysis Requests objects linked to the Batch kargs
249
        are passed directly to the catalog.
250
        """
251
        brains = self.getAnalysisRequestsBrains(**kwargs)
252
        return [b.getObject() for b in brains]
253
254
    def isOpen(self):
255
        """Returns true if the Batch is in 'open' state
256
        """
257
        return api.get_workflow_status_of(self) not in ["cancelled", "closed"]
258
259
    def getLabelNames(self):
260
        uc = getToolByName(self, 'uid_catalog')
261
        uids = [uid for uid in self.Schema().getField('BatchLabels').get(self)]
262
        labels = [label.getObject().title for label in uc(UID=uids)]
263
        return labels
264
265
266
registerType(Batch, PROJECTNAME)
267