Passed
Push — 2.x ( 00f734...bf6542 )
by Jordi
07:33
created

senaite.core.content.senaitesetup   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 261
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 19
eloc 157
dl 0
loc 261
rs 10
c 0
b 0
f 0

1 Function

Rating   Name   Duplication   Size   Complexity  
A default_email_body_sample_publication() 0 11 2

14 Methods

Rating   Name   Duplication   Size   Complexity  
A Setup.setEmailBodySamplePublication() 0 6 1
A Setup.getSampleAnalysesRequired() 0 6 1
A Setup.getEmailBodySamplePublication() 0 13 3
A Setup.getEnableGlobalAuditlog() 0 6 1
A Setup.getImmediateResultsEntry() 0 6 1
A Setup.setEnableGlobalAuditlog() 0 10 2
A Setup.getSiteLogoCSS() 0 6 1
A Setup.setCategorizeSampleAnalyses() 0 6 1
A Setup.setSampleAnalysesRequired() 0 6 1
A Setup.setSiteLogo() 0 6 1
A Setup.getSiteLogo() 0 6 1
A Setup.setSiteLogoCSS() 0 6 1
A Setup.getCategorizeSampleAnalyses() 0 6 1
A Setup.setImmediateResultsEntry() 0 6 1
1
# -*- coding: utf-8 -*-
2
3
from AccessControl import ClassSecurityInfo
4
from bika.lims import api
5
from plone.app.textfield import IRichTextValue
6
from plone.app.textfield.widget import RichTextFieldWidget  # TBD: port to core
7
from plone.autoform import directives
8
from plone.formwidget.namedfile.widget import NamedFileFieldWidget
9
from plone.supermodel import model
10
from Products.CMFCore import permissions
11
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
12
from senaite.core.catalog import AUDITLOG_CATALOG
13
from senaite.core.content.base import Container
14
from senaite.core.interfaces import IHideActionsMenu
15
from senaite.core.interfaces import ISetup
16
from senaite.core.schema import RichTextField
17
from senaite.impress import senaiteMessageFactory as _
18
from zope import schema
19
from zope.interface import implementer
20
from zope.interface import provider
21
from zope.schema.interfaces import IContextAwareDefaultFactory
22
23
24
@provider(IContextAwareDefaultFactory)
25
def default_email_body_sample_publication(context):
26
    """Returns the default body text for publication emails
27
    """
28
    view = api.get_view("senaite_view", context=api.get_setup())
29
    if view is None:
30
        # Test fixture
31
        return u""
32
    tpl = ViewPageTemplateFile(
33
        "../browser/setup/templates/email_body_sample_publication.pt")
34
    return tpl(view)
35
36
37
class ISetupSchema(model.Schema):
38
    """Schema and marker interface
39
    """
40
41
    directives.widget("email_body_sample_publication", RichTextFieldWidget)
42
    email_body_sample_publication = RichTextField(
43
        title=_("title_senaitesetup_publication_email_text",
44
                default=u"Publication Email Text"),
45
        description=_(
46
            "description_senaitesetup_publication_email_text",
47
            default=u"Set the email body text to be used by default "
48
            "when sending out result reports to the selected recipients. "
49
            "You can use reserved keywords: "
50
            "$client_name, $recipients, $lab_name, $lab_address"),
51
        defaultFactory=default_email_body_sample_publication,
52
        required=False,
53
    )
54
55
    enable_global_auditlog = schema.Bool(
56
        title=_(u"Enable global Auditlog"),
57
        description=_(
58
            "The global Auditlog shows all modifications of the system. "
59
            "When enabled, all entities will be indexed in a separate "
60
            "catalog. This will increase the time when objects are "
61
            "created or modified."
62
        ),
63
        default=False,
64
    )
65
66
    # NOTE:
67
    # We use the `NamedFileFieldWidget` instead of `NamedImageFieldWidget`
68
    # by purpose! Using the latter rises this PIL error (appears only in log):
69
    # IOError: cannot identify image file <cStringIO.StringI object at ...>
70
    directives.widget("site_logo", NamedFileFieldWidget)
71
    site_logo = schema.Bytes(
72
        title=_(u"Site Logo"),
73
        description=_(u"This shows a custom logo on your SENAITE site."),
74
        required=False,
75
    )
76
77
    site_logo_css = schema.ASCII(
78
        title=_(u"Site Logo CSS"),
79
        description=_(
80
            u"Add custom CSS rules for the Logo, "
81
            u"e.g. height:15px; width:150px;"
82
        ),
83
        required=False,
84
    )
85
86
    immediate_results_entry = schema.Bool(
87
        title=_(u"Immediate results entry"),
88
        description=_(
89
            "description_senaitesetup_immediateresultsentry",
90
            default=u"Allow the user to directly enter results after sample "
91
            "creation, e.g. to enter field results immediately, or lab "
92
            "results, when the automatic sample reception is activated."
93
        ),
94
    )
95
96
    categorize_sample_analyses = schema.Bool(
97
        title=_("title_senaitesetup_categorizesampleanalyses",
98
                default=u"Categorize sample analyses"),
99
        description=_(
100
            "description_senaitesetup_categorizesampleanalyses",
101
            default=u"Group analyses by category for samples"
102
        ),
103
        default=False,
104
    )
