Passed
Push — 2.x ( 2459cb...f048b4 )
by Ramon
06:30
created

Container.getPreservations()   A

Complexity

Conditions 4

Size

Total Lines 10
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 10
dl 0
loc 10
rs 9.9
c 0
b 0
f 0
cc 4
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-2021 by it's authors.
19
# Some rights reserved, see README and LICENSE.
20
21
22
import json
23
import plone.protect
24
from AccessControl import ClassSecurityInfo
25
from bika.lims import bikaMessageFactory as _
26
from bika.lims.browser.fields import UIDReferenceField
27
from bika.lims.browser.widgets import ReferenceWidget
28
from bika.lims.catalog.bikasetup_catalog import SETUP_CATALOG
29
from bika.lims.config import PROJECTNAME
30
from bika.lims.content.bikaschema import BikaSchema
31
from bika.lims.interfaces import IContainer
32
from bika.lims.interfaces import IDeactivable
33
from magnitude import mg
34
from operator import itemgetter
35
from Products.Archetypes.atapi import registerType
36
from Products.Archetypes.BaseContent import BaseContent
37
from Products.Archetypes.Field import BooleanField
38
from Products.Archetypes.Field import StringField
39
from Products.Archetypes.Schema import Schema
40
from Products.Archetypes.Widget import BooleanWidget
41
from Products.Archetypes.Widget import StringWidget
42
from Products.CMFCore.utils import getToolByName
43
from senaite.core.p3compat import cmp
44
from zope.interface import implements
45
46
schema = BikaSchema.copy() + Schema((
47
    UIDReferenceField(
48
        "ContainerType",
49
        required=0,
50
        allowed_types=("ContainerType",),
51
        widget=ReferenceWidget(
52
            label=_("Container Type"),
53
            showOn=True,
54
            catalog_name=SETUP_CATALOG,
55
            base_query={
56
                "is_active": True,
57
                "sort_on": "sortable_title",
58
                "sort_order": "ascending"
59
            },
60
        ),
61
    ),
62
    StringField('Capacity',
63
        required = 1,
64
        default = "0 ml",
65
        widget = StringWidget(
66
            label=_("Capacity"),
67
            description=_("Maximum possible size or volume of samples."),
68
        ),
69
    ),
70
    BooleanField('PrePreserved',
71
        validators = ('container_prepreservation_validator'),
72
        default = False,
73
        widget = BooleanWidget(
74
            label=_("Pre-preserved"),
75
            description = _(
76
                "Check this box if this container is already preserved."
77
                "Setting this will short-circuit the preservation workflow "
78
                "for sample partitions stored in this container."),
79
        ),
80
    ),
81
    UIDReferenceField(
82
        "Preservation",
83
        required=0,
84
        allowed_types=("Preservation",),
85
        widget=ReferenceWidget(
86
            label=_("Preservation"),
87
            description=_(
88
                "If this container is pre-preserved, then the preservation "
89
                "method could be selected here."
90
            ),
91
            showOn=True,
92
            catalog_name=SETUP_CATALOG,
93
            base_query={
94
                "is_active": True,
95
                "sort_on": "sortable_title",
96
                "sort_order": "ascending"
97
            },
98
        ),
99
    ),
100
    BooleanField('SecuritySealIntact',
101
        default = True,
102
        widget = BooleanWidget(
103
            label=_("Security Seal Intact Y/N"),
104
        ),
105
    ),
106
))
107
schema['description'].widget.visible = True
108
schema['description'].schemata = 'default'
109
110
111
class Container(BaseContent):
112
    implements(IContainer, IDeactivable)
113
    security = ClassSecurityInfo()
114
    displayContentsTab = False
115
    schema = schema
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable schema does not seem to be defined.
Loading history...
116
117
    _at_rename_after_creation = True
118
    def _renameAfterCreation(self, check_auto_id=False):
119
        from bika.lims.idserver import renameAfterCreation
120
        renameAfterCreation(self)
121
122 View Code Duplication
    def getJSCapacity(self, **kw):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
123
        """Try convert the Capacity to 'ml' or 'g' so that JS has an
124
        easier time working with it.  If conversion fails, return raw value.
125
        """
126
        default = self.Schema()['Capacity'].get(self)
127
        try:
128
            mgdefault = default.split(' ', 1)
129
            mgdefault = mg(float(mgdefault[0]), mgdefault[1])
130
        except Exception:
131
            mgdefault = mg(0, 'ml')
132
        try:
133
            return str(mgdefault.ounit('ml'))
134
        except Exception:
135
            pass
136
        try:
137
            return str(mgdefault.ounit('g'))
138
        except Exception:
139
            pass
140
        return str(default)
141
142
143
registerType(Container, PROJECTNAME)
144
145
146
# TODO: Refactor!
147
#       This class is registered as `getcontainers` and used in artemplate to
148
#       populate the combogrid field
149 View Code Duplication
class ajaxGetContainers:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
150
151
    catalog_name='senaite_catalog_setup'
152
    contentFilter = {'portal_type': 'SampleContainer',
153
                     'is_active': True}
154
155
    def __init__(self, context, request):
156
        self.context = context
157
        self.request = request
158
159
    def __call__(self):
160
161
        plone.protect.CheckAuthenticator(self.request)
162
        searchTerm = 'searchTerm' in self.request and self.request[
163
            'searchTerm'].lower() or ''
164
        page = self.request['page']
165
        nr_rows = self.request['rows']
166
        sord = self.request['sord']
167
        sidx = self.request['sidx']
168
        rows = []
169
170
        # lookup objects from ZODB
171
        catalog = getToolByName(self.context, self.catalog_name)
172
        brains = catalog(self.contentFilter)
173
        brains = searchTerm and \
174
            [p for p in brains if p.Title.lower().find(searchTerm) > -1] \
175
            or brains
176
177
        rows = [{'UID': p.UID,
178
                 'container_uid': p.UID,
179
                 'Container': p.Title,
180
                 'Description': p.Description}
181
                for p in brains]
182
183
        rows = sorted(rows, cmp=lambda x, y: cmp(x.lower(
184
        ), y.lower()), key=itemgetter(sidx and sidx or 'Container'))
185
        if sord == 'desc':
186
            rows.reverse()
187
        pages = len(rows) / int(nr_rows)
188
        pages += divmod(len(rows), int(nr_rows))[1] and 1 or 0
189
        ret = {'page': page,
190
               'total': pages,
191
               'records': len(rows),
192
               'rows': rows[(int(page) - 1) * int(nr_rows): int(page) * int(nr_rows)]}
193
        return json.dumps(ret)
194