Passed
Push — master ( bcbb8c...8785a0 )
by Jordi
05:37 queued 01:13
created

ReferenceSamplesView.get_editable_columns()   A

Complexity

Conditions 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 4
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
import collections
9
10
from bika.lims import api
11
from bika.lims import bikaMessageFactory as _
12
from bika.lims.browser.bika_listing import BikaListingView
13
from bika.lims.browser.worksheet.tools import showRejectionMessage
14
from bika.lims.interfaces import IRoutineAnalysis
15
from bika.lims.permissions import EditWorksheet
16
from bika.lims.permissions import ManageWorksheets
17
from bika.lims.utils import get_link
18
from plone.memoize import view
19
from plone.protect import CheckAuthenticator
20
21
22
class ReferenceSamplesView(BikaListingView):
23
    """Displays reference control samples
24
    """
25
26
    def __init__(self, context, request):
27
        super(ReferenceSamplesView, self).__init__(context, request)
28
29
        self.catalog = "bika_catalog"
30
        self.contentFilter = {
31
            "portal_type": "ReferenceSample",
32
            "getSupportedServices": self.get_assigned_services_uids(),
33
            "isValid": True,
34
            "review_state": "current",
35
            "inactive_state": "active",
36
            "sort_on": "sortable_title",
37
            "sort_order": "ascending",
38
        }
39
40
        self.context_actions = {}
41
        self.title = _("Add Control Reference")
42
        self.show_sort_column = False
43
        self.show_select_row = False
44
        self.show_select_all_checkbox = False
45
        self.show_column_toggles = False
46
        self.show_select_column = True
47
        self.show_categories = False
48
        self.pagesize = 999999
49
        self.allow_edit = True
50
        self.show_search = False
51
52
        self.icon = "{}/{}".format(
53
            self.portal_url,
54
            "/++resource++bika.lims.images/worksheet_big.png"
55
        )
56
57
        self.columns = collections.OrderedDict((
58
            ("Title", {
59
                "title": _("Reference Sample"),
60
                "sortable": False}),
61
            ("SupportedServices", {
62
                "title": _("Supported Services"),
63
                "type": "multiselect",
64
                "sortable": False}),
65
            ("Position", {
66
                "title": _("Position"),
67
                "sortable": False}),
68
        ))
69
70
        self.review_states = [
71
            {
72
                "id": "default",
73
                "title": _("All"),
74
                "contentFilter": {},
75
                "transitions": [{"id": "add"}],
76
                "custom_transitions": [
77
                    {
78
                        "id": "add",
79
                        "title": _("Add"),
80
                        "url": self.__name__,
81
                    }
82
                ],
83
                "columns": self.columns.keys()
84
            },
85
        ]
86
87
    def __call__(self):
88
        template = super(ReferenceSamplesView, self).__call__()
89
        # TODO: Refactor Worfklow
90
        grant = self.is_edit_allowed() and self.is_manage_allowed()
91
        if not grant:
92
            redirect_url = api.get_url(self.context)
93
            return self.request.response.redirect(redirect_url)
94
        # TODO: Refactor this function call
95
        showRejectionMessage(self.context)
96
        # Handle form submission
97
        if self.request.form.get("submitted"):
98
            CheckAuthenticator(self.request)
99
            self.handle_submit()
100
        return template
101
102
    def update(self):
103
        """Update hook
104
        """
105
        super(ReferenceSamplesView, self).update()
106
107
    def handle_submit(self):
108
        """Handle form submission
109
        """
110
        form = self.request.form
111
        # Selected service UIDs
112
        uids = form.get("uids")
113
        # reference sample -> selected services mapping
114
        supported_services = form.get("SupportedServices")
115
        # service -> position mapping
116
        positions = form.get("Position")[0]
117
        for uid in uids:
118
            position = positions.get(uid)
119
            if position == "new":
120
                position = None
121
            service_uids = supported_services.get(uid)
122
            referencesample = api.get_object_by_uid(uid)
123
            self.context.addReferenceAnalyses(
124
                referencesample, service_uids, dest_slot=position)
