Passed
Push — master ( 1b98f4...c06457 )
by Ramon
09:26 queued 04:32
created

()   A

Complexity

Conditions 5

Size

Total Lines 17
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 14
dl 0
loc 17
rs 9.2333
c 0
b 0
f 0
cc 5
nop 2
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
""" Bika setup handlers. """
9
10
from Products.CMFCore.utils import getToolByName
11
from Products.CMFPlone.utils import _createObjectByType
12
from bika.lims import logger
13
from bika.lims.catalog import getCatalogDefinitions
14
from bika.lims.catalog import setup_catalogs
15
from bika.lims.config import *
16
from bika.lims.interfaces import IARImportFolder, IHaveNoBreadCrumbs
17
from bika.lims.utils import tmpID
18
from zope.interface import alsoProvides
19
20
GROUPS = {
21
    # Dictionary {group_name: [roles]}
22
    "Analysts": ["Analyst", ],
23
    "Clients": ["Client", ],
24
    "LabClerks": ["LabClerk",],
25
    # TODO Unbound LabManagers from Manager role
26
    "LabManagers": ["LabManager", "Manager", ],
27
    "Preservers": ["Perserver", ],
28
    "Publishers": ["Publisher", ],
29
    "Verifiers": ["Verifier", ],
30
    "Samplers": ["Sampler", ],
31
    "RegulatoryInspectors": ["RegulatoryInspector", ],
32
    "SamplingCoordinators": ["SamplingCoordinator", ],
33
}
34
35
# noinspection PyClassHasNoInit
36
class Empty:
37
    pass
38
39
40
class BikaGenerator(object):
41
    def __init__(self):
42
        pass
43
44
    def setupPortalContent(self, portal):
45
        """ Setup Bika site structure """
46
        self.remove_default_content(portal)
47
        self.reindex_structure(portal)
48
49
        portal.bika_setup.laboratory.unmarkCreationFlag()
50
        portal.bika_setup.laboratory.reindexObject()
51
52
    def reindex_structure(self, portal):
53
        # index objects - importing through GenericSetup doesn't
54
        for obj_id in ('clients',
55
                       'batches',
56
                       'invoices',
57
                       'pricelists',
58
                       'bika_setup',
59
                       'methods',
60
                       'analysisrequests',
61
                       'referencesamples',
62
                       'supplyorders',
63
                       'worksheets',
64
                       'reports',
65
                       'arimports',
66
                       ):
67
            try:
68
                obj = portal[obj_id]
69
                obj.unmarkCreationFlag()
70
                obj.reindexObject()
71
            except AttributeError:
72
                pass
73
74
        for obj_id in ('bika_analysiscategories',
75
                       'bika_analysisservices',
76
                       'bika_attachmenttypes',
77
                       'bika_batchlabels',
78
                       'bika_calculations',
79
                       'bika_departments',
80
                       'bika_containers',
81
                       'bika_containertypes',
82
                       'bika_preservations',
83
                       'bika_identifiertypes',
84
                       'bika_instruments',
85
                       'bika_instrumenttypes',
86
                       'bika_instrumentlocations',
87
                       'bika_analysisspecs',
88
                       'bika_analysisprofiles',
89
                       'bika_artemplates',
90
                       'bika_labcontacts',
91
                       'bika_labproducts',
92
                       'bika_manufacturers',
93
                       'bika_sampleconditions',
94
                       'bika_samplematrices',
95
                       'bika_samplingdeviations',
96
                       'bika_samplepoints',
97
                       'bika_sampletypes',
98
                       'bika_srtemplates',
99
                       'bika_reflexrulefolder',
100
                       'bika_storagelocations',
101
                       'bika_subgroups',
102
                       'bika_suppliers',
103
                       'bika_referencedefinitions',
104
                       'bika_worksheettemplates'):
105
            try:
106
                obj = portal.bika_setup[obj_id]
107
                obj.unmarkCreationFlag()
108
                obj.reindexObject()
109
            except AttributeError:
110
                pass
111
112
    def remove_default_content(self, portal):
113
        # remove undesired content objects
114
        del_ids = []
115
        for obj_id in ['Members', 'news', 'events']:
