Passed
Push — master ( 1513bd...0193a4 )
by Ramon
05:35
created

bika.lims.workflow.analysis.guards.guard_publish()   A

Complexity

Conditions 1

Size

Total Lines 6
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 1
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 bika.lims import api
9
from bika.lims.interfaces.analysis import IRequestAnalysis
10
from bika.lims import workflow as wf
11
12
13
def attach(obj):
14
    if not wf.isBasicTransitionAllowed(obj):
15
        return False
16
    if not obj.getAttachment():
17
        return obj.getAttachmentOption() != 'r'
18
    return True
19
20
21
def dependencies_guard(analysis, transition_id):
22
    """Return whether the transition(s) passed in can be performed or not to
23
    the dependencies of the analysis passed in
24
    """
25
    if isinstance(transition_id, list):
26
        for transition_id in transition_id:
27
            if not dependencies_guard(analysis, transition_id):
28
                return False
29
        return True
30
31
    for dependency in analysis.getDependencies():
32
        if not wf.isTransitionAllowed(dependency, transition_id):
33
            if not wf.wasTransitionPerformed(dependency, transition_id):
34
                return False
35
    return True
36
37
38
def guard_assign(analysis):
39
    """Return whether the transition "assign" can be performed or not
40
    """
41
    # TODO Workflow - Analysis. Assign guard to return True only in WS.Add?
42
    #      We need "unassigned" analyses to appear in Worksheet Add analyses.
43
    #      Hence, it returns True if the analysis has not been assigned to any
44
    #      worksheet yet. The problem is this can end up (if the 'assign'
45
    #      transition is displayed in listings other than WS Add Analyses)
46
    #      with an analysis transitioned to 'assigned' state, but without
47
    #      a worksheet assigned!. This transition should only be triggered by
48
    #      content.worksheet.addAnalysis (see that func for more info)
49
50
    # Cannot assign if the Sample has not been received
51
    if not analysis.isSampleReceived():
52
        return False
53
54
    # Check if only LabManager and Manager roles can manage worksheets
55
    if analysis.bika_setup.getRestrictWorksheetManagement():
56
        member = api.get_current_user()
57
        super_roles = ["LabManager", "Manager"]
58
        if (len(set(super_roles) - set(member.getRoles())) == len(super_roles)):
59
            # Current user is not a "super-user"
60
            return False
61
62
    # Cannot assign if the analysis has a worksheet assigned already
63
    if analysis.getWorksheet():
64
        return False
65
66
    return True
67
68
69
def guard_unassign(analysis):
70
    """Return whether the transition "unassign" can be performed or not
71
    """
72
    # Check if only LabManager and Manager roles can manage worksheets
73
    if analysis.bika_setup.getRestrictWorksheetManagement():
74
        member = api.get_current_user()
75
        super_roles = ["LabManager", "Manager"]
76
        if (len(set(super_roles) - set(member.getRoles())) == len(super_roles)):
77
            # Current user is not a "super-user"
78
            return False
79
80
    # Cannot unassign if the analysis does not have a worksheet assigned
81
    worksheet = analysis.getWorksheet()
82
    if not worksheet:
83
        return False
84
85
    # Cannot unassign if the worksheet is not open
86
    if api.get_workflow_status_of(worksheet) != "open":
87
        return False
88
89
    return True
90
91
92
def guard_cancel(analysis):
93
    """Return whether the transition "cancel" can be performed or not. Returns
94
    True only when the Analysis Request the analysis belongs to is in cancelled
95
    state. Otherwise, returns False.
96
    """
97
    return not api.is_active(analysis.getRequest())
98
99
100
def guard_reinstate(analysis):
101
    """Return whether the transition "reinstate" can be performed or not.
102
    Returns True only when the Analysis Request the analysis belongs to is in a
103
    non-cancelled state. Otherwise, returns False.
104
    """
105
    return api.is_active(analysis.getRequest())
106
107
108
def guard_submit(analysis):
109
    """Return whether the transition "submit" can be performed or not
110
    """
111
    # Cannot submit without a result
112
    if not analysis.getResult():
113
        return False
114
115
    # Cannot submit with interims without value
116
    for interim in analysis.getInterimFields():
117
        if not interim.get("value", ""):
118
            return False
119
120
    # Check if can submit based on the Analysis Request state
121
    if IRequestAnalysis.providedBy(analysis):
122
        point_of_capture = analysis.getPointOfCapture()
123
        # Cannot submit if the Sample has not been received
124
        if point_of_capture == "lab" and not analysis.isSampleReceived():
125
            return False
126
        # Cannot submit if the Sample has not been sampled
