Passed
Push — master ( 6d6a8c...6374c8 )
by Ramon
05:17
created

AnalysisRequestAnalysesView.get_currency_symbol()   A

Complexity

Conditions 1

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 6
dl 0
loc 8
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.content.analysisspec import ResultsRangeDict
14
from bika.lims.utils import dicts_to_dict
15
from bika.lims.utils import get_image
16
from bika.lims.utils import get_link
17
from bika.lims.utils import logged_in_client
18
from bika.lims.utils import t
19
from bika.lims.workflow import wasTransitionPerformed
20
from plone.memoize import view
21
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
22
from zope.i18n.locales import locales
23
24
25
class AnalysisRequestAnalysesView(BikaListingView):
26
    """AR Manage Analyses View
27
    """
28
    template = ViewPageTemplateFile("templates/analysisrequest_analyses.pt")
29
30
    def __init__(self, context, request):
31
        super(AnalysisRequestAnalysesView, self).__init__(context, request)
32
33
        self.catalog = "bika_setup_catalog"
34
        self.contentFilter = {
35
            "portal_type": "AnalysisService",
36
            "sort_on": "sortable_title",
37
            "sort_order": "ascending",
38
            "inactive_state": "active"
39
        }
40
        self.context_actions = {}
41
        self.icon = "{}/{}".format(
42
            self.portal_url,
43
            "++resource++bika.lims.images/analysisservice_big.png"
44
        )
45
        self.show_column_toggles = False
46
        self.show_select_column = True
47
        self.show_select_all_checkbox = False
48
        self.pagesize = 999999
49
        self.show_search = True
50
        self.fetch_transitions_on_select = False
51
52
        self.categories = []
53
        self.selected = []
54
        self.do_cats = self.context.bika_setup.getCategoriseAnalysisServices()
55
        if self.do_cats:
56
            self.show_categories = True
57
            self.expand_all_categories = False
58
59
        self.columns = collections.OrderedDict((
60
            ("Title", {
61
                "title": _("Service"),
62
                "index": "sortable_title",
63
                "sortable": False}),
64
            ("Unit", {
65
                "title": _("Unit"),
66
                "sortable": False}),
67
            ("Hidden", {
68
                "title": _("Hidden"),
69
                "sortable": False,
70
                "type": "boolean"}),
71
            ("Price", {
72
                "title": _("Price"),
73
                "sortable": False}),
74
            ("Partition", {
75
                "title": _("Partition"),
76
                "sortable": False,
77
                "type": "choices"}),
78
            ("warn_min", {
79
                "title": _("Min warn")}),
80
            ("min", {
81
                "title": _("Min")}),
82
            ("warn_max", {
83
                "title": _("Max warn")}),
84
            ("max", {
85
                "title": _("Max")}),
86
        ))
87
88
        columns = ["Title", "Unit", "Hidden", ]
89
        if self.show_prices():
90
            columns.append("Price")
91
        if self.show_partitions():
92
            columns.append("Partition")
93
        if self.show_ar_specs():
94
            columns.append("warn_min")
95
            columns.append("min")
96
            columns.append("warn_max")
97
            columns.append("max")
98
99
        self.review_states = [
100
            {
101
                "id": "default",
102
                "title": _("All"),
103
                "contentFilter": {"inactive_state": "active"},
104
                "columns": columns,
105
                "transitions": [{"id": "disallow-all-possible-transitions"}],
106
                "custom_transitions": [
107
                    {
108
                        "id": "save_analyses_button",
109
                        "title": _("Save")
110
                    }
111
                ],
112
            },
113
        ]
114
115
    def update(self):
116
        """Update hook
117
        """
118
        super(AnalysisRequestAnalysesView, self).update()
119
        analyses = self.context.getAnalyses(full_objects=True)
120
        self.analyses = dict([(a.getServiceUID(), a) for a in analyses])
121
        self.selected = self.analyses.keys()
122
123
    @view.memoize
124
    def show_prices(self):
125
        """Checks if prices should be shown or not
126
        """
127
        setup = api.get_setup()
128
        return setup.getShowPrices()
129
130
    @view.memoize
131
    def show_partitions(self):
132
        """Checks if partitions should be shown
133
        """
134
        setup = api.get_setup()
135
        return setup.getShowPartitions()
136
137
    @view.memoize
138
    def show_ar_specs(self):
139
        """Checks if AR specs should be shown or not
140
        """
141
        setup = api.get_setup()
142
        return setup.getEnableARSpecs()
143
144
    @view.memoize
145
    def get_results_range(self):
146
        """Get the results Range from the AR
147
        """
148
        spec = self.context.getResultsRange()
149
        if spec:
150
            return dicts_to_dict(spec, "keyword")
151
        return ResultsRangeDict()
152
153
    @view.memoize