125
        redirect_url = "{}/{}".format(
126
            api.get_url(self.context), "manage_results")
127
        self.request.response.redirect(redirect_url)
128
129
    @view.memoize
130
    def is_edit_allowed(self):
131
        """Check if edit is allowed
132
        """
133
        checkPermission = self.context.portal_membership.checkPermission
134
        return checkPermission(EditWorksheet, self.context)
135
136
    @view.memoize
137
    def is_manage_allowed(self):
138
        """Check if manage is allowed
139
        """
140
        checkPermission = self.context.portal_membership.checkPermission
141
        return checkPermission(ManageWorksheets, self.context)
142
143
    @view.memoize
144
    def get_editable_columns(self):
145
        """Return editable fields
146
        """
147
        columns = ["Position", "SupportedServices"]
148
        return columns
149
150
    @view.memoize
151
    def get_assigned_services(self):
152
        """Get the current assigned services of this Worksheet
153
        """
154
        analyses = self.context.getAnalyses()
155
        routine_analyses = filter(
156
            lambda an: IRoutineAnalysis.providedBy(an), analyses)
157
        services = map(lambda an: an.getAnalysisService(), routine_analyses)
158
        return services
159
160
    @view.memoize
161
    def get_assigned_services_uids(self):
162
        """Get the current assigned services UIDs of this Worksheet
163
        """
164
        services = self.get_assigned_services()
165
        uids = map(api.get_uid, services)
166
        return list(set(uids))
167
168
    def get_supported_services_uids(self, referencesample):
169
        """Get the supported services of the reference sample
170
        """
171
        uids = referencesample.getSupportedServices(only_uids=True)
172
        return list(set(uids))
173
174
    def make_supported_services_choices(self, referencesample):
175
        """Create choices for supported services
176
        """
177
        choices = []
178
        assigned_services = self.get_assigned_services_uids()
179
        for uid in self.get_supported_services_uids(referencesample):
180
            service = api.get_object(uid)
181
            title = api.get_title(service)
182
            selected = uid in assigned_services
183
            choices.append({
184
                "ResultValue": uid,
185
                "ResultText": title,
186
                "selected": selected,
187
            })
188
        return choices
189
190
    @view.memoize
191
    def make_position_choices(self):
192
        """Create choices for available positions
193
        """
194
        choices = []
195
        for pos in self.get_available_positions():
196
            choices.append({
197
                "ResultValue": pos,
198
                "ResultText": pos,
199
            })
200
        return choices
201
202
    @view.memoize
203
    def get_available_positions(self):
204
        """Return a list of empty slot numbers
205
        """
206
        available_positions = ["new"]
207
        layout = self.context.getLayout()
208
        used_positions = [int(slot["position"]) for slot in layout]
209
        if used_positions:
210
            used = [
211
                pos for pos in range(1, max(used_positions) + 1) if
212
                pos not in used_positions]
213
            available_positions.extend(used)
214
        return available_positions
215
216
    def folderitem(self, obj, item, index):
217
        """Service triggered each time an item is iterated in folderitems.
218
219
        The use of this service prevents the extra-loops in child objects.
220
221
        :obj: the instance of the class to be foldered
222
        :item: dict containing the properties of the object to be used by
223
            the template
224
        :index: current index of the item
225
        """
226
        item = super(ReferenceSamplesView, self).folderitem(obj, item, index)
227
228
        # ensure we have an object and not a brain
229
        obj = api.get_object(obj)
230
        url = api.get_url(obj)
231
        title = api.get_title(obj)
232
233
        item["Title"] = title
234
        item["replace"]["Title"] = get_link(url, value=title)
235
        item["allow_edit"] = self.get_editable_columns()
236
237
        # Supported Services
238
        supported_services_choices = self.make_supported_services_choices(obj)
239
        item["choices"]["SupportedServices"] = supported_services_choices
240
241
        # Position
242
        item["Position"] = "new"
243
        item["choices"]["Position"] = self.make_position_choices()
244
245
        return item
246