116
            if obj_id in portal:
117
                del_ids.append(obj_id)
118
        if del_ids:
119
            portal.manage_delObjects(ids=del_ids)
120
121
    def setupGroupsAndRoles(self, portal):
122
        # Create groups
123
        groups_ids = portal.portal_groups.listGroupIds()
124
        groups_ids = filter(lambda gr: gr not in groups_ids, GROUPS.keys())
125
        for group_id in groups_ids:
126
            portal.portal_groups.addGroup(group_id, title=group_id,
127
                                          roles=GROUPS[group_id])
128
129
    def setupCatalogs(self, portal):
130
        # an item should belong to only one catalog.
131
        # that way looking it up means first looking up *the* catalog
132
        # in which it is indexed, as well as making it cheaper to index.
133
134
        def addIndex(cat, *args):
135
            # noinspection PyBroadException
136
            try:
137
                cat.addIndex(*args)
138
            except:
139
                pass
140
141
        def addColumn(cat, col):
142
            # noinspection PyBroadException
143
            try:
144
                cat.addColumn(col)
145
            except:
146
                pass
147
148
        # create lexicon
149
        wordSplitter = Empty()
150
        wordSplitter.group = 'Word Splitter'
151
        wordSplitter.name = 'Unicode Whitespace splitter'
152
        caseNormalizer = Empty()
153
        caseNormalizer.group = 'Case Normalizer'
154
        caseNormalizer.name = 'Unicode Case Normalizer'
155
        stopWords = Empty()
156
        stopWords.group = 'Stop Words'
157
        stopWords.name = 'Remove listed and single char words'
158
        elem = [wordSplitter, caseNormalizer, stopWords]
159
        zc_extras = Empty()
160
        zc_extras.index_type = 'Okapi BM25 Rank'
161
        zc_extras.lexicon_id = 'Lexicon'
162
163
        # bika_catalog
164
165
        bc = getToolByName(portal, 'bika_catalog', None)
166
        if bc is None:
167
            logger.warning('Could not find the bika_catalog tool.')
168
            return
169
170
        # noinspection PyBroadException
171
        try:
172
            bc.manage_addProduct['ZCTextIndex'].manage_addLexicon(
173
                'Lexicon', 'Lexicon', elem)
174
        except:
175
            logger.warning('Could not add ZCTextIndex to bika_catalog')
176
            pass
177
178
        at = getToolByName(portal, 'archetype_tool')
179
        at.setCatalogsByType('Batch', ['bika_catalog', 'portal_catalog'])
180
        # TODO Remove in >v1.3.0
181
        at.setCatalogsByType('Sample', ['bika_catalog', 'portal_catalog'])
182
        # TODO Remove in >v1.3.0
183
        at.setCatalogsByType('SamplePartition',
184
                             ['bika_catalog', 'portal_catalog'])
185
        at.setCatalogsByType('ReferenceSample',
186
                             ['bika_catalog', 'portal_catalog'])
187
188
        addIndex(bc, 'path', 'ExtendedPathIndex', 'getPhysicalPath')
189
        addIndex(bc, 'allowedRolesAndUsers', 'KeywordIndex')
190
        addIndex(bc, 'UID', 'FieldIndex')
191
        addIndex(bc, 'SearchableText', 'ZCTextIndex', zc_extras)
192
        addIndex(bc, 'Title', 'ZCTextIndex', zc_extras)
193
        addIndex(bc, 'Description', 'ZCTextIndex', zc_extras)
194
        addIndex(bc, 'id', 'FieldIndex')
195
        addIndex(bc, 'getId', 'FieldIndex')
196
        addIndex(bc, 'Type', 'FieldIndex')
197
        addIndex(bc, 'portal_type', 'FieldIndex')
198
        addIndex(bc, 'created', 'DateIndex')
199
        addIndex(bc, 'Creator', 'FieldIndex')
200
        addIndex(bc, 'getObjPositionInParent', 'GopipIndex')
201
        addIndex(bc, 'title', 'FieldIndex', 'Title')
202
        addIndex(bc, 'sortable_title', 'FieldIndex')
203
        addIndex(bc, 'description', 'FieldIndex', 'Description')
