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

guard_publish()   A

Complexity

Conditions 1

Size

Total Lines 9
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 9
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.workflow import getCurrentState
10
from bika.lims.workflow import isActive
11
from bika.lims.workflow import isBasicTransitionAllowed
12
from bika.lims.workflow import isTransitionAllowed
13
14
# States to be omitted in regular transitions
15
ANALYSIS_DETTACHED_STATES = ['cancelled', 'rejected', 'retracted']
16
17
def to_be_preserved(obj):
18
    """ Returns True if the Sample from this AR needs to be preserved
19
    Returns false if the Analysis Request has no Sample assigned yet or
20
    does not need to be preserved
21
    Delegates to Sample's guard_to_be_preserved
22
    """
23
    sample = obj.getSample()
24
    return sample and sample.guard_to_be_preserved()
25
26
27
def schedule_sampling(obj):
28
    """
29
    Prevent the transition if:
30
    - if the user isn't part of the sampling coordinators group
31
      and "sampling schedule" checkbox is set in bika_setup
32
    - if no date and samples have been defined
33
      and "sampling schedule" checkbox is set in bika_setup
34
    """
35
    if obj.bika_setup.getScheduleSamplingEnabled() and \
36
            isBasicTransitionAllowed(obj):
37
        return True
38
    return False
39
40
41
def receive(obj):
42
    return isBasicTransitionAllowed(obj)
43
44
45
def guard_create_partitions(analysis_request):
46
    """Returns true if partitions can be created using the analysis request
47
    passed in as the source.
48
    """
49
    if not analysis_request.bika_setup.getShowPartitions():
50
        # If partitions are disabled in Setup, return False
51
        return False
52
53
    if not isBasicTransitionAllowed(analysis_request):
54
        return False
55
56
    if analysis_request.isPartition():
57
        # Do not allow the creation of partitions from partitions
58
        return False
59
60
    return True
61
62
63
def guard_submit(analysis_request):
64
    """Return whether the transition "submit" can be performed or not.
65
    Returns True if there is at least one analysis in a non-dettached state and
66
    all analyses in a non-dettached analyses have been submitted.
67
    """
68
    analyses_ready = False
69
    for analysis in analysis_request.getAnalyses():
70
        analysis_status = api.get_workflow_status_of(api.get_object(analysis))
71
        if analysis_status in ANALYSIS_DETTACHED_STATES:
72
            continue
73
        if analysis_status in ['assigned', 'unassigned']:
74
            return False
75
        analyses_ready = True
76
    return analyses_ready
77
78
79
def guard_verify(analysis_request):
80
    """Returns whether the transition "verify" can be performed or not.
81
    Returns True if at there is at least one analysis in a non-dettached state
82
    and all analyses in a non-dettached state are in "verified" state.
83
    """
84
    analyses_ready = False
85
    for analysis in analysis_request.getAnalyses():
86
        analysis_status = api.get_workflow_status_of(api.get_object(analysis))
87
        if analysis_status in ANALYSIS_DETTACHED_STATES:
88
            continue
89
        if analysis_status != 'verified':
90
            return False
91
        analyses_ready = True
92
    return analyses_ready
93
94
95
def prepublish(obj):
96
    """Returns True if 'prepublish' transition can be applied to the Analysis
97
    Request passed in.
98
    Returns true if the Analysis Request is active (not in a cancelled/inactive
99
    state), the 'publish' transition cannot be performed yet, and at least one
100
    of its analysis is under to_be_verified state or has been already verified.
101
    As per default DC workflow definition in bika_ar_workflow, note that
102
    prepublish does not transitions the Analysis Request to any other state
103
    different from the actual one, neither its children. This 'fake' transition
104
    is only used for the prepublish action to be displayed when the Analysis
105
    Request' status is other than verified, so the labman can generate a
106
    provisional report, also if results are not yet definitive.
107
    :returns: true or false
108
    """
109
    if not isBasicTransitionAllowed(obj):
110
        return False
111
112
    if isTransitionAllowed(obj, 'publish'):
113
        return False
114
115
    analyses = obj.getAnalyses(full_objects=True)
116
    for an in analyses:
117
        # If the analysis is not active, omit
118
        if not isActive(an):
119
            continue
120
121
        # Check if the current state is 'verified'
122
        status = getCurrentState(an)
123
        if status in ['verified', 'to_be_verified']:
124
            return True
125
126
    # This analysis request has no single result ready to be verified or
127
    # verified yet. In this situation, it doesn't make sense to publish a
128
    # provisional results reports without a single result to display
129
    return False
130
131
132
def guard_publish(analysis_request):
133
    """Returns True if 'publish' transition can be applied to the Analysis
134
    Request passed in. Returns true if the Analysis Request is active (not in
135
    a cancelled/inactive state). As long as 'publish' transition, in accordance
136
    with its DC workflow can only be performed if its previous state is
137
    verified or published, there is no need of additional validations.
138
    :returns: true or false
139
    """
140
    return isBasicTransitionAllowed(analysis_request)
141
142
143
def guard_rollback_to_receive(analysis_request):
144
    """Return whether 'rollback_to_receive' transition can be performed or not
145
    """
146
    # Can rollback to receive if at least one analysis hasn't been submitted yet
147
    # or if all analyses have been rejected or retracted
148
    analyses = analysis_request.getAnalyses()
149
    skipped = 0
150
    for analysis in analyses:
151
        analysis_object = api.get_object(analysis)
152
        state = getCurrentState(analysis_object)
153
        if state in ["unassigned", "assigned"]:
154
            return True
155
        if state in ["retracted", "rejected"]:
156
            skipped += 1
157
    return len(analyses) == skipped
158
159
160
def guard_cancel(analysis_request):
161
    """Returns whether 'cancel' transition can be performed or not. Returns
162
    True only if all analyses are in "unassigned" status
163
    """
164
    # Ask to partitions
165
    for partition in analysis_request.getDescendants(all_descendants=False):
166
        if not isTransitionAllowed(partition, "cancel"):
167
            return False
168
169
    # Look through analyses
170
    for analysis in analysis_request.getAnalyses():
171
        analysis_object = api.get_object(analysis)
172
        if api.get_workflow_status_of(analysis_object) != "unassigned":
173
            return False
174
175
    return True
176
177
178
def guard_reinstate(analysis_request):
179
    """Returns whether 'reinstate" transition can be performed or not. Returns
180
    True only if this is not a partition or the parent analysis request can be
181
    reinstated
182
    """
183
    parent = analysis_request.getParentAnalysisRequest()
184
    return not parent or isTransitionAllowed(parent, "reinstate")
185