Passed
Push — master ( eeab6e...dd6af3 )
by Ramon
05:59
created

bika/lims/adapters/widgetvisibility.py (2 issues)

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 bika.lims import api
22
from bika.lims.interfaces import IATWidgetVisibility
23
from bika.lims.interfaces import IAnalysisRequestSecondary
24
from bika.lims.interfaces import IBatch
25
from bika.lims.interfaces import IClient
26
from bika.lims.utils import getHiddenAttributesForClass
27
from zope.interface import implements
28
29
_marker = []
30
31
32
class SenaiteATWidgetVisibility(object):
33
    implements(IATWidgetVisibility)
34
35
    def __init__(self, context, sort=1000, field_names=None):
36
        self.context = context
37
        self.sort = sort
38
        self.field_names = field_names or list()
39
40
    def __call__(self, context, mode, field, default):
41
        state = default if default else "visible"
42
        if not field or field.getName() not in self.field_names:
43
            return state
44
        return self.isVisible(field, mode, default)
45
46
    def isVisible(self, field, mode="view", default="visible"):
47
        """Returns if the field is visible in a given mode
48
49
        Possible returned values are:
50
        - hidden: Field rendered as a hidden input field
51
        - invisible: Field not rendered at all
52
        - visible: Field rendered as a label or editable field depending on the
53
            mode. E.g. if mode is "edit" and the value returned is "visible",
54
            the field will be rendered as an input. If the mode is "view", the
55
            field will be rendered as a span.
56
        """
57
        raise NotImplementedError("Must be implemented by subclass")
58
59
60
class ClientFieldVisibility(SenaiteATWidgetVisibility):
61
    """The Client field is editable by default in ar_add.  This adapter
62
    will force the Client field to be hidden when it should not be set
63
    by the user.
64
    """
65
    def __init__(self, context):
66
        super(ClientFieldVisibility, self).__init__(
67
            context=context, sort=10, field_names=["Client"])
68
69
    def isVisible(self, field, mode="view", default="visible"):
70
        if mode == "add":
71
            parent = self.context.aq_parent
72
            if IClient.providedBy(parent):
73
                # Note we return "hidden" here instead of "invisible": we want
74
                # the field to be auto-filled and processed on submit
75
                return "hidden"
76
            if IBatch.providedBy(parent) and parent.getClient():
77
                # The Batch has a Client assigned already!
78
                # Note we can have Batches without a client assigned
79
                return "hidden"
80
        elif mode == "edit":
81
            # This is already managed by wf permission, but is **never** a good
82
            # idea to allow the user to change the Client from an AR (basically
83
            # because otherwise, we'd need to move the object from one client
84
            # folder to another!).
85
            return "invisible"
86
        return default
87
88
89
class BatchFieldVisibility(SenaiteATWidgetVisibility):
90
    """This will force the 'Batch' field to 'hidden' in ar_add when the parent
91
    context is a Batch.
92
    """
93
    def __init__(self, context):
94
        super(BatchFieldVisibility, self).__init__(
95
            context=context, sort=10, field_names=["Batch"])
96
97
    def isVisible(self, field, mode="view", default="visible"):
98
        if IBatch.providedBy(self.context.aq_parent):
99
            return "hidden"
100
        return default
101
102
103
class PreservationFieldsVisibility(SenaiteATWidgetVisibility):
104
    """Display/Hide fields related with Preservation Workflow
105
    """
106
    def __init__(self, context):
107
        super(PreservationFieldsVisibility, self).__init__(
108
            context=context, sort=10,
109
            field_names=["DatePreserved", "Preserver"])
110
111
    def isVisible(self, field, mode="view", default="visible"):
112
        if not self.context.bika_setup.getSamplePreservationEnabled():
113
            return "invisible"
114
        return default
115
116
117
class ScheduledSamplingFieldsVisibility(SenaiteATWidgetVisibility):
118
    """Display/Hide fields related with ScheduledSampling Workflow
119
    """
120
    def __init__(self, context):
121
        super(ScheduledSamplingFieldsVisibility, self).__init__(
122
            context=context, sort=10,
123
            field_names=["ScheduledSamplingSampler", "SamplingRound"])
124
125
    def isVisible(self, field, mode="view", default="visible"):
126
        if not self.context.bika_setup.getScheduleSamplingEnabled():
127
            return "invisible"
128
        return default
129
130
131
class SamplingFieldsVisibility(SenaiteATWidgetVisibility):
132
    """
133
    This will handle Handling 'DateSampled' and 'SamplingDate' fields'
134
    visibilities based on Sampling Workflow (SWF)status. We must check the
135
    attribute saved on the sample, not the bika_setup value though. See the
136
    internal comments how it enables/disables WidgetVisibility depending on SWF.
137
    """
138
    def __init__(self, context):
139
        super(SamplingFieldsVisibility, self).__init__(
140
            context=context, sort=10,
141
            field_names=["Sampler", "DateSampled", "SamplingDate"])
142
143
    def isVisible(self, field, mode="view", default="visible"):