204
        addIndex(bc, 'review_state', 'FieldIndex')
205
        addIndex(bc, 'Identifiers', 'KeywordIndex')
206
        addIndex(bc, 'is_active', 'BooleanIndex')
207
        addIndex(bc, 'BatchDate', 'DateIndex')
208
        addIndex(bc, 'getClientTitle', 'FieldIndex')
209
        addIndex(bc, 'getClientUID', 'FieldIndex')
210
        addIndex(bc, 'getClientID', 'FieldIndex')
211
        addIndex(bc, 'getClientBatchID', 'FieldIndex')
212
        addIndex(bc, 'getDateReceived', 'DateIndex')
213
        addIndex(bc, 'getDateSampled', 'DateIndex')
214
        addIndex(bc, 'getDueDate', 'DateIndex')
215
        addIndex(bc, 'getExpiryDate', 'DateIndex')
216
        addIndex(bc, 'getReferenceDefinitionUID', 'FieldIndex')
217
        addIndex(bc, 'getSampleTypeTitle', 'FieldIndex')
218
        addIndex(bc, 'getSampleTypeUID', 'FieldIndex')
219
220
        # https://github.com/senaite/senaite.core/pull/1091
221
        addIndex(bc, 'getSupportedServices', 'KeywordIndex')
222
        addIndex(bc, 'getBlank', 'BooleanIndex')
223
        addIndex(bc, 'isValid', 'BooleanIndex')
224
225
        addColumn(bc, 'path')
226
        addColumn(bc, 'UID')
227
        addColumn(bc, 'id')
228
        addColumn(bc, 'getId')
229
        addColumn(bc, 'Type')
230
        addColumn(bc, 'portal_type')
231
        addColumn(bc, 'creator')
232
        addColumn(bc, 'Created')
233
        addColumn(bc, 'Title')
234
        addColumn(bc, 'Description')
235
        addColumn(bc, 'sortable_title')
236
        addColumn(bc, 'getClientTitle')
237
        addColumn(bc, 'getClientID')
238
        addColumn(bc, 'getClientBatchID')
239
        addColumn(bc, 'getSampleTypeTitle')
240
        addColumn(bc, 'getDateReceived')
241
        addColumn(bc, 'getDateSampled')
242
        addColumn(bc, 'review_state')
243
244
        # bika_setup_catalog
245
246
        bsc = getToolByName(portal, 'bika_setup_catalog', None)
247
        if bsc is None:
248
            logger.warning('Could not find the setup catalog tool.')
249
            return
250
251
        # noinspection PyBroadException
252
        try:
253
            bsc.manage_addProduct['ZCTextIndex'].manage_addLexicon(
254
                'Lexicon', 'Lexicon', elem)
255
        except:
256
            logger.warning('Could not add ZCTextIndex to bika_setup_catalog')
257
            pass
258
259
        at = getToolByName(portal, 'archetype_tool')
260
        at.setCatalogsByType('Department',
261
                             ['bika_setup_catalog', "portal_catalog", ])
262
        at.setCatalogsByType('Container', ['bika_setup_catalog', ])
263
        at.setCatalogsByType('ContainerType', ['bika_setup_catalog', ])
264
        at.setCatalogsByType('AnalysisCategory', ['bika_setup_catalog', ])
265
        at.setCatalogsByType('AnalysisService',
266
                             ['bika_setup_catalog', 'portal_catalog'])
267
        at.setCatalogsByType('AnalysisSpec', ['bika_setup_catalog', ])
268
        at.setCatalogsByType('SampleCondition', ['bika_setup_catalog'])
269
        at.setCatalogsByType('SampleMatrix', ['bika_setup_catalog', ])
270
        at.setCatalogsByType('SampleType',
271
                             ['bika_setup_catalog', 'portal_catalog'])
272
        at.setCatalogsByType('SamplePoint',
273
                             ['bika_setup_catalog', 'portal_catalog'])
274
        at.setCatalogsByType('StorageLocation',
275
                             ['bika_setup_catalog', 'portal_catalog'])
276
        at.setCatalogsByType('SamplingDeviation', ['bika_setup_catalog', ])