154
    def get_partitions(self):
155
        """Get the partitions
156
        """
157
        sample = self.context.getSample()
158
        return sample.objectValues("SamplePartition")
159
160
    def get_partition(self, analysis):
161
        """Get the partition of the Analysis
162
        """
163
        partition = analysis.getSamplePartition()
164
        if not partition:
165
            return self.get_partitions()[0]
166
        return partition
167
168
    @view.memoize
169
    def get_currency_symbol(self):
170
        """Get the currency Symbol
171
        """
172
        locale = locales.getLocale('en')
173
        setup = api.get_setup()
174
        currency = setup.getCurrency()
175
        return locale.numbers.currencies[currency].symbol
176
177
    def is_submitted(self, obj):
178
        """Check if the "submit" transition was performed
179
        """
180
        return wasTransitionPerformed(obj, "submit")
181
182
    @view.memoize
183
    def get_logged_in_client(self):
184
        """Return the logged in client
185
        """
186
        return logged_in_client(self.context)
187
188
    def get_editable_columns(self, obj):
189
        """Return editable fields
190
        """
191
        columns = ["Partition", "min", "max", "warn_min", "warn_max", "Hidden"]
192
        if not self.get_logged_in_client():
193
            columns.append("Price")
194
        return columns
195
196
    def folderitems(self):
197
        """XXX refactor if possible to non-classic mode
198
        """
199
        items = super(AnalysisRequestAnalysesView, self).folderitems()
200
        self.categories.sort()
201
        return items
202
203
    def folderitem(self, obj, item, index):
204
        """Service triggered each time an item is iterated in folderitems.
205
206
        The use of this service prevents the extra-loops in child objects.
207
208
        :obj: the instance of the class to be foldered
209
        :item: dict containing the properties of the object to be used by
210
            the template
211
        :index: current index of the item
212
        """
213
        # ensure we have an object and not a brain
214
        obj = api.get_object(obj)
215
        uid = api.get_uid(obj)
216
217
        # settings for this analysis
218
        service_settings = self.context.getAnalysisServiceSettings(uid)
219
        hidden = service_settings.get("hidden", obj.getHidden())
220
221
        # get the category
222
        category = obj.getCategoryTitle()
223
        item["category"] = category
224
        if category not in self.categories:
225
            self.categories.append(category)
226
227
        parts = filter(api.is_active, self.get_partitions())
228
        partitions = map(lambda part: {
229
            "ResultValue": part.Title(), "ResultText": part.getId()}, parts)
230
231
        keyword = obj.getKeyword()
232
        partition = None
233
        if uid in self.analyses:
234
            analysis = self.analyses[uid]
235
            # Might differ from the service keyword
236
            keyword = analysis.getKeyword()
237
            # Mark the row as disabled if the analysis is not in an open state
238
            item["disabled"] = not analysis.isOpen()
239
            # get the hidden status of the analysis
240
            hidden = analysis.getHidden()
241
            # get the partition of the analysis
242
            partition = self.get_partition(analysis)
243
        else:
244
            partition = self.get_partitions()[0]
245
246
        # get the specification of this object
247
        rr = self.get_results_range()
248
        spec = rr.get(keyword, ResultsRangeDict())
249
250
        item["Title"] = obj.Title()
251
        item["Unit"] = obj.getUnit()
252
        item["Price"] = obj.getPrice()
253
        item["before"]["Price"] = self.get_currency_symbol()
254
        item["allow_edit"] = self.get_editable_columns(obj)
255
        item["selected"] = uid in self.selected
256
        item["min"] = str(spec.get("min", ""))
257
        item["max"] = str(spec.get("max", ""))
258
        item["warn_min"] = str(spec.get("warn_min", ""))
259
        item["warn_max"] = str(spec.get("warn_max", ""))
260
        item["Hidden"] = hidden
261
        item["Partition"] = partition.getId()
262
        item["choices"]["Partition"] = partitions
263
264
        # Append info link before the service
265
        # see: bika.lims.site.coffee for the attached event handler
266
        item["before"]["Title"] = get_link(
267
            "analysisservice_info?service_uid={}".format(uid),
268
            value="<span class='glyphicon glyphicon-info-sign'></span>",
269
            css_class="service_info")
270
271
        # Icons
272
        after_icons = ""
273
        if obj.getAccredited():
274
            after_icons += get_image(
275
                "accredited.png", title=t(_("Accredited")))
276
        if obj.getAttachmentOption() == "r":
277
            after_icons += get_image(
278
                "attach_reqd.png", title=t(_("Attachment required")))
279
        if obj.getAttachmentOption() == "n":
280
            after_icons += get_image(
281
                "attach_no.png", title=t(_('Attachment not permitted')))
282
        if after_icons:
283
            item["after"]["Title"] = after_icons
284
285
        return item
286