144
        # If object has been already created, get SWF statues from it.
145
        swf_enabled = False
146
        if hasattr(self.context, 'getSamplingWorkflowEnabled') and \
147
                self.context.getSamplingWorkflowEnabled() is not '':
148
            swf_enabled = self.context.getSamplingWorkflowEnabled()
149
        else:
150
            swf_enabled = self.context.bika_setup.getSamplingWorkflowEnabled()
151
152
        if mode == "add":
153
            if field.getName() == "DateSampled":
154
                field.required = not swf_enabled
155
                return swf_enabled and "invisible" or "edit"
156
            elif field.getName() == "SamplingDate":
157
                field.required = swf_enabled
158
                return swf_enabled and "edit" or "invisible"
159
            elif field.getName() == "Sampler":
160
                return swf_enabled and "edit" or "invisible"
161
162
        elif not swf_enabled:
163
            if field.getName() != "DateSampled":
164
                return "invisible"
165
166
        return default
167
168
169
class RegistryHiddenFieldsVisibility(SenaiteATWidgetVisibility):
170
    """Do not display fields declared in bika.lims.hiddenattributes registry key
171
    """
172
    def __init__(self, context):
173
        field_names = getHiddenAttributesForClass(context.portal_type)
174
        super(RegistryHiddenFieldsVisibility, self).__init__(
175
            context=context, sort=-1, field_names=[field_names,])
176
177
    def isVisible(self, field, mode="view", default="visible"):
178
        return "invisible"
179
180
181
class AccountancyFieldsVisibility(SenaiteATWidgetVisibility):
182
    """Display/Hide fields related with Accountancy (Discount, prices, invoice)
183
    """
184
    def __init__(self, context):
185
        super(AccountancyFieldsVisibility, self).__init__(
186
            context=context, sort=3,
187
            field_names=["BulkDiscount", "MemberDiscountApplies",
188
                         "InvoiceExclude", "MemberDiscount"])
189
190
    def isVisible(self, field, mode="view", default="visible"):
191
        if not self.context.bika_setup.getShowPrices():
192
            return "invisible"
193
        return default
194
195
196
class DateReceivedFieldVisibility(SenaiteATWidgetVisibility):
197
    """DateReceived is editable in sample context, only if all related analyses
198
    are not yet submitted and if not a secondary sample.
199
    """
200
    def __init__(self, context):
201
        super(DateReceivedFieldVisibility, self).__init__(
202
            context=context, sort=3, field_names=["DateReceived"])
203
204
    def isVisible(self, field, mode="view", default="visible"):
205
        """Returns whether the field is visible in a given mode
206
        """
207
        if mode != "edit":
208
            return default
209
210
        # If this is a Secondary Analysis Request, this field is not editable
211
        if IAnalysisRequestSecondary.providedBy(self.context):
212
            return "invisible"
213
214
        return self.context.isOpen() and "visible" or "invisible"
215
216
217 View Code Duplication
class SecondaryDateSampledFieldVisibility(SenaiteATWidgetVisibility):
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
218
    """DateSampled is editable in sample unless secondary sample
219
    """
220
    def __init__(self, context):
221
        super(SecondaryDateSampledFieldVisibility, self).__init__(
222
            context=context, sort=3, field_names=["DateSampled"])
223
224
    def isVisible(self, field, mode="view", default="visible"):
225
        """Returns whether the field is visible in a given mode
226
        """
227
        if mode != "edit":
228
            return default
229
230
        # If this is a Secondary Analysis Request, this field is not editable
231
        if IAnalysisRequestSecondary.providedBy(self.context):
232
            return "invisible"
233
        return default
234
235
236 View Code Duplication
class PrimaryAnalysisRequestFieldVisibility(SenaiteATWidgetVisibility):
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
237
    """PrimarySample field is not visible unless the current Sample is a
238
    Secondary Sample. And even in such case, the field cannot be edited
239
    """
240
    def __init__(self, context):
241
        super(PrimaryAnalysisRequestFieldVisibility, self).__init__(
242
            context=context, sort=3, field_names=["PrimaryAnalysisRequest"])
243
244
    def isVisible(self, field, mode="view", default="visible"):
245
        """Returns whether the field is visible in a given mode
246
        """
247
        if mode == "add":
248
            return default
249
250
        if not IAnalysisRequestSecondary.providedBy(self.context):
251
            # If not a secondary Analysis Request, don't render the field
252
            return "hidden"
253
254
        # No mather if the mode is edit or view, display it always as readonly
255
        if mode == "edit":
256
            return "invisible"
257
258
        return default
259
260
261
class InternalUseFieldVisibility(SenaiteATWidgetVisibility):
262
    """InternalUse field must only be visible to lab personnel
263
    """
264
    def __init__(self, context):
265
        super(InternalUseFieldVisibility, self).__init__(
266
            context=context, sort=3, field_names=["InternalUse"])
267
268
    def isVisible(self, field, mode="view", default="visible"):
269
        """Returns whether the field is visible in a given mode
270
        """
271
        return api.get_current_client() and "invisible" or default
272