127
        if point_of_capture == "field" and not analysis.isSampleSampled():
128
            return False
129
130
    # Check if the current user can submit if is not assigned
131
    if not analysis.bika_setup.getAllowToSubmitNotAssigned():
132
        member = api.get_current_user()
133
        super_roles = ["LabManager", "Manager"]
134
        if (len(set(super_roles) - set(member.getRoles())) == len(super_roles)):
135
            # Cannot submit if unassigned
136
            if not analysis.getAnalyst():
137
                return False
138
            # Cannot submit if assigned analyst is not the current user
139
            if analysis.getAnalyst() != member.getId():
140
                return False
141
142
    # Check dependencies (analyses this analysis depends on)
143
    return dependencies_guard(analysis, "submit")
144
145
146 View Code Duplication
def guard_multi_verify(analysis):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
147
    """Return whether the transition "multi_verify" can be performed or not
148
    The transition multi_verify will only take place if multi-verification of
149
    results is enabled.
150
    """
151
    # If there is only one remaining verification, return False
152
    remaining_verifications = analysis.getNumberOfRemainingVerifications()
153
    if remaining_verifications <= 1:
154
        return False
155
156
    # Check if the current user is the same who submitted the result
157
    user_id = api.get_current_user().getId()
158
    if (analysis.getSubmittedBy() == user_id):
159
        if not analysis.isSelfVerificationEnabled():
160
            return False
161
162
    # Check if user is the last verifier and consecutive multi-verification is
163
    # disabled
164
    verifiers = analysis.getVerificators()
165
    mv_type = analysis.bika_setup.getTypeOfmultiVerification()
166
    if verifiers and verifiers[:-1] == user_id \
167
            and mv_type == "self_multi_not_cons":
168
        return False
169
170
    # Check if user verified before and self multi-verification is disabled
171
    if user_id in verifiers and mv_type == "self_multi_disabled":
172
        return False
173
174
    # Check dependencies (analyses this analysis depends on)
175
    return dependencies_guard(analysis, ["verify", "multi_verify"])
176
177
178 View Code Duplication
def guard_verify(analysis):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
179
    """Return whether the transition "verify" can be performed or not
180
    """
181
    # Check if multi-verification
182
    remaining_verifications = analysis.getNumberOfRemainingVerifications()
183
    if remaining_verifications > 1:
184
        return False
185
186
    # Check if the current user is the same that submitted the result
187
    user_id = api.get_current_user().getId()
188
    if (analysis.getSubmittedBy() == user_id):
189
        if not analysis.isSelfVerificationEnabled():
190
            return False
191
192
    if analysis.getNumberOfRequiredVerifications() <= 1:
193
        # Check dependencies (analyses this analysis depends on)
194
        return dependencies_guard(analysis, "verify")
195
196
    # This analysis requires more than one verification
197
    # Check if user is the last verifier and consecutive multi-verification is
198
    # disabled
199
    verifiers = analysis.getVerificators()
200
    mv_type = analysis.bika_setup.getTypeOfmultiVerification()
201
    if verifiers and verifiers[:-1] == user_id \
202
            and mv_type == "self_multi_not_cons":
203
        return False
204
205
    # Check if user verified before and self multi-verification is disabled
206
    if user_id in verifiers and mv_type == "self_multi_disabled":
207
        return False
208
209
    # Check dependencies (analyses this analysis depends on)
210
    return dependencies_guard(analysis, ["verify", "multi_verify"])
211
212
213
def guard_retract(analysis):
214
    """ Return whether the transition "retract" can be performed or not
215
    """
216
    # Cannot retract if there are dependents that cannot be retracted
217
    for dependent in analysis.getDependents():
218
        if not wf.isTransitionAllowed(dependent, "retract"):
219
            return False
220
221
    # Cannot retract if all dependencies have been verified
222
    dependencies = analysis.getDependencies()
223
    if not dependencies:
224
        return True
225
    for dependency in dependencies:
226
        if not wf.wasTransitionPerformed(dependency, "verify"):
227
            return True
228
229
    return False
230
231
232
def guard_reject(analysis):
233
    """Return whether the transition "reject" can be performed or not
234
    """
235
    # Cannot reject if there are dependents that cannot be rejected
236
    for dependent in analysis.getDependents():
237
        if not wf.isTransitionAllowed(dependent, "reject"):
238
            return False
239
240
    return True
241
242
243
def guard_publish(analysis):
244
    """Return whether the transition "publish" can be performed or not. Returns
245
    True only when the Analysis Request the analysis belongs to is in published
246
    state. Otherwise, returns False.
247
    """
248
    return api.get_workflow_status_of(analysis.getRequest()) == "published"
249