277
        at.setCatalogsByType('IdentifierType', ['bika_setup_catalog', ])
278
        at.setCatalogsByType('Instrument',
279
                             ['bika_setup_catalog', 'portal_catalog'])
280
        at.setCatalogsByType('InstrumentType',
281
                             ['bika_setup_catalog', 'portal_catalog'])
282
        at.setCatalogsByType('InstrumentLocation',
283
                             ['bika_setup_catalog', 'portal_catalog'])
284
        at.setCatalogsByType('Method', ['bika_setup_catalog', 'portal_catalog'])
285
        at.setCatalogsByType('Multifile', ['bika_setup_catalog'])
286
        at.setCatalogsByType('AttachmentType', ['bika_setup_catalog', ])
287
        at.setCatalogsByType('Attachment', ['portal_catalog'])
288
        at.setCatalogsByType('Calculation',
289
                             ['bika_setup_catalog', 'portal_catalog'])
290
        at.setCatalogsByType('AnalysisProfile',
291
                             ['bika_setup_catalog', 'portal_catalog'])
292
        at.setCatalogsByType('ARTemplate',
293
                             ['bika_setup_catalog', 'portal_catalog'])
294
        at.setCatalogsByType('LabProduct',
295
                             ['bika_setup_catalog', 'portal_catalog'])
296
        at.setCatalogsByType('LabContact',
297
                             ['bika_setup_catalog', 'portal_catalog'])
298
        at.setCatalogsByType('Manufacturer',
299
                             ['bika_setup_catalog', 'portal_catalog'])
300
        at.setCatalogsByType('Preservation', ['bika_setup_catalog', ])
301
        at.setCatalogsByType('ReferenceDefinition',
302
                             ['bika_setup_catalog', 'portal_catalog'])
303
        at.setCatalogsByType('SRTemplate',
304
                             ['bika_setup_catalog', 'portal_catalog'])
305
        at.setCatalogsByType('SubGroup', ['bika_setup_catalog', ])
306
        at.setCatalogsByType('Supplier',
307
                             ['bika_setup_catalog', 'portal_catalog'])
308
        at.setCatalogsByType('Unit', ['bika_setup_catalog', ])
309
        at.setCatalogsByType('WorksheetTemplate',
310
                             ['bika_setup_catalog', 'portal_catalog'])
311
        at.setCatalogsByType('BatchLabel', ['bika_setup_catalog', ])
312
313
        addIndex(bsc, 'path', 'ExtendedPathIndex', 'getPhysicalPath')
314
        addIndex(bsc, 'allowedRolesAndUsers', 'KeywordIndex')
315
        addIndex(bsc, 'UID', 'FieldIndex')
316
        addIndex(bsc, 'SearchableText', 'ZCTextIndex', zc_extras)
317
        addIndex(bsc, 'Title', 'ZCTextIndex', zc_extras)
318
        addIndex(bsc, 'Description', 'ZCTextIndex', zc_extras)
319
        addIndex(bsc, 'id', 'FieldIndex')
320
        addIndex(bsc, 'getId', 'FieldIndex')
321
        addIndex(bsc, 'Type', 'FieldIndex')
322
        addIndex(bsc, 'portal_type', 'FieldIndex')
323
        addIndex(bsc, 'created', 'DateIndex')
324
        addIndex(bsc, 'Creator', 'FieldIndex')
325
        addIndex(bsc, 'getObjPositionInParent', 'GopipIndex')
326
        addIndex(bc, 'Identifiers', 'KeywordIndex')
327
328
        addIndex(bsc, 'title', 'FieldIndex', 'Title')
329
        addIndex(bsc, 'sortable_title', 'FieldIndex')
330
        addIndex(bsc, 'description', 'FieldIndex', 'Description')
331
332
        addIndex(bsc, 'review_state', 'FieldIndex')
333
334
        addIndex(bsc, 'getAccredited', 'FieldIndex')
335
        addIndex(bsc, 'getAnalyst', 'FieldIndex')
336
        addIndex(bsc, 'getBlank', 'FieldIndex')
337
        addIndex(bsc, 'getCalculationTitle', 'FieldIndex')
338
        addIndex(bsc, 'getCalculationUID', 'FieldIndex')
