From cae4591142c48c3ac05ba66b50633a6b5292943b Mon Sep 17 00:00:00 2001 From: Espurna Date: Thu, 25 Jan 2018 11:58:52 +0100 Subject: [PATCH 01/17] sample type AdmittedStickerTemplates field + AdmittedStickerTemplates widget --- bika/lims/browser/widgets/__init__.py | 1 + .../widgets/sampletypestickerswidget.py | 22 +++ bika/lims/content/sampletype.py | 151 ++++++++++++++++-- .../bika_widgets/sampletypestickerswidget.js | 47 ++++++ bika/lims/vocabularies/__init__.py | 4 +- 5 files changed, 212 insertions(+), 13 deletions(-) create mode 100644 bika/lims/browser/widgets/sampletypestickerswidget.py create mode 100644 bika/lims/skins/bika/bika_widgets/sampletypestickerswidget.js diff --git a/bika/lims/browser/widgets/__init__.py b/bika/lims/browser/widgets/__init__.py index e91e0b208f..4c7332f5d3 100644 --- a/bika/lims/browser/widgets/__init__.py +++ b/bika/lims/browser/widgets/__init__.py @@ -29,3 +29,4 @@ from .rejectionwidget import RejectionWidget from .priorityselectionwidget import PrioritySelectionWidget from .comboboxwidget import ComboBoxWidget +from .sampletypestickerswidget import SampleTypeStickersWidget diff --git a/bika/lims/browser/widgets/sampletypestickerswidget.py b/bika/lims/browser/widgets/sampletypestickerswidget.py new file mode 100644 index 0000000000..d118e72508 --- /dev/null +++ b/bika/lims/browser/widgets/sampletypestickerswidget.py @@ -0,0 +1,22 @@ +from AccessControl import ClassSecurityInfo + +from Products.Archetypes.Registry import registerWidget + +from bika.lims.browser.widgets import RecordsWidget + + +class SampleTypeStickersWidget(RecordsWidget): + security = ClassSecurityInfo() + _properties = RecordsWidget._properties.copy() + _properties.update({ + 'helper_js': ( + "bika_widgets/recordswidget.js", + "bika_widgets/sampletypestickerswidget.js",), + }) + + +registerWidget( + SampleTypeStickersWidget, + title="Sample type stickers widget", + description='Defines the available stickers for a sample type.', + ) diff --git a/bika/lims/content/sampletype.py b/bika/lims/content/sampletype.py index 8757f2e991..a944f1872e 100644 --- a/bika/lims/content/sampletype.py +++ b/bika/lims/content/sampletype.py @@ -6,26 +6,41 @@ # Some rights reserved. See LICENSE.rst, CONTRIBUTORS.rst. from AccessControl import ClassSecurityInfo + from Products.ATContentTypes.lib.historyaware import HistoryAwareMixin +from Products.ATExtensions.ateapi import RecordsField from Products.Archetypes.public import * from Products.Archetypes.references import HoldingReference -from Products.CMFCore.permissions import View, ModifyPortalContent from Products.CMFCore.utils import getToolByName from Products.CMFPlone.utils import safe_unicode -from bika.lims.browser import BrowserView +from magnitude import mg +from zope.interface import implements + from bika.lims import bikaMessageFactory as _ -from bika.lims.utils import t -from bika.lims.config import PROJECTNAME -from bika.lims.browser.widgets import DurationWidget +from bika.lims import logger from bika.lims.browser.fields import DurationField +from bika.lims.browser.widgets import DurationWidget +from bika.lims.browser.widgets import SampleTypeStickersWidget +from bika.lims.browser.widgets.referencewidget import ReferenceWidget as brw +from bika.lims.config import PROJECTNAME from bika.lims.content.bikaschema import BikaSchema from bika.lims.interfaces import ISampleType -from magnitude import mg, MagnitudeError -from zope.interface import implements -from bika.lims.browser.widgets.referencewidget import ReferenceWidget as brw -import json -import plone -import sys +from bika.lims.vocabularies import getStickerTemplates + + +def sticker_templates(): + """ + It returns the registered stickers in the system. + :return: a DisplayList object + """ + voc = DisplayList() + stickers = getStickerTemplates() + for sticker in stickers: + voc.add(sticker.get('id'), sticker.get('title')) + if voc.index == 0: + logger.warning('Sampletype: getStickerTemplates is empty!') + return voc + schema = BikaSchema.copy() + Schema(( DurationField('RetentionPeriod', @@ -106,6 +121,47 @@ visibile=False, ) ), + RecordsField( + 'AdmittedStickerTemplates', + subfields=( + 'admitted', + 'small_default', + 'large_default', + ), + subfield_labels={ + 'admitted': _( + 'Admitted stickers for the sample type'), + 'small_default': _( + 'Default small sticker'), + 'large_default': _( + 'Default large sticker')}, + subfield_sizes={ + 'admitted': 6, + 'small_default': 1, + 'large_default': 1}, + subfield_types={ + 'admitted': 'selection', + 'small_default': 'selection', + 'large_default': 'selection' + }, + subfield_vocabularies={ + 'admitted': sticker_templates(), + 'small_default': '_small_default_voc', + 'large_default': '_large_default_voc', + }, + required_subfields={ + 'admitted': 1, + 'small_default': 1, + 'large_default': 1}, + default=[{}], + fixedSize=1, + widget=SampleTypeStickersWidget( + label=_("Admitted sticker templates"), + description=_( + "Defines the stickers to use for this sample type."), + allowDelete=False, + ), + ), )) schema['description'].schemata = 'default' @@ -198,6 +254,79 @@ def ContainerTypesVocabulary(self): from bika.lims.content.containertype import ContainerTypes return ContainerTypes(self, allow_blank=True) + def getDefaultSmallSticker(self): + """ + Returns the small sticker ID defined as default. + + :return: A string as an sticker ID + """ + values = self.getField('AdmittedStickerTemplates').get(self) + value = values.get('small_default') + return value + + def getDefaultLargeSticker(self): + """ + Returns the large sticker ID defined as default. + + :return: A string as an sticker ID + """ + values = self.getField('AdmittedStickerTemplates').get(self) + value = values.get('large_default') + return value + + def _small_default_voc(self): + """ + Returns the vocabulary to be used in + AdmittedStickerTemplates.small_default + + If the object has saved not AdmittedStickerTemplates.admitted stickers, + this method will return an empty DisplayList. Otherwise it returns + the stickers selected in admitted. + + :return: A DisplayList + """ + values = self.getField('AdmittedStickerTemplates').get(self) + if not values: + return DisplayList() + admitted = values[0].get('admitted') + if not admitted: + return DisplayList() + voc = DisplayList() + stickers = getStickerTemplates() + for sticker in stickers: + if sticker.get('id') in admitted: + voc.add(sticker.get('id'), sticker.get('title')) + if voc.index > 0: + return voc + return DisplayList() + + def _large_default_voc(self): + """ + Returns the vocabulary to be used in + AdmittedStickerTemplates.large_default + + If the object has saved not AdmittedStickerTemplates.admitted stickers, + this method will return an empty DisplayList. Otherwise it returns + the stickers selected in admitted. + + :return: A DisplayList + """ + values = self.getField('AdmittedStickerTemplates').get(self) + if not values: + return DisplayList() + admitted = values[0].get('admitted') + if not admitted: + return DisplayList() + voc = DisplayList() + stickers = getStickerTemplates() + for sticker in stickers: + if sticker.get('id') in admitted: + voc.add(sticker.get('id'), sticker.get('title')) + if voc.index > 0: + return voc + return DisplayList() + + registerType(SampleType, PROJECTNAME) def SampleTypes(self, instance=None, allow_blank=False): diff --git a/bika/lims/skins/bika/bika_widgets/sampletypestickerswidget.js b/bika/lims/skins/bika/bika_widgets/sampletypestickerswidget.js new file mode 100644 index 0000000000..3b7c22fd0d --- /dev/null +++ b/bika/lims/skins/bika/bika_widgets/sampletypestickerswidget.js @@ -0,0 +1,47 @@ +jQuery(function($){ + $(document).ready(function(){ + // Controller for admitted stickers multi selection input. + $("#AdmittedStickerTemplates-admitted-0") + .bind('change', function(){ + on_admitted_change(); + } + ); + }); + /** + * When "admitted sticker selection" input changes, "default small" and + * "default large" selector options must be updated in acordance with the + * new admitted options. + * @return {None} nothing. + */ + function on_admitted_change(){ + // Get admitted options + var admitted_ops = $("#AdmittedStickerTemplates-admitted-0") + .find('option:selected'); + + // Clean small/large select options + $("#AdmittedStickerTemplates-small_default-0").find('option').remove(); + $("#AdmittedStickerTemplates-large_default-0").find('option').remove(); + + // Set small/large options from admitted ones + var i; + var small_opt_clone; + var large_opt_clone; + for(i=0; admitted_ops.length > i; i++){ + small_opt_clone = $(admitted_ops[i]).clone(); + $("#AdmittedStickerTemplates-small_default-0") + .append(small_opt_clone); + large_opt_clone = $(admitted_ops[i]).clone(); + $("#AdmittedStickerTemplates-large_default-0") + .append(large_opt_clone); + } + // Select the last cloned option. This way we give a value to the + // selected input. + if (small_opt_clone != undefined){ + $(small_opt_clone).attr('selected', 'selected'); + } + if (large_opt_clone != undefined){ + $(large_opt_clone).attr('selected', 'selected'); + } + } + +}); diff --git a/bika/lims/vocabularies/__init__.py b/bika/lims/vocabularies/__init__.py index f42d5d87c4..36c8a81425 100644 --- a/bika/lims/vocabularies/__init__.py +++ b/bika/lims/vocabularies/__init__.py @@ -539,9 +539,9 @@ class StickerTemplatesVocabulary(object): """ implements(IVocabularyFactory) - def __call__(self, context): + def __call__(self, context, filter_by_type=False): out = [SimpleTerm(x['id'], x['id'], x['title']) for x in - getStickerTemplates()] + getStickerTemplates(filter_by_type=filter_by_type)] return SimpleVocabulary(out) From 9b4e2082f0e045b925cd3230873570203943d7b1 Mon Sep 17 00:00:00 2001 From: Espurna Date: Thu, 25 Jan 2018 18:49:39 +0100 Subject: [PATCH 02/17] stickers options from adapters --- bika/lims/adapters/configure.zcml | 8 +++++ bika/lims/adapters/stickers.py | 60 +++++++++++++++++++++++++++++++ bika/lims/browser/stickers.py | 18 +++++++++- bika/lims/content/sampletype.py | 30 ++++++++++------ bika/lims/interfaces/__init__.py | 12 +++++++ 5 files changed, 117 insertions(+), 11 deletions(-) create mode 100644 bika/lims/adapters/stickers.py diff --git a/bika/lims/adapters/configure.zcml b/bika/lims/adapters/configure.zcml index 7d583697fe..8f193e69cb 100644 --- a/bika/lims/adapters/configure.zcml +++ b/bika/lims/adapters/configure.zcml @@ -114,4 +114,12 @@ preserveOriginal="True" /> + + + + diff --git a/bika/lims/adapters/stickers.py b/bika/lims/adapters/stickers.py new file mode 100644 index 0000000000..96da5fc615 --- /dev/null +++ b/bika/lims/adapters/stickers.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# +# This file is part of SENAITE.CORE +# +# Copyright 2018 by it's authors. +# Some rights reserved. See LICENSE.rst, CONTRIBUTORS.rst. + +from zope.interface import implements + +from bika.lims.interfaces import IGetStickerTemplates +from bika.lims.vocabularies import getStickerTemplates + + +class GetSampleStickers(object): + """ + Returns an array with the templates of stickers available for Sample + object in context. + Each array item is a dictionary with the following structure: + [{'id': , + 'title': , + 'selected: True/False'}, ] + """ + + implements(IGetStickerTemplates) + + def __init__(self, context): + self.context = context + self.request = None + self.sample_type = None + + def __call__(self, request): + self.request = request + # Stickers admittance are saved in sample type + self.sample_type = self.context.getSampleType() + sticker_ids = self.sample_type.getAdmittedStickers() + default_sticker_id = self.get_default_sticker_id() + result = [] + # Getting only existing templates and its info + stickers = getStickerTemplates() + for sticker in stickers: + if sticker.get('id') in sticker_ids: + sticker_info = sticker.copy() + sticker_info['selected'] = \ + default_sticker_id == sticker.get('id') + result.append(sticker_info) + return result + + def get_default_sticker_id(self): + """ + Gets the default sticker for that content type depending on the + requested size. + + :return: An sticker ID as string + """ + size = self.request.get('size', '') + if size == 'small': + default = self.sample_type.getDefaultSmallSticker() + else: + default = self.sample_type.getDefaultLargeSticker() + return default diff --git a/bika/lims/browser/stickers.py b/bika/lims/browser/stickers.py index bdafcedc2b..f3cfd359eb 100644 --- a/bika/lims/browser/stickers.py +++ b/bika/lims/browser/stickers.py @@ -11,10 +11,13 @@ from bika.lims import logger from bika.lims.browser import BrowserView from bika.lims.utils import createPdf +from zope.component.interfaces import ComponentLookupError from bika.lims.vocabularies import getStickerTemplates from plone.resource.utils import iterDirectoriesOfType, queryResourceDirectory from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile import glob, os, os.path, sys, traceback +from bika.lims.interfaces import IGetStickerTemplates +from zope.component import getAdapters import os import App @@ -159,8 +162,21 @@ def getAvailableTemplates(self): 'title': , 'selected: True/False'} """ - seltemplate = self.getSelectedTemplate() + # Getting adapters for current context. those adapters will return + # the desired sticker templates for the current context: + try: + adapters = getAdapters((self.context, ), IGetStickerTemplates) + except ComponentLookupError: + logger.info('No IGetStickerTemplates adapters found.') + adapters = None templates = [] + if adapters is not None: + # Gather all templates + for name, adapter in adapters: + templates += adapter(self.request) + return templates + # If there are no adapters, get all sticker templates in the system + seltemplate = self.getSelectedTemplate() for temp in getStickerTemplates(filter_by_type=self.filter_by_type): out = temp out['selected'] = temp.get('id', '') == seltemplate diff --git a/bika/lims/content/sampletype.py b/bika/lims/content/sampletype.py index a944f1872e..9936fdd613 100644 --- a/bika/lims/content/sampletype.py +++ b/bika/lims/content/sampletype.py @@ -261,7 +261,9 @@ def getDefaultSmallSticker(self): :return: A string as an sticker ID """ values = self.getField('AdmittedStickerTemplates').get(self) - value = values.get('small_default') + if not values: + return '' + value = values[0].get('small_default') return value def getDefaultLargeSticker(self): @@ -271,9 +273,23 @@ def getDefaultLargeSticker(self): :return: A string as an sticker ID """ values = self.getField('AdmittedStickerTemplates').get(self) - value = values.get('large_default') + if not values: + return '' + value = values[0].get('large_default') return value + def getAdmittedStickers(self): + """ + Returns the admitted sticker IDs defined. + + :return: An array of sticker IDs + """ + values = self.getField('AdmittedStickerTemplates').get(self) + if not values: + return [] + admitted = values[0].get('admitted') + return admitted + def _small_default_voc(self): """ Returns the vocabulary to be used in @@ -285,10 +301,7 @@ def _small_default_voc(self): :return: A DisplayList """ - values = self.getField('AdmittedStickerTemplates').get(self) - if not values: - return DisplayList() - admitted = values[0].get('admitted') + admitted = self.getAdmittedStickers() if not admitted: return DisplayList() voc = DisplayList() @@ -311,10 +324,7 @@ def _large_default_voc(self): :return: A DisplayList """ - values = self.getField('AdmittedStickerTemplates').get(self) - if not values: - return DisplayList() - admitted = values[0].get('admitted') + admitted = self.getAdmittedStickers() if not admitted: return DisplayList() voc = DisplayList() diff --git a/bika/lims/interfaces/__init__.py b/bika/lims/interfaces/__init__.py index 0c6ba00a40..1c890d6bf8 100644 --- a/bika/lims/interfaces/__init__.py +++ b/bika/lims/interfaces/__init__.py @@ -823,3 +823,15 @@ class ITopWideHTMLComponentsHook(Interface): """ Marker interface to hook html components in bikalisting """ + + +class IGetStickerTemplates(Interface): + """ + Marker interface to get stickers for a specific content type. + + An IGetStickerTemplates adapter should return a result with the + following format: + + :return: [{'id': , + 'title': }, ...] + """ From 785c7d980110fe3c0718d2565dc4345963da2a8b Mon Sep 17 00:00:00 2001 From: Espurna Date: Fri, 26 Jan 2018 13:52:28 +0100 Subject: [PATCH 03/17] upgrade step --- bika/lims/content/sampletype.py | 69 +++++++++++++++++++++++++++++++++ bika/lims/upgrade/v01_02_001.py | 29 +++++++++++++- 2 files changed, 97 insertions(+), 1 deletion(-) diff --git a/bika/lims/content/sampletype.py b/bika/lims/content/sampletype.py index 9936fdd613..c173e9f662 100644 --- a/bika/lims/content/sampletype.py +++ b/bika/lims/content/sampletype.py @@ -336,6 +336,75 @@ def _large_default_voc(self): return voc return DisplayList() + def setDefaultSmallSticker(self, value): + """ + Sets the small sticker ID defined as default. + + :param value: A sticker ID + """ + if value is None: + logger.error( + "Setting wrong 'AdmittedStickerTemplates/small_default' value" + " to Sample Type '{}'" + .format(self.getId())) + return + if not isinstance(value, str): + logger.error( + "Setting wrong 'AdmittedStickerTemplates/small_default' value" + " type to Sample Type '{}'" + .format(self.getId())) + return + field = self.getField('AdmittedStickerTemplates') + new_value = field.get(self) + new_value[0]['small_default'] = value + field.set(self, new_value) + + def setDefaultLargeSticker(self, value): + """ + Sets the large sticker ID defined as default. + + :param value: A sticker ID + """ + if value is None: + logger.error( + "Setting wrong 'AdmittedStickerTemplates/large_default' value" + " to Sample Type '{}'" + .format(self.getId())) + return + if not isinstance(value, str): + logger.error( + "Setting wrong 'AdmittedStickerTemplates/large_default' value" + " type to Sample Type '{}'" + .format(self.getId())) + return + field = self.getField('AdmittedStickerTemplates') + new_value = field.get(self) + new_value[0]['large_default'] = value + field.set(self, new_value) + + def setAdmittedStickers(self, value): + """ + Sets the admitted sticker IDs. + + :param value: An array of sticker IDs + """ + if value is None: + logger.error( + "Setting wrong 'AdmittedStickerTemplates/admitted' value" + " to Sample Type '{}'" + .format(self.getId())) + return + if not isinstance(value, list): + logger.error( + "Setting wrong 'AdmittedStickerTemplates/admitted' value" + " type to Sample Type '{}'" + .format(self.getId())) + return + field = self.getField('AdmittedStickerTemplates') + new_value = field.get(self) + new_value[0]['admitted'] = value + field.set(self, new_value) + registerType(SampleType, PROJECTNAME) diff --git a/bika/lims/upgrade/v01_02_001.py b/bika/lims/upgrade/v01_02_001.py index d494c55178..ed5c5acc10 100644 --- a/bika/lims/upgrade/v01_02_001.py +++ b/bika/lims/upgrade/v01_02_001.py @@ -11,6 +11,8 @@ from bika.lims.config import PROJECTNAME as product from bika.lims.upgrade import upgradestep from bika.lims.upgrade.utils import UpgradeUtils +from bika.lims.vocabularies import getStickerTemplates + from bika.lims.workflow import changeWorkflowState from bika.lims.workflow import isActive from DateTime import DateTime @@ -36,6 +38,7 @@ def upgrade(tool): set_guards_to_inactive_workflow() fix_service_status_inconsistences() fix_service_profile_template_inconsistences() + set_sample_type_default_stickers(portal) logger.info("{0} upgraded to version {1}".format(product, version)) @@ -106,4 +109,28 @@ def _change_inactive_state(service, new_state): } wtool.setStatusOf('bika_inactive_workflow', service, wf_state) workflow.updateRoleMappingsFor(service) - service.reindexObject(idxs=['allowedRolesAndUsers', 'inactive_state']) \ No newline at end of file + service.reindexObject(idxs=['allowedRolesAndUsers', 'inactive_state']) + + +def set_sample_type_default_stickers(portal): + """ + Fills the admitted stickers and their default stickers to every sample + type. + """ + # Getting all sticker templates + stickers = getStickerTemplates() + sticker_ids = [] + for sticker in stickers: + sticker_ids.append(sticker.get('id')) + def_small_template = portal.bika_setup.getSmallStickerTemplate() + def_large_template = portal.bika_setup.getLargeStickerTemplate() + # Getting all Sample Type objects + catalog = api.get_tool('bika_setup_catalog') + brains = catalog(portal_type='SampleType') + for brain in brains: + obj = api.get_object(brain) + if obj.getAdmittedStickers() is not None: + continue + obj.setAdmittedStickers(sticker_ids) + obj.setDefaultLargeSticker(def_large_template) + obj.setDefaultSmallSticker(def_small_template) From fc6ab0a4c6132fd82db152529be069068bcff95a Mon Sep 17 00:00:00 2001 From: Espurna Date: Fri, 26 Jan 2018 14:01:47 +0100 Subject: [PATCH 04/17] changelog --- CHANGES.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index 8be14b812f..2296efdd6d 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -8,6 +8,8 @@ Changelog - #555 Don't allow the deactivation Analysis Services with active dependencies - #555 Don't allow the activation of Analysis Services with inactive dependents +- #607 Choose the template in the preview and in accordance with the +sample type **Removed** From 401d18de0e744277bbbcd0ee492355efbe411149 Mon Sep 17 00:00:00 2001 From: Espurna Date: Mon, 29 Jan 2018 13:11:27 +0100 Subject: [PATCH 05/17] Make sure we resturn a list of templates --- bika/lims/adapters/stickers.py | 7 +++++++ bika/lims/browser/stickers.py | 1 + 2 files changed, 8 insertions(+) diff --git a/bika/lims/adapters/stickers.py b/bika/lims/adapters/stickers.py index 96da5fc615..cf5a40a5d0 100644 --- a/bika/lims/adapters/stickers.py +++ b/bika/lims/adapters/stickers.py @@ -7,6 +7,7 @@ from zope.interface import implements +from bika.lims import logger from bika.lims.interfaces import IGetStickerTemplates from bika.lims.vocabularies import getStickerTemplates @@ -31,6 +32,12 @@ def __init__(self, context): def __call__(self, request): self.request = request # Stickers admittance are saved in sample type + if not hasattr(self.context, 'getSampleType'): + logger.warning( + "{} has no attribute 'getSampleType', so no sticker will be " + "returned.". format(self.context.getId()) + ) + return [] self.sample_type = self.context.getSampleType() sticker_ids = self.sample_type.getAdmittedStickers() default_sticker_id = self.get_default_sticker_id() diff --git a/bika/lims/browser/stickers.py b/bika/lims/browser/stickers.py index f3cfd359eb..638297e3e1 100644 --- a/bika/lims/browser/stickers.py +++ b/bika/lims/browser/stickers.py @@ -174,6 +174,7 @@ def getAvailableTemplates(self): # Gather all templates for name, adapter in adapters: templates += adapter(self.request) + if templates: return templates # If there are no adapters, get all sticker templates in the system seltemplate = self.getSelectedTemplate() From eb2d4b28a273b9dfec63b31a5e2b85f394a8ed4d Mon Sep 17 00:00:00 2001 From: Espurna Date: Mon, 29 Jan 2018 14:44:59 +0100 Subject: [PATCH 06/17] taking into account IAnalysisRequest contexts --- bika/lims/adapters/configure.zcml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/bika/lims/adapters/configure.zcml b/bika/lims/adapters/configure.zcml index 8f193e69cb..472cf15ef9 100644 --- a/bika/lims/adapters/configure.zcml +++ b/bika/lims/adapters/configure.zcml @@ -121,5 +121,10 @@ for="bika.lims.interfaces.ISample" provides="bika.lims.interfaces.IGetStickerTemplates" /> + From 708feac219e2d3ad93ac8e08f6b7f231097ed81f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Tue, 30 Jan 2018 22:45:36 +0000 Subject: [PATCH 07/17] Update CHANGES.rst --- CHANGES.rst | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index cbf85774a6..76fbf02cd1 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -6,10 +6,7 @@ Changelog **Added** -- #555 Don't allow the deactivation Analysis Services with active dependencies -- #555 Don't allow the activation of Analysis Services with inactive dependents -- #607 Choose the template in the preview and in accordance with the -sample type +- #607 Barcode and labelling depending on Sample Type **Removed** From d252f691ef6e459e40652d100bcb69e257118fe6 Mon Sep 17 00:00:00 2001 From: Espurna Date: Fri, 2 Feb 2018 10:40:00 +0100 Subject: [PATCH 08/17] reduce complexity --- bika/lims/adapters/stickers.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/bika/lims/adapters/stickers.py b/bika/lims/adapters/stickers.py index cf5a40a5d0..bc443955dd 100644 --- a/bika/lims/adapters/stickers.py +++ b/bika/lims/adapters/stickers.py @@ -61,7 +61,5 @@ def get_default_sticker_id(self): """ size = self.request.get('size', '') if size == 'small': - default = self.sample_type.getDefaultSmallSticker() - else: - default = self.sample_type.getDefaultLargeSticker() - return default + return self.sample_type.getDefaultSmallSticker() + return self.sample_type.getDefaultLargeSticker() From 5d0320e8d262e58889fba3cfaeb61f270c973592 Mon Sep 17 00:00:00 2001 From: Espurna Date: Fri, 2 Feb 2018 10:58:13 +0100 Subject: [PATCH 09/17] using global variable for strings --- bika/lims/content/sampletype.py | 35 ++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/bika/lims/content/sampletype.py b/bika/lims/content/sampletype.py index c173e9f662..994973ef94 100644 --- a/bika/lims/content/sampletype.py +++ b/bika/lims/content/sampletype.py @@ -27,6 +27,9 @@ from bika.lims.interfaces import ISampleType from bika.lims.vocabularies import getStickerTemplates +SMALL_DEFAULT_STICKER = 'small_default' +LARGE_DEFAULT_STICKER = 'large_default' + def sticker_templates(): """ @@ -125,34 +128,34 @@ def sticker_templates(): 'AdmittedStickerTemplates', subfields=( 'admitted', - 'small_default', - 'large_default', + SMALL_DEFAULT_STICKER, + LARGE_DEFAULT_STICKER, ), subfield_labels={ 'admitted': _( 'Admitted stickers for the sample type'), - 'small_default': _( + SMALL_DEFAULT_STICKER: _( 'Default small sticker'), - 'large_default': _( + LARGE_DEFAULT_STICKER: _( 'Default large sticker')}, subfield_sizes={ 'admitted': 6, - 'small_default': 1, - 'large_default': 1}, + SMALL_DEFAULT_STICKER: 1, + LARGE_DEFAULT_STICKER: 1}, subfield_types={ 'admitted': 'selection', - 'small_default': 'selection', - 'large_default': 'selection' + SMALL_DEFAULT_STICKER: 'selection', + LARGE_DEFAULT_STICKER: 'selection' }, subfield_vocabularies={ 'admitted': sticker_templates(), - 'small_default': '_small_default_voc', - 'large_default': '_large_default_voc', + SMALL_DEFAULT_STICKER: '_small_default_voc', + LARGE_DEFAULT_STICKER: '_large_default_voc', }, required_subfields={ 'admitted': 1, - 'small_default': 1, - 'large_default': 1}, + SMALL_DEFAULT_STICKER: 1, + LARGE_DEFAULT_STICKER: 1}, default=[{}], fixedSize=1, widget=SampleTypeStickersWidget( @@ -263,7 +266,7 @@ def getDefaultSmallSticker(self): values = self.getField('AdmittedStickerTemplates').get(self) if not values: return '' - value = values[0].get('small_default') + value = values[0].get(SMALL_DEFAULT_STICKER) return value def getDefaultLargeSticker(self): @@ -275,7 +278,7 @@ def getDefaultLargeSticker(self): values = self.getField('AdmittedStickerTemplates').get(self) if not values: return '' - value = values[0].get('large_default') + value = values[0].get(LARGE_DEFAULT_STICKER) return value def getAdmittedStickers(self): @@ -356,7 +359,7 @@ def setDefaultSmallSticker(self, value): return field = self.getField('AdmittedStickerTemplates') new_value = field.get(self) - new_value[0]['small_default'] = value + new_value[0][SMALL_DEFAULT_STICKER] = value field.set(self, new_value) def setDefaultLargeSticker(self, value): @@ -379,7 +382,7 @@ def setDefaultLargeSticker(self, value): return field = self.getField('AdmittedStickerTemplates') new_value = field.get(self) - new_value[0]['large_default'] = value + new_value[0][LARGE_DEFAULT_STICKER] = value field.set(self, new_value) def setAdmittedStickers(self, value): From 4b83ea4d9eba69c1617a7f5a6d6d53e2e0969845 Mon Sep 17 00:00:00 2001 From: Espurna Date: Fri, 2 Feb 2018 11:12:57 +0100 Subject: [PATCH 10/17] duplicated function --- bika/lims/content/sampletype.py | 29 +++-------------------------- 1 file changed, 3 insertions(+), 26 deletions(-) diff --git a/bika/lims/content/sampletype.py b/bika/lims/content/sampletype.py index 994973ef94..76616370a6 100644 --- a/bika/lims/content/sampletype.py +++ b/bika/lims/content/sampletype.py @@ -149,8 +149,8 @@ def sticker_templates(): }, subfield_vocabularies={ 'admitted': sticker_templates(), - SMALL_DEFAULT_STICKER: '_small_default_voc', - LARGE_DEFAULT_STICKER: '_large_default_voc', + SMALL_DEFAULT_STICKER: '_sticker_templates_vocabularies', + LARGE_DEFAULT_STICKER: '_sticker_templates_vocabularies', }, required_subfields={ 'admitted': 1, @@ -293,7 +293,7 @@ def getAdmittedStickers(self): admitted = values[0].get('admitted') return admitted - def _small_default_voc(self): + def _sticker_templates_vocabularies(self): """ Returns the vocabulary to be used in AdmittedStickerTemplates.small_default @@ -316,29 +316,6 @@ def _small_default_voc(self): return voc return DisplayList() - def _large_default_voc(self): - """ - Returns the vocabulary to be used in - AdmittedStickerTemplates.large_default - - If the object has saved not AdmittedStickerTemplates.admitted stickers, - this method will return an empty DisplayList. Otherwise it returns - the stickers selected in admitted. - - :return: A DisplayList - """ - admitted = self.getAdmittedStickers() - if not admitted: - return DisplayList() - voc = DisplayList() - stickers = getStickerTemplates() - for sticker in stickers: - if sticker.get('id') in admitted: - voc.add(sticker.get('id'), sticker.get('title')) - if voc.index > 0: - return voc - return DisplayList() - def setDefaultSmallSticker(self, value): """ Sets the small sticker ID defined as default. From a7cf4d79d6e7650739a36811772e83378c279d7a Mon Sep 17 00:00:00 2001 From: Espurna Date: Fri, 2 Feb 2018 11:16:25 +0100 Subject: [PATCH 11/17] duplicated method --- bika/lims/content/sampletype.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/bika/lims/content/sampletype.py b/bika/lims/content/sampletype.py index 76616370a6..3961520fab 100644 --- a/bika/lims/content/sampletype.py +++ b/bika/lims/content/sampletype.py @@ -257,17 +257,20 @@ def ContainerTypesVocabulary(self): from bika.lims.content.containertype import ContainerTypes return ContainerTypes(self, allow_blank=True) + def getDefaultSticker(self, size): + values = self.getField('AdmittedStickerTemplates').get(self) + if not values: + return '' + value = values[0].get(size) + return value + def getDefaultSmallSticker(self): """ Returns the small sticker ID defined as default. :return: A string as an sticker ID """ - values = self.getField('AdmittedStickerTemplates').get(self) - if not values: - return '' - value = values[0].get(SMALL_DEFAULT_STICKER) - return value + return self.getDefaultSticker(SMALL_DEFAULT_STICKER) def getDefaultLargeSticker(self): """ @@ -275,11 +278,7 @@ def getDefaultLargeSticker(self): :return: A string as an sticker ID """ - values = self.getField('AdmittedStickerTemplates').get(self) - if not values: - return '' - value = values[0].get(LARGE_DEFAULT_STICKER) - return value + return self.getDefaultSticker(LARGE_DEFAULT_STICKER) def getAdmittedStickers(self): """ From 0c93e95290a74f60bb3c1b0bc312f907dd243bc0 Mon Sep 17 00:00:00 2001 From: Espurna Date: Fri, 2 Feb 2018 11:20:44 +0100 Subject: [PATCH 12/17] duplicated methods --- bika/lims/content/sampletype.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/bika/lims/content/sampletype.py b/bika/lims/content/sampletype.py index 3961520fab..2aa01ee93a 100644 --- a/bika/lims/content/sampletype.py +++ b/bika/lims/content/sampletype.py @@ -257,11 +257,11 @@ def ContainerTypesVocabulary(self): from bika.lims.content.containertype import ContainerTypes return ContainerTypes(self, allow_blank=True) - def getDefaultSticker(self, size): + def _get_sticker_subfield(self, subfield): values = self.getField('AdmittedStickerTemplates').get(self) if not values: return '' - value = values[0].get(size) + value = values[0].get(subfield) return value def getDefaultSmallSticker(self): @@ -270,7 +270,7 @@ def getDefaultSmallSticker(self): :return: A string as an sticker ID """ - return self.getDefaultSticker(SMALL_DEFAULT_STICKER) + return self._get_sticker_subfield(SMALL_DEFAULT_STICKER) def getDefaultLargeSticker(self): """ @@ -278,7 +278,7 @@ def getDefaultLargeSticker(self): :return: A string as an sticker ID """ - return self.getDefaultSticker(LARGE_DEFAULT_STICKER) + return self._get_sticker_subfield(LARGE_DEFAULT_STICKER) def getAdmittedStickers(self): """ @@ -286,11 +286,10 @@ def getAdmittedStickers(self): :return: An array of sticker IDs """ - values = self.getField('AdmittedStickerTemplates').get(self) - if not values: - return [] - admitted = values[0].get('admitted') - return admitted + admitted = self._get_sticker_subfield('admitted') + if admitted: + return admitted + return [] def _sticker_templates_vocabularies(self): """ From 257e074c0444bc0b3308c83f9c0ba785d54a0f53 Mon Sep 17 00:00:00 2001 From: Espurna Date: Fri, 2 Feb 2018 11:21:31 +0100 Subject: [PATCH 13/17] code reduction --- bika/lims/content/sampletype.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/bika/lims/content/sampletype.py b/bika/lims/content/sampletype.py index 2aa01ee93a..526efb93c9 100644 --- a/bika/lims/content/sampletype.py +++ b/bika/lims/content/sampletype.py @@ -310,9 +310,7 @@ def _sticker_templates_vocabularies(self): for sticker in stickers: if sticker.get('id') in admitted: voc.add(sticker.get('id'), sticker.get('title')) - if voc.index > 0: - return voc - return DisplayList() + return voc def setDefaultSmallSticker(self, value): """ From 437c440e08663df55b87f812616ee7685fa7966d Mon Sep 17 00:00:00 2001 From: Espurna Date: Fri, 2 Feb 2018 11:30:46 +0100 Subject: [PATCH 14/17] code reduction --- bika/lims/content/sampletype.py | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/bika/lims/content/sampletype.py b/bika/lims/content/sampletype.py index 526efb93c9..869a827275 100644 --- a/bika/lims/content/sampletype.py +++ b/bika/lims/content/sampletype.py @@ -330,10 +330,7 @@ def setDefaultSmallSticker(self, value): " type to Sample Type '{}'" .format(self.getId())) return - field = self.getField('AdmittedStickerTemplates') - new_value = field.get(self) - new_value[0][SMALL_DEFAULT_STICKER] = value - field.set(self, new_value) + self._set_sticker_subfield(SMALL_DEFAULT_STICKER, value) def setDefaultLargeSticker(self, value): """ @@ -353,10 +350,7 @@ def setDefaultLargeSticker(self, value): " type to Sample Type '{}'" .format(self.getId())) return - field = self.getField('AdmittedStickerTemplates') - new_value = field.get(self) - new_value[0][LARGE_DEFAULT_STICKER] = value - field.set(self, new_value) + self._set_sticker_subfield(LARGE_DEFAULT_STICKER, value) def setAdmittedStickers(self, value): """ @@ -376,10 +370,13 @@ def setAdmittedStickers(self, value): " type to Sample Type '{}'" .format(self.getId())) return + self._set_sticker_subfield('admitted', value) + + def _set_sticker_subfield(self, subfield, value): field = self.getField('AdmittedStickerTemplates') - new_value = field.get(self) - new_value[0]['admitted'] = value - field.set(self, new_value) + stickers = field.get(self) + stickers[0][subfield] = value + field.set(self, stickers) registerType(SampleType, PROJECTNAME) From 63c61ee8c5c398a14093022a77ad736755f663c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Thu, 8 Feb 2018 11:59:07 +0000 Subject: [PATCH 15/17] Update CHANGES.rst --- CHANGES.rst | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index f2493e4847..6b4267fc40 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -6,10 +6,7 @@ Changelog **Added** -- #555 Don't allow the deactivation Analysis Services with active dependencies -- #555 Don't allow the activation of Analysis Services with inactive dependents -- #607 Choose the template in the preview and in accordance with the -sample type +- #607 Ability to choose sticker template based on sample type - #480 Sample panel in dashboard - #617 Instrument import interface: 2-Dimensional-CSV - #617 Instrument import interface: Agilent Masshunter From 782b4f58b7a169689732609b55d03c1675aa5e92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Thu, 8 Feb 2018 13:08:58 +0100 Subject: [PATCH 16/17] Moved stickers binding with Sample Types upgrade step to 1.2.2 --- bika/lims/upgrade/v01_02_001.py | 27 --------------------------- bika/lims/upgrade/v01_02_002.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/bika/lims/upgrade/v01_02_001.py b/bika/lims/upgrade/v01_02_001.py index ed5c5acc10..72a98c8c07 100644 --- a/bika/lims/upgrade/v01_02_001.py +++ b/bika/lims/upgrade/v01_02_001.py @@ -11,8 +11,6 @@ from bika.lims.config import PROJECTNAME as product from bika.lims.upgrade import upgradestep from bika.lims.upgrade.utils import UpgradeUtils -from bika.lims.vocabularies import getStickerTemplates - from bika.lims.workflow import changeWorkflowState from bika.lims.workflow import isActive from DateTime import DateTime @@ -38,7 +36,6 @@ def upgrade(tool): set_guards_to_inactive_workflow() fix_service_status_inconsistences() fix_service_profile_template_inconsistences() - set_sample_type_default_stickers(portal) logger.info("{0} upgraded to version {1}".format(product, version)) @@ -110,27 +107,3 @@ def _change_inactive_state(service, new_state): wtool.setStatusOf('bika_inactive_workflow', service, wf_state) workflow.updateRoleMappingsFor(service) service.reindexObject(idxs=['allowedRolesAndUsers', 'inactive_state']) - - -def set_sample_type_default_stickers(portal): - """ - Fills the admitted stickers and their default stickers to every sample - type. - """ - # Getting all sticker templates - stickers = getStickerTemplates() - sticker_ids = [] - for sticker in stickers: - sticker_ids.append(sticker.get('id')) - def_small_template = portal.bika_setup.getSmallStickerTemplate() - def_large_template = portal.bika_setup.getLargeStickerTemplate() - # Getting all Sample Type objects - catalog = api.get_tool('bika_setup_catalog') - brains = catalog(portal_type='SampleType') - for brain in brains: - obj = api.get_object(brain) - if obj.getAdmittedStickers() is not None: - continue - obj.setAdmittedStickers(sticker_ids) - obj.setDefaultLargeSticker(def_large_template) - obj.setDefaultSmallSticker(def_small_template) diff --git a/bika/lims/upgrade/v01_02_002.py b/bika/lims/upgrade/v01_02_002.py index 87692a3812..6410a886ae 100644 --- a/bika/lims/upgrade/v01_02_002.py +++ b/bika/lims/upgrade/v01_02_002.py @@ -6,6 +6,7 @@ # Some rights reserved. See LICENSE.rst, CONTRIBUTORS.rst. from Products.Archetypes.config import REFERENCE_CATALOG from Products.CMFCore.utils import getToolByName +from bika.lims import api from bika.lims import logger from bika.lims.catalog.worksheet_catalog import CATALOG_WORKSHEET_LISTING from bika.lims.browser.dashboard.dashboard import \ @@ -13,6 +14,7 @@ from bika.lims.config import PROJECTNAME as product from bika.lims.upgrade import upgradestep from bika.lims.upgrade.utils import UpgradeUtils +from bika.lims.vocabularies import getStickerTemplates version = '1.2.2' # Remember version number in metadata.xml and setup.py profile = 'profile-{0}:default'.format(product) @@ -47,6 +49,9 @@ def upgrade(tool): # section from Dashboard add_sample_section_in_dashboard(portal) + # Ability to choose the sticker templates based on sample types (#607) + set_sample_type_default_stickers(portal) + logger.info("{0} upgraded to version {1}".format(product, version)) return True @@ -69,3 +74,26 @@ def fix_worksheet_template_index(portal, ut): def add_sample_section_in_dashboard(portal): setup_dashboard_panels_visibility_registry('samples') + +def set_sample_type_default_stickers(portal): + """ + Fills the admitted stickers and their default stickers to every sample + type. + """ + # Getting all sticker templates + stickers = getStickerTemplates() + sticker_ids = [] + for sticker in stickers: + sticker_ids.append(sticker.get('id')) + def_small_template = portal.bika_setup.getSmallStickerTemplate() + def_large_template = portal.bika_setup.getLargeStickerTemplate() + # Getting all Sample Type objects + catalog = api.get_tool('bika_setup_catalog') + brains = catalog(portal_type='SampleType') + for brain in brains: + obj = api.get_object(brain) + if obj.getAdmittedStickers() is not None: + continue + obj.setAdmittedStickers(sticker_ids) + obj.setDefaultLargeSticker(def_large_template) + obj.setDefaultSmallSticker(def_small_template) From 2a86ec1710288388e91d3889cd42b7995885cd0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Thu, 8 Feb 2018 13:14:58 +0100 Subject: [PATCH 17/17] Remove duplicate code --- bika/lims/content/sampletype.py | 30 +++--------------------------- 1 file changed, 3 insertions(+), 27 deletions(-) diff --git a/bika/lims/content/sampletype.py b/bika/lims/content/sampletype.py index 869a827275..14f33a8452 100644 --- a/bika/lims/content/sampletype.py +++ b/bika/lims/content/sampletype.py @@ -318,18 +318,6 @@ def setDefaultSmallSticker(self, value): :param value: A sticker ID """ - if value is None: - logger.error( - "Setting wrong 'AdmittedStickerTemplates/small_default' value" - " to Sample Type '{}'" - .format(self.getId())) - return - if not isinstance(value, str): - logger.error( - "Setting wrong 'AdmittedStickerTemplates/small_default' value" - " type to Sample Type '{}'" - .format(self.getId())) - return self._set_sticker_subfield(SMALL_DEFAULT_STICKER, value) def setDefaultLargeSticker(self, value): @@ -338,18 +326,6 @@ def setDefaultLargeSticker(self, value): :param value: A sticker ID """ - if value is None: - logger.error( - "Setting wrong 'AdmittedStickerTemplates/large_default' value" - " to Sample Type '{}'" - .format(self.getId())) - return - if not isinstance(value, str): - logger.error( - "Setting wrong 'AdmittedStickerTemplates/large_default' value" - " type to Sample Type '{}'" - .format(self.getId())) - return self._set_sticker_subfield(LARGE_DEFAULT_STICKER, value) def setAdmittedStickers(self, value): @@ -358,6 +334,9 @@ def setAdmittedStickers(self, value): :param value: An array of sticker IDs """ + self._set_sticker_subfield('admitted', value) + + def _set_sticker_subfield(self, subfield, value): if value is None: logger.error( "Setting wrong 'AdmittedStickerTemplates/admitted' value" @@ -370,9 +349,6 @@ def setAdmittedStickers(self, value): " type to Sample Type '{}'" .format(self.getId())) return - self._set_sticker_subfield('admitted', value) - - def _set_sticker_subfield(self, subfield, value): field = self.getField('AdmittedStickerTemplates') stickers = field.get(self) stickers[0][subfield] = value