Passed
Push — master ( f42093...226b52 )
by Ramon
04:24
created

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

Complexity

Conditions 2

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