339
        addIndex(bsc, 'getCalibrationExpiryDate', 'FieldIndex')
340
        addIndex(bsc, 'getCategoryTitle', 'FieldIndex')
341
        addIndex(bsc, 'getCategoryUID', 'FieldIndex')
342
        addIndex(bsc, 'getClientUID', 'FieldIndex')
343
        addIndex(bsc, 'getDepartmentTitle', 'FieldIndex')
344
        addIndex(bsc, 'getDocumentID', 'FieldIndex')
345
        addIndex(bsc, 'getDuplicateVariation', 'FieldIndex')
346
        addIndex(bsc, 'getFormula', 'FieldIndex')
347
        addIndex(bsc, 'getFullname', 'FieldIndex')
348
        addIndex(bsc, 'getHazardous', 'FieldIndex')
349
        addIndex(bsc, 'getInstrumentLocationName', 'FieldIndex')
350
        addIndex(bsc, 'getInstrumentTitle', 'FieldIndex')
351
        addIndex(bsc, 'getInstrumentType', 'FieldIndex')
352
        addIndex(bsc, 'getInstrumentTypeName', 'FieldIndex')
353
        addIndex(bsc, 'getKeyword', 'FieldIndex')
354
        addIndex(bsc, 'getManagerEmail', 'FieldIndex')
355
        addIndex(bsc, 'getManagerName', 'FieldIndex')
356
        addIndex(bsc, 'getManagerPhone', 'FieldIndex')
357
        addIndex(bsc, 'getMaxTimeAllowed', 'FieldIndex')
358
        addIndex(bsc, 'getMethodID', 'FieldIndex')
359
        addIndex(bsc, 'getAvailableMethodUIDs', 'KeywordIndex')
360
        addIndex(bsc, 'getModel', 'FieldIndex')
361
        addIndex(bsc, 'getName', 'FieldIndex')
362
        addIndex(bsc, 'getPointOfCapture', 'FieldIndex')
363
        addIndex(bsc, 'getPrice', 'FieldIndex')
364
        addIndex(bsc, 'getSamplePointTitle', 'KeywordIndex')
365
        addIndex(bsc, 'getSamplePointUID', 'FieldIndex')
366
        addIndex(bsc, 'getSampleTypeTitle', 'FieldIndex')
367
        addIndex(bsc, 'getSampleTypeTitles', 'KeywordIndex')
368
        addIndex(bsc, 'getSampleTypeUID', 'FieldIndex')
369
        addIndex(bsc, 'getServiceUID', 'FieldIndex')
370
        addIndex(bsc, 'getServiceUIDs', 'KeywordIndex')
371
        addIndex(bsc, 'getTotalPrice', 'FieldIndex')
372
        addIndex(bsc, 'getUnit', 'FieldIndex')
373
        addIndex(bsc, 'getVATAmount', 'FieldIndex')
374
        addIndex(bsc, 'getVolume', 'FieldIndex')
375
        addIndex(bsc, 'is_active', 'BooleanIndex')
376
377
        addColumn(bsc, 'path')
378
        addColumn(bsc, 'UID')
379
        addColumn(bsc, 'id')
380
        addColumn(bsc, 'getId')
381
        addColumn(bsc, 'Type')
382
        addColumn(bsc, 'portal_type')
383
        addColumn(bsc, 'getObjPositionInParent')
384
385
        addColumn(bsc, 'Title')
386
        addColumn(bsc, 'Description')
387
        addColumn(bsc, 'title')
388
        addColumn(bsc, 'sortable_title')
389
        addColumn(bsc, 'description')
390
        addColumn(bsc, 'review_state')
391
        addColumn(bsc, 'getAccredited')
392
        addColumn(bsc, 'getInstrumentType')
393
        addColumn(bsc, 'getInstrumentTypeName')
394
        addColumn(bsc, 'getInstrumentLocationName')
395
        addColumn(bsc, 'getBlank')
396
        addColumn(bsc, 'getCalculationTitle')
397
        addColumn(bsc, 'getCalculationUID')
398
        addColumn(bsc, 'getCalibrationExpiryDate')
399
        addColumn(bsc, 'getCategoryTitle')