105
106
    sample_analyses_required = schema.Bool(
107
        title=_("title_senaitesetup_sampleanalysesrequired",
108
                default=u"Require sample analyses"),
109
        description=_(
110
            "description_senaitesetup_sampleanalysesrequired",
111
            default=u"Analyses are required for sample registration"
112
        ),
113
        default=True,
114
    )
115
116
    ###
117
    # Fieldsets
118
    ###
119
    model.fieldset(
120
        "analyses",
121
        label=_("label_senaitesetup_fieldset_analyses", default=u"Analyses"),
122
        fields=[
123
            "immediate_results_entry",
124
            "categorize_sample_analyses",
125
            "sample_analyses_required",
126
        ]
127
    )
128
129
    model.fieldset(
130
        "notifications",
131
        label=_(u"Notifications"),
132
        fields=[
133
            "email_body_sample_publication",
134
        ]
135
    )
136
137
    model.fieldset(
138
        "appearance",
139
        label=_(u"Appearance"),
140
        fields=[
141
            "site_logo",
142
            "site_logo_css",
143
        ]
144
    )
145
146
147
@implementer(ISetup, ISetupSchema, IHideActionsMenu)
148
class Setup(Container):
149
    """SENAITE Setup Folder
150
    """
151
    security = ClassSecurityInfo()
152
153
    @security.protected(permissions.View)
154
    def getEmailBodySamplePublication(self):
155
        """Returns the transformed email body text for publication emails
156
        """
157
        accessor = self.accessor("email_body_sample_publication")
158
        value = accessor(self)
159
        if IRichTextValue.providedBy(value):
160
            # Transforms the raw value to the output mimetype
161
            value = value.output_relative_to(self)
162
        if not value:
163
            # Always fallback to default value
164
            value = default_email_body_sample_publication(self)
165
        return value
166
167
    @security.protected(permissions.ModifyPortalContent)
168
    def setEmailBodySamplePublication(self, value):
169
        """Set email body text for publication emails
170
        """
171
        mutator = self.mutator("email_body_sample_publication")
172
        return mutator(self, value)
173
174
    @security.protected(permissions.View)
175
    def getEnableGlobalAuditlog(self):
176
        """Returns if the global Auditlog is enabled
177
        """
178
        accessor = self.accessor("enable_global_auditlog")
179
        return accessor(self)
180
181
    @security.protected(permissions.ModifyPortalContent)
182
    def setEnableGlobalAuditlog(self, value):
183
        """Enable/Disable global Auditlogging
184
        """
185
        if value is False:
186
            # clear the auditlog catalog
187
            catalog = api.get_tool(AUDITLOG_CATALOG)
188
            catalog.manage_catalogClear()
189
        mutator = self.mutator("enable_global_auditlog")
190
        return mutator(self, value)
191
192
    @security.protected(permissions.View)
193
    def getSiteLogo(self):
194
        """Returns the global site logo
195
        """
196
        accessor = self.accessor("site_logo")
197
        return accessor(self)
198
199
    @security.protected(permissions.ModifyPortalContent)
200
    def setSiteLogo(self, value):
201
        """Set the site logo
202
        """
203
        mutator = self.mutator("site_logo")
204
        return mutator(self, value)
205
206
    @security.protected(permissions.View)
207
    def getSiteLogoCSS(self):
208
        """Returns the global site logo
209
        """
210
        accessor = self.accessor("site_logo_css")
211
        return accessor(self)
212
213
    @security.protected(permissions.ModifyPortalContent)
214
    def setSiteLogoCSS(self, value):
215
        """Set the site logo
216
        """
217
        mutator = self.mutator("site_logo_css")
218
        return mutator(self, value)
219
220
    @security.protected(permissions.View)
221
    def getImmediateResultsEntry(self):
222
        """Returns if immediate results entry is enabled or not
223
        """
224
        accessor = self.accessor("immediate_results_entry")
225
        return accessor(self)
226
227
    @security.protected(permissions.ModifyPortalContent)
228
    def setImmediateResultsEntry(self, value):
229
        """Enable/Disable global Auditlogging
230
        """
231
        mutator = self.mutator("immediate_results_entry")
232
        return mutator(self, value)
233
234
    @security.protected(permissions.View)
235
    def getCategorizeSampleAnalyses(self):
236
        """Returns if analyses should be grouped by category for samples
237
        """
238
        accessor = self.accessor("categorize_sample_analyses")
239
        return accessor(self)
240
241
    @security.protected(permissions.ModifyPortalContent)
242
    def setCategorizeSampleAnalyses(self, value):
243
        """Enable/Disable grouping of analyses by category for samples
244
        """
245
        mutator = self.mutator("categorize_sample_analyses")
246
        return mutator(self, value)
247
248
    @security.protected(permissions.View)
249
    def getSampleAnalysesRequired(self):
250
        """Returns if analyses are required in sample add form
251
        """
252
        accessor = self.accessor("sample_analyses_required")
253
        return accessor(self)
254
255
    @security.protected(permissions.ModifyPortalContent)
256
    def setSampleAnalysesRequired(self, value):
257
        """Allow/Disallow to create samples without analyses
258
        """
259
        mutator = self.mutator("sample_analyses_required")
260
        return mutator(self, value)
261