Passed
Push — master ( f5ec93...b1a244 )
by Jordi
04:40
created

before_sample()   A

Complexity

Conditions 3

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 3
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 DateTime import DateTime
22
from bika.lims import api
23
from bika.lims.interfaces import IDetachedPartition
24
from bika.lims.interfaces import IReceived, IVerified, IAnalysisRequestPartition
25
from bika.lims.utils import changeWorkflowState
26
from bika.lims.utils.analysisrequest import create_retest
27
from bika.lims.workflow import get_prev_status_from_history
28
from bika.lims.workflow.analysisrequest import AR_WORKFLOW_ID, \
29
    do_action_to_descendants, do_action_to_analyses, do_action_to_ancestors
30
from zope.interface import alsoProvides
31
from zope.interface import noLongerProvides
32
33
34
def before_sample(analysis_request):
35
    """Method triggered before "sample" transition for the Analysis Request
36
    passed in is performed
37
    """
38
    if not analysis_request.getDateSampled():
39
        analysis_request.setDateSampled(DateTime())
40
    if not analysis_request.getSampler():
41
        analysis_request.setSampler(api.get_current_user().id)
42
43
44
def after_reject(analysis_request):
45
    """Method triggered after a 'reject' transition for the Analysis Request
46
    passed in is performed. Cascades the transition to descendants (partitions)
47
    and analyses as well. If "notify on rejection" setting is enabled, sends a
48
    notification to the client contact.
49
    """
50
    do_action_to_descendants(analysis_request, "reject")
51
    do_action_to_analyses(analysis_request, "reject")
52
53
54
def after_retract(analysis_request):
55
    """Method triggered after a 'retract' transition for the Analysis Request
56
    passed in is performed. Cascades the transition to descendants (partitions)
57
    and analyses as well.
58
    """
59
    do_action_to_descendants(analysis_request, "retract")
60
    do_action_to_analyses(analysis_request, "retract")
61
62
63
def after_invalidate(obj):
64
    """Function triggered after 'invalidate' transition for the Analysis
65
    Request passed in is performed. Creates a retest
66
    """
67
    create_retest(obj)
68
69
70
def after_submit(analysis_request):
71
    """Function called after a 'submit' transition is triggered. Promotes the
72
    submission of ancestors and descendants (partitions).
73
    """
74
    # This transition is not meant to be triggered manually by the user, rather
75
    # promoted by analyses. Hence, there is no need to cascade the transition
76
    # to the analyses the analysis request contains.
77
    do_action_to_ancestors(analysis_request, "submit")
78
    do_action_to_descendants(analysis_request, "submit")
79
80
81
def after_verify(analysis_request):
82
    """Method triggered after a 'verify' transition for the Analysis Request
83
    passed in is performed. Promotes the 'verify' transition to ancestors,
84
    descendants and to the analyses that belong to the analysis request.
85
    """
86
    # Mark this analysis request as IReceived
87
    alsoProvides(analysis_request, IVerified)
88
89
    # This transition is not meant to be triggered manually by the user, rather
90
    # promoted by analyses. Hence, there is no need to cascade the transition
91
    # to the analyses the analysis request contains.
92
    do_action_to_ancestors(analysis_request, "verify")
93
    do_action_to_descendants(analysis_request, "verify")
94
95
96
def after_publish(analysis_request):
97
    """Method triggered after an 'publish' transition for the Analysis Request
98
    passed in is performed. Performs the 'publish' transition Publishes the
99
    descendant partitions and all analyses associated to the analysis request
100
    as well.
101
    """
102
    do_action_to_descendants(analysis_request, "publish")
103
    do_action_to_analyses(analysis_request, "publish")
104
105
106
def after_reinstate(analysis_request):
107
    """Method triggered after a 'reinstate' transition for the Analysis Request
108
    passed in is performed. Sets its status to the last status before it was
109
    cancelled. Reinstates the descendant partitions and all the analyses
110
    associated to the analysis request as well.
111
    """
112
    do_action_to_descendants(analysis_request, "reinstate")
113
    do_action_to_analyses(analysis_request, "reinstate")
114
115
    # Force the transition to previous state before the request was cancelled
116
    prev_status = get_prev_status_from_history(analysis_request, "cancelled")
117
    changeWorkflowState(analysis_request, AR_WORKFLOW_ID, prev_status,
118
                        action="reinstate")
119
    analysis_request.reindexObject()
120
121
122
def after_cancel(analysis_request):
123
    """Method triggered after a 'cancel' transition for the Analysis Request
124
    passed in is performed. Cascades this transition to its analyses and
125
    partitions.
126
    """
127
    do_action_to_descendants(analysis_request, "cancel")
128
    do_action_to_analyses(analysis_request, "cancel")
129
130
131
def after_receive(analysis_request):
132
    """Method triggered after "receive" transition for the Analysis Request
133
    passed in is performed
134
    """
135
    # Mark this analysis request as IReceived
136
    alsoProvides(analysis_request, IReceived)
137
138
    analysis_request.setDateReceived(DateTime())
139
    do_action_to_analyses(analysis_request, "initialize")
140
141
142
def after_sample(analysis_request):
143
    """Method triggered after "sample" transition for the Analysis Request
144
    passed in is performed
145
    """
146
    analysis_request.setDateSampled(DateTime())
147
    idxs = ['getDateSampled']
148
    for analysis in analysis_request.getAnalyses(full_objects=True):
149
        analysis.reindexObject(idxs=idxs)
150
151
152
def after_rollback_to_receive(analysis_request):
153
    """Function triggered after "rollback to receive" transition is performed
154
    """
155
    if IVerified.providedBy(analysis_request):
156
        noLongerProvides(analysis_request, IVerified)
157
158
159
def after_detach(analysis_request):
160
    """Function triggered after "detach" transition is performed
161
    """
162
    # Unbind the sample from its parent (the primary)
163
    parent = analysis_request.getParentAnalysisRequest()
164
    analysis_request.setParentAnalysisRequest(None)
165
166
    # Assign the primary from which the sample has been detached
167
    analysis_request.setDetachedFrom(parent)
168
169
    # This sample is no longer a partition
170
    noLongerProvides(analysis_request, IAnalysisRequestPartition)
171
172
    # And we mark the sample with IDetachedPartition
173
    alsoProvides(analysis_request, IDetachedPartition)
174
175
    # Reindex both the parent and the detached one
176
    analysis_request.reindexObject()
177
    parent.reindexObject()
178