400
        addColumn(bsc, 'getCategoryUID')
401
        addColumn(bsc, 'getClientUID')
402
        addColumn(bsc, 'getDepartmentTitle')
403
        addColumn(bsc, 'getDuplicateVariation')
404
        addColumn(bsc, 'getFormula')
405
        addColumn(bsc, 'getFullname')
406
        addColumn(bsc, 'getHazardous')
407
        addColumn(bsc, 'getInstrumentTitle')
408
        addColumn(bsc, 'getKeyword')
409
        addColumn(bsc, 'getManagerName')
410
        addColumn(bsc, 'getManagerPhone')
411
        addColumn(bsc, 'getManagerEmail')
412
        addColumn(bsc, 'getMaxTimeAllowed')
413
        addColumn(bsc, 'getModel')
414
        addColumn(bsc, 'getName')
415
        addColumn(bsc, 'getPointOfCapture')
416
        addColumn(bsc, 'getPrice')
417
        addColumn(bsc, 'getSamplePointTitle')
418
        addColumn(bsc, 'getSamplePointUID')
419
        addColumn(bsc, 'getSampleTypeTitle')
420
        addColumn(bsc, 'getSampleTypeUID')
421
        addColumn(bsc, 'getServiceUID')
422
        addColumn(bsc, 'getTotalPrice')
423
        addColumn(bsc, 'getUnit')
424
        addColumn(bsc, 'getVATAmount')
425
        addColumn(bsc, 'getVolume')
426
427
        # portal_catalog
428
        pc = getToolByName(portal, 'portal_catalog', None)
429
        if pc is None:
430
            logger.warning('Could not find the portal_catalog tool.')
431
            return
432
        addIndex(pc, 'Analyst', 'FieldIndex')
433
        addColumn(pc, 'Analyst')
434
        # TODO: Nmrl
435
        addColumn(pc, 'getProvince')
436
        addColumn(pc, 'getDistrict')
437
438
        # Setting up all LIMS catalogs defined in catalog folder
439
        setup_catalogs(portal, getCatalogDefinitions())
440
441
    def setupTopLevelFolders(self, context):
442
        workflow = getToolByName(context, "portal_workflow")
443
        obj_id = 'arimports'
444
        if obj_id in context.objectIds():
445
            obj = context._getOb(obj_id)
446
            # noinspection PyBroadException
447
            try:
448
                workflow.doActionFor(obj, "hide")
449
            except:
450
                pass
451
            obj.setLayout('@@arimports')
452
            alsoProvides(obj, IARImportFolder)
453
            alsoProvides(obj, IHaveNoBreadCrumbs)
454
455
456
def create_CAS_IdentifierType(portal):
457
    """LIMS-1391 The CAS Nr IdentifierType is normally created by
458
    setuphandlers during site initialisation.
459
    """
460
    bsc = getToolByName(portal, 'bika_setup_catalog', None)
461
    idtypes = bsc(portal_type='IdentifierType', title='CAS Nr')
462
    if not idtypes:
463
        folder = portal.bika_setup.bika_identifiertypes
464
        idtype = _createObjectByType('IdentifierType', folder, tmpID())
465
        idtype.processForm()
466
        idtype.edit(title='CAS Nr',
467
                    description='Chemical Abstracts Registry number',
468
                    portal_types=['Analysis Service'])
469
470
471
def setupVarious(context):
472
    """
473
    Final Bika import steps.
474
    """
475
    if context.readDataFile('bika.lims_various.txt') is None:
476
        return
477
478
    site = context.getSite()
479
    gen = BikaGenerator()
480
    gen.setupGroupsAndRoles(site)
481
    gen.setupPortalContent(site)
482
    gen.setupTopLevelFolders(site)
483
    gen.setupCatalogs(site)
484
485
    # Plone's jQuery gets clobbered when jsregistry is loaded.
486
    setup = site.portal_setup
487
    setup.runImportStepFromProfile(
488
        'profile-plone.app.jquery:default', 'jsregistry')
489
    # setup.runImportStepFromProfile('profile-plone.app.jquerytools:default',
490
    #  'jsregistry')
491
492
    create_CAS_IdentifierType(site)
493