class PercentValidator: """ Floatable, >=0, <=100. """ implements(IValidator) name = "percentvalidator" def __call__(self, value, *args, **kwargs): instance = kwargs['instance'] # fieldname = kwargs['field'].getName() # request = kwargs.get('REQUEST', {}) # form = request.get('form', {}) translate = getToolByName(instance, 'translation_service').translate try: value = float(value) except: msg = _("Validation failed: percent values must be numbers") return to_utf8(translate(msg)) if value < 0 or value > 100: msg = _( "Validation failed: percent values must be between 0 and 100") return to_utf8(translate(msg)) return True
class StandardIDValidator: """Matches against regular expression: [^A-Za-z\w\d\-\_] """ implements(IValidator) name = "standard_id_validator" def __call__(self, value, *args, **kwargs): regex = r"[^A-Za-z\w\d\-\_]" instance = kwargs['instance'] # fieldname = kwargs['field'].getName() # request = kwargs.get('REQUEST', {}) # form = request.get('form', {}) translate = getToolByName(instance, 'translation_service').translate # check the value against all AnalysisService keywords if re.findall(regex, value): msg = _("Validation failed: keyword contains invalid " "characters") return to_utf8(translate(msg)) return True
class BikaAnalysisCatalog(CatalogTool): """Catalog for analysis types""" implements(IBikaAnalysisCatalog) security = ClassSecurityInfo() _properties = ({'id': 'title', 'type': 'string', 'mode': 'w'}, ) title = 'Bika Analysis Catalog' id = 'bika_analysis_catalog' portal_type = meta_type = 'BikaAnalysisCatalog' plone_tool = 1 def __init__(self): ZCatalog.__init__(self, self.id) security.declareProtected(ManagePortal, 'clearFindAndRebuild') def clearFindAndRebuild(self): """ """ def indexObject(obj, path): self.reindexObject(obj) at = getToolByName(self, 'archetype_tool') types = [k for k, v in at.catalog_map.items() if self.id in v] self.manage_catalogClear() portal = getToolByName(self, 'portal_url').getPortalObject() portal.ZopeFindAndApply(portal, obj_metatypes=types, search_sub=True, apply_func=indexObject)
class DefaultReferenceWidgetVocabulary(object): implements(IReferenceWidgetVocabulary) def __init__(self, context, request): self.context = context self.request = request def __call__(self, result=None, specification=None, **kwargs): searchTerm = _c(self.request.get('searchTerm', '')).lower() force_all = self.request.get('force_all', 'true') searchFields = 'search_fields' in self.request \ and json.loads(_u(self.request.get('search_fields', '[]'))) \ or ('Title',) # lookup objects from ZODB catalog_name = _c(self.request.get('catalog_name', 'portal_catalog')) catalog = getToolByName(self.context, catalog_name) base_query = json.loads(_c(self.request['base_query'])) search_query = json.loads(_c(self.request.get('search_query', "{}"))) # first with all queries contentFilter = dict((k, v) for k, v in base_query.items()) contentFilter.update(search_query) try: brains = catalog(contentFilter) except: from lims import logger logger.info(contentFilter) raise if brains and searchTerm: _brains = [] if len(searchFields) == 0 \ or (len(searchFields) == 1 and searchFields[0] == 'Title'): _brains = [ p for p in brains if p.Title.lower().find(searchTerm) > -1 ] else: for p in brains: for fieldname in searchFields: value = getattr(p, fieldname, None) if not value: instance = p.getObject() schema = instance.Schema() if fieldname in schema: value = schema[fieldname].get(instance) if value and value.lower().find(searchTerm) > -1: _brains.append(p) break brains = _brains # Then just base_query alone ("show all if no match") if not brains and force_all.lower() == 'true': if search_query: brains = catalog(base_query) if brains and searchTerm: _brains = [ p for p in brains if p.Title.lower().find(searchTerm) > -1 ] if _brains: brains = _brains return brains
class NIBvalidator: """ Validates if the introduced NIB is correct. """ implements(IValidator) name = "NIBvalidator" def __call__(self, value, *args, **kwargs): """ Check the NIB number value:: string with NIB. """ instance = kwargs['instance'] translate = getToolByName(instance, 'translation_service').translate LEN_NIB = 21 table = (73, 17, 89, 38, 62, 45, 53, 15, 50, 5, 49, 34, 81, 76, 27, 90, 9, 30, 3) # convert to entire numbers list nib = _toIntList(value) # checking the length of the number if len(nib) != LEN_NIB: msg = _('Incorrect NIB number: %s' % value) return to_utf8(translate(msg)) # last numbers algorithm validator return nib[-2] * 10 + nib[-1] == 98 - _sumLists(table, nib[:-2]) % 97
class LabContact(Person): security = ClassSecurityInfo() displayContentsTab = False schema = schema implements(ILabContact) _at_rename_after_creation = True def _renameAfterCreation(self, check_auto_id=False): from lims.idserver import renameAfterCreation renameAfterCreation(self) def Title(self): """ Return the contact's Fullname as title """ return safe_unicode(self.getFullname()).encode('utf-8') def hasUser(self): """ check if contact has user """ return self.portal_membership.getMemberById( self.getUsername()) is not None def getDepartments(self): bsc = getToolByName(self, 'bika_setup_catalog') items = [('','')] + [(o.UID, o.Title) for o in bsc(portal_type='Department', inactive_state = 'active')] o = self.getDepartment() if o and o.UID() not in [i[0] for i in items]: items.append((o.UID(), o.Title())) items.sort(lambda x,y: cmp(x[1], y[1])) return DisplayList(list(items))
class CatalogVocabulary(object): """Make vocabulary from catalog query. """ implements(IDisplayListVocabulary) catalog = 'portal_catalog' contentFilter = {} key = 'UID' value = 'Title' def __init__(self, context): self.context = context def __call__(self, **kwargs): site = getSite() request = aq_get(site, 'REQUEST', None) catalog = getToolByName(site, self.catalog) if 'inactive_state' in catalog.indexes(): self.contentFilter['inactive_state'] = 'active' if 'cancellation_state' in catalog.indexes(): self.contentFilter['cancellation_state'] = 'active' self.contentFilter.update(**kwargs) objects = (b.getObject() for b in catalog(self.contentFilter)) items = [] for obj in objects: key = obj[self.key] key = callable(key) and key() or key value = obj[self.value] value = callable(value) and value() or value items.append((key, t(value))) return DisplayList(items)
class InstrumentCertificationsViewView(BrowserView): """ View of Instrument Certifications Shows the list of Instrument Certifications, either Internal and External Calibrations. """ implements(IViewView) template = ViewPageTemplateFile("templates/instrument_certifications.pt") _certificationsview = None def __call__(self): return self.template() def get_certifications_table(self): """ Returns the table of Certifications """ return self.get_certifications_view().contents_table() def get_certifications_view(self): """ Returns the Certifications Table view """ if not self._certificationsview: self._certificationsview = InstrumentCertificationsView( self.context, self.request) return self._certificationsview
class AnalysisProfile(BaseContent): security = ClassSecurityInfo() schema = schema displayContentsTab = False implements(IAnalysisProfile) _at_rename_after_creation = True def _renameAfterCreation(self, check_auto_id=False): from lims.idserver import renameAfterCreation renameAfterCreation(self) def getClientUID(self): return self.aq_parent.UID() def getAnalysisServiceSettings(self, uid): """ Returns a dictionary with the settings for the analysis service that match with the uid provided. If there are no settings for the analysis service and profile, returns a dictionary with the key 'uid' """ sets = [s for s in self.getAnalysisServicesSettings() \ if s.get('uid','') == uid] return sets[0] if sets else {'uid': uid} def isAnalysisServiceHidden(self, uid): """ Checks if the analysis service that match with the uid provided must be hidden in results. If no hidden assignment has been set for the analysis in this profile, returns the visibility set to the analysis itself. Raise a TypeError if the uid is empty or None Raise a ValueError if there is no hidden assignment in this profile or no analysis service found for this uid. """ if not uid: raise TypeError('None type or empty uid') sets = self.getAnalysisServiceSettings(uid) if 'hidden' not in sets: uc = getToolByName(self, 'uid_catalog') serv = uc(UID=uid) if serv and len(serv) == 1: return serv[0].getObject().getRawHidden() else: raise ValueError('%s is not valid' % uid) return sets.get('hidden', False) def getVATAmount(self): """ Compute AnalysisProfileVATAmount """ price, vat = self.getAnalysisProfilePrice( ), self.getAnalysisProfileVAT() return float(price) * float(vat) / 100 def getTotalPrice(self): """ Computes the final price using the VATAmount and the subtotal price """ price, vat = self.getAnalysisProfilePrice(), self.getVATAmount() return float(price) + float(vat)
class JSONReadExtender(object): """- Adds the full details of all analyses to the AR.Analyses field """ implements(IJSONReadExtender) adapts(IAnalysisRequest) def __init__(self, context): self.context = context def ar_analysis_values(self): ret = [] analyses = self.context.getAnalyses(cancellation_state='active') for proxy in analyses: analysis = proxy.getObject() service = analysis.getService() if proxy.review_state == 'retracted': # these are scraped up when Retested analyses are found below. continue # things that are manually inserted into the analysis. # These things will be included even if they are not present in # include_fields in the request. method = analysis.getMethod() if not method: method = service.getMethod() service = analysis.getService() analysis_data = { "Uncertainty": service.getUncertainty(analysis.getResult()), "Method": method.Title() if method else '', "Unit": service.getUnit(), } # Place all schema fields ino the result. analysis_data.update(load_brain_metadata(proxy, [])) # Place all schema fields ino the result. analysis_data.update(load_field_values(analysis, [])) # call any adapters that care to modify the Analysis data. # adapters = getAdapters((analysis, ), IJSONReadExtender) # for name, adapter in adapters: # adapter(request, analysis_data) if not self.include_fields or "transitions" in self.include_fields: analysis_data['transitions'] = get_workflow_actions(analysis) if analysis.getRetested(): retracted = self.context.getAnalyses(review_state='retracted', title=analysis.Title(), full_objects=True) prevs = sorted(retracted, key=lambda item: item.created()) prevs = [{ 'created': str(p.created()), 'Result': p.getResult(), 'InterimFields': p.getInterimFields() } for p in prevs] analysis_data['Previous Results'] = prevs ret.append(analysis_data) return ret def __call__(self, request, data): self.request = request self.include_fields = get_include_fields(request) if not self.include_fields or "Analyses" in self.include_fields: data['Analyses'] = self.ar_analysis_values()
class ResultOutOfRange(object): """Return alerts for any analyses inside the context ar """ implements(IFieldIcons) adapts(IAnalysisRequest) def __init__(self, context): self.context = context def __call__(self, result=None, **kwargs): workflow = getToolByName(self.context, 'portal_workflow') items = self.context.getAnalyses() field_icons = {} for obj in items: obj = obj.getObject() if hasattr(obj, 'getObject') else obj uid = obj.UID() astate = workflow.getInfoFor(obj, 'review_state') if astate == 'retracted': continue adapters = getAdapters((obj, ), IFieldIcons) for name, adapter in adapters: alerts = adapter(obj) if alerts: if uid in field_icons: field_icons[uid].extend(alerts[uid]) else: field_icons[uid] = alerts[uid] return field_icons
class AnalysisCategory(BaseContent): implements(IAnalysisCategory) security = ClassSecurityInfo() displayContentsTab = False schema = schema _at_rename_after_creation = True def _renameAfterCreation(self, check_auto_id=False): from lims.idserver import renameAfterCreation renameAfterCreation(self) def getDepartments(self): bsc = getToolByName(self, 'bika_setup_catalog') deps = [] for d in bsc(portal_type='Department', inactive_state='active'): deps.append((d.UID, d.Title)) return DisplayList(deps) def workflow_script_deactivat(self): # A instance cannot be deactivated if it contains services pu = getToolByName(self, 'plone_utils') bsc = getToolByName(self, 'bika_setup_catalog') ars = bsc(portal_type='AnalysisService', getCategoryUID=self.UID()) if ars: message = _("Category cannot be deactivated because " "it contains Analysis Services") pu.addPortalMessage(message, 'error') transaction.get().abort() raise WorkflowException
class BikaContentVocabulary(object): """Vocabulary factory for Bika Setup objects. We find them by listing folder contents directly. """ implements(IVocabularyFactory) def __init__(self, folders, portal_types): self.folders = isinstance(folders, (tuple, list)) and \ folders or [folders, ] self.portal_types = isinstance(portal_types, (tuple, list)) and \ portal_types or [portal_types, ] def __call__(self, context): site = getSite() request = aq_get(site, 'REQUEST', None) items = [] wf = site.portal_workflow for folder in self.folders: folder = site.restrictedTraverse(folder) for portal_type in self.portal_types: objects = list(folder.objectValues(portal_type)) objects = [ o for o in objects if wf.getInfoFor(o, 'inactive_state') == 'active' ] if not objects: continue objects.sort(lambda x, y: cmp(x.Title().lower(), y.Title().lower())) xitems = [(t(item.Title()), item.Title()) for item in objects] xitems = [SimpleTerm(i[1], i[1], i[0]) for i in xitems] items += xitems return SimpleVocabulary(items)
class UniqueFieldValidator: """ Verifies that a field value is unique for items if the same type in this location """ implements(IValidator) name = "uniquefieldvalidator" def __call__(self, value, *args, **kwargs): instance = kwargs['instance'] fieldname = kwargs['field'].getName() # request = kwargs.get('REQUEST', {}) # form = request.get('form', {}) translate = getToolByName(instance, 'translation_service').translate if value == instance.get(fieldname): return True for item in aq_parent(instance).objectValues(): if hasattr(item, 'UID') and item.UID() != instance.UID() and \ fieldname in item.Schema() and \ str(item.Schema()[fieldname].get(item)) == str(value): # We have to compare them as strings because # even if a number (as an id) is saved inside # a string widget and string field, it will be # returned as an int. I don't know if it is # caused because is called with # <item.Schema()[fieldname].get(item)>, # but it happens... msg = _("Validation failed: '${value}' is not unique", mapping={'value': safe_unicode(value)}) return to_utf8(translate(msg)) return True
class PrePreservationValidator: """ Validate PrePreserved Containers. User must select a Preservation. """ implements(IValidator) name = "container_prepreservation_validator" def __call__(self, value, *args, **kwargs): # If not prepreserved, no validation required. if not value: return True instance = kwargs['instance'] # fieldname = kwargs['field'].getName() request = kwargs.get('REQUEST', {}) form = request.form preservation = form.get('Preservation') if type(preservation) in (list, tuple): preservation = preservation[0] if preservation: return True translate = getToolByName(instance, 'translation_service').translate # bsc = getToolByName(instance, 'bika_setup_catalog') if not preservation: msg = _("Validation failed: PrePreserved containers " "must have a preservation selected.") return to_utf8(translate(msg))
class ClientFieldWidgetVisibility(object): """The Client field is editable by default in ar_add. This adapter will force the Client field to be hidden when it should not be set by the user. """ implements(IATWidgetVisibility) def __init__(self, context): self.context = context self.sort = 10 def __call__(self, context, mode, field, default): state = default if default else 'hidden' fieldName = field.getName() if fieldName != 'Client': return state parent = self.context.aq_parent if IBatch.providedBy(parent): if parent.getClient(): return 'hidden' if IClient.providedBy(parent): return 'hidden' return state
class ServiceKeywordValidator: """Validate AnalysisService Keywords must match isUnixLikeName may not be the same as another service keyword may not be the same as any InterimField id. """ implements(IValidator) name = "servicekeywordvalidator" def __call__(self, value, *args, **kwargs): instance = kwargs['instance'] # fieldname = kwargs['field'].getName() # request = kwargs.get('REQUEST', {}) # form = request.get('form', {}) translate = getToolByName(instance, 'translation_service').translate if re.findall(r"[^A-Za-z\w\d\-\_]", value): return _("Validation failed: keyword contains invalid characters") # check the value against all AnalysisService keywords # this has to be done from catalog so we don't # clash with ourself bsc = getToolByName(instance, 'bika_setup_catalog') services = bsc(portal_type='AnalysisService', getKeyword=value) for service in services: if service.UID != instance.UID(): msg = _( "Validation failed: '${title}': This keyword " "is already in use by service '${used_by}'", mapping={ 'title': safe_unicode(value), 'used_by': safe_unicode(service.Title) }) return to_utf8(translate(msg)) calc = hasattr(instance, 'getCalculation') and \ instance.getCalculation() or None our_calc_uid = calc and calc.UID() or '' # check the value against all Calculation Interim Field ids calcs = [c for c in bsc(portal_type='Calculation')] for calc in calcs: calc = calc.getObject() interim_fields = calc.getInterimFields() if not interim_fields: continue for field in interim_fields: if field['keyword'] == value and our_calc_uid != calc.UID(): msg = _( "Validation failed: '${title}': This keyword " "is already in use by calculation '${used_by}'", mapping={ 'title': safe_unicode(value), 'used_by': safe_unicode(calc.Title()) }) return to_utf8(translate(msg)) return True
class InstrumentMultifileView(MultifileView): implements(IFolderContentsView, IViewView) def __init__(self, context, request): super(InstrumentMultifileView, self).__init__(context, request) self.show_workflow_action_buttons = False self.title = self.context.translate(_("Instrument Files")) self.description = "Different interesting documents and files to be attached to the instrument"
class PreservationsView(BikaListingView): implements(IFolderContentsView, IViewView) def __init__(self, context, request): super(PreservationsView, self).__init__(context, request) self.catalog = 'bika_setup_catalog' self.contentFilter = {'portal_type': 'Preservation', 'sort_on': 'sortable_title'} self.context_actions = {_('Add'): {'url': 'createObject?type_name=Preservation', 'icon': '++resource++bika.lims.images/add.png'}} self.title = self.context.translate(_("Preservations")) self.icon = self.portal_url + "/++resource++bika.lims.images/preservation_big.png" self.description = "" self.show_sort_column = False self.show_select_row = False self.show_select_column = True self.pagesize = 25 self.columns = { 'Title': {'title': _('Preservation'), 'index':'sortable_title'}, 'Description': {'title': _('Description'), 'index': 'description', 'toggle': True}, } self.review_states = [ {'id':'default', 'title': _('Active'), 'contentFilter': {'inactive_state': 'active'}, 'transitions': [{'id':'deactivate'}, ], 'columns': ['Title', 'Description']}, {'id':'inactive', 'title': _('Dormant'), 'contentFilter': {'inactive_state': 'inactive'}, 'transitions': [{'id':'activate'}, ], 'columns': ['Title', 'Description']}, {'id':'all', 'title': _('All'), 'contentFilter':{}, 'columns': ['Title', 'Description']}, ] def folderitems(self): items = BikaListingView.folderitems(self) for x in range(len(items)): if not items[x].has_key('obj'): continue obj = items[x]['obj'] items[x]['Description'] = obj.Description() items[x]['replace']['Title'] = "<a href='%s'>%s</a>" % \ (items[x]['url'], items[x]['Title']) return items
class ARImportItem(BaseContent): security = ClassSecurityInfo() implements(IARImportItem) schema = schema displayContentsTab = False def Title(self): """ Return the Product as title """ return safe_unicode(self.getSampleName()).encode('utf-8')
class ARPriority(BaseContent): security = ClassSecurityInfo() schema = schema displayContentsTab = False implements(IARPriority) _at_rename_after_creation = True def _renameAfterCreation(self, check_auto_id=False): renameAfterCreation(self)
class BikaSetup(folder.ATFolder): security = ClassSecurityInfo() schema = schema implements(IBikaSetup, IHaveNoBreadCrumbs) def getAttachmentsPermitted(self): """ are any attachments permitted """ if self.getARAttachmentOption() in ['r', 'p'] \ or self.getAnalysisAttachmentOption() in ['r', 'p']: return True else: return False def getStickerTemplates(self): """ get the sticker templates """ out = [[t['id'], t['title']] for t in _getStickerTemplates()] return DisplayList(out) def getARAttachmentsPermitted(self): """ are AR attachments permitted """ if self.getARAttachmentOption() == 'n': return False else: return True def getAnalysisAttachmentsPermitted(self): """ are analysis attachments permitted """ if self.getAnalysisAttachmentOption() == 'n': return False else: return True def getAnalysisServices(self): """ """ bsc = getToolByName(self, 'bika_setup_catalog') items = [('','')] + [(o.UID, o.Title) for o in bsc(portal_type='AnalysisService', inactive_state = 'active')] items.sort(lambda x,y: cmp(x[1], y[1])) return DisplayList(list(items)) def getPrefixFor(self, portal_type): """Return the prefix for a portal_type. If not found, simply uses the portal_type itself """ prefix = [p for p in self.getPrefixes() if p['portal_type'] == portal_type] if prefix: return prefix[0]['prefix'] else: return portal_type def getCountries(self): items = [(x['ISO'], x['Country']) for x in COUNTRIES] items.sort(lambda x,y: cmp(x[1], y[1])) return items
class InstrumentType(BaseContent): implements(IInstrumentType) security = ClassSecurityInfo() displayContentsTab = False schema = schema _at_rename_after_creation = True def _renameAfterCreation(self, check_auto_id=False): from lims.idserver import renameAfterCreation renameAfterCreation(self)
class ARReportTemplatesVocabulary(object): """Locate all ARReport templates to allow user to set the default """ implements(IVocabularyFactory) def __call__(self, context): out = [ SimpleTerm(x['id'], x['id'], x['title']) for x in getARReportTemplates() ] return SimpleVocabulary(out)
class StickerTemplatesVocabulary(object): """ Locate all sticker templates """ implements(IVocabularyFactory) def __call__(self, context): out = [ SimpleTerm(x['id'], x['id'], x['title']) for x in getStickerTemplates() ] return SimpleVocabulary(out)
class TemplatesView(BikaListingView): implements(IFolderContentsView, IViewView) def __init__(self, context, request): super(TemplatesView, self).__init__(context, request) self.catalog = "bika_setup_catalog" self.contentFilter = { 'portal_type': 'SRTemplate', 'sort_order': 'sortable_title', 'path': { "query": "/".join(self.context.getPhysicalPath()), "level": 0 }, } self.show_sort_column = False self.show_select_row = False self.show_select_column = True self.icon = self.portal_url + "/++resource++bika.lims.images/artemplate_big.png" self.title = self.context.translate(_("SR Templates")) self.description = "" self.context_actions = { _('Add Template'): { 'url': 'createObject?type_name=SRTemplate', 'icon': '++resource++bika.lims.images/add.png' } } self.columns = { 'Title': { 'title': _('Template'), 'index': 'sortable_title' }, 'Description': { 'title': _('Description'), 'index': 'description' }, } self.review_states = [{ 'id':'default', 'title': _('Default'), 'contentFilter': {}, 'columns': ['Title', 'Description'] }] def folderitems(self): items = BikaListingView.folderitems(self) for item in items: if not item.has_key('obj'): continue obj = item['obj'] title_link = "<a href='%s'>%s</a>" % (item['url'], item['title']) item['replace']['Title'] = title_link return items
class Invoice(BaseFolder): implements(IInvoice) security = ClassSecurityInfo() displayContentsTab = False schema = schema _at_rename_after_creation = True def _renameAfterCreation(self, check_auto_id=False): from lims.idserver import renameAfterCreation renameAfterCreation(self) def Title(self): """ Return the Invoice Id as title """ return safe_unicode(self.getId()).encode('utf-8') security.declareProtected(View, 'getSubtotal') def getSubtotal(self): """ Compute Subtotal """ return sum([float(obj['Subtotal']) for obj in self.invoice_lineitems]) security.declareProtected(View, 'getVATAmount') def getVATAmount(self): """ Compute VAT """ return Decimal(self.getTotal()) - Decimal(self.getSubtotal()) security.declareProtected(View, 'getTotal') def getTotal(self): """ Compute Total """ return sum([float(obj['Total']) for obj in self.invoice_lineitems]) security.declareProtected(View, 'getInvoiceSearchableText') def getInvoiceSearchableText(self): """ Aggregate text of all line items for querying """ s = '' for item in self.invoice_lineitems: s = s + item['ItemDescription'] return s # XXX workflow script def workflow_script_dispatch(self): """ dispatch order """ self.setDateDispatched(DateTime()) security.declarePublic('current_date') def current_date(self): """ return current date """ return DateTime()
class DateTimeField(DTF): """A field that stores dates and times This is identical to the AT widget on which it's based, but it checks the i18n translation values for date formats. This does not specifically check the date_format_short_datepicker, so this means that date_formats should be identical between the python strftime and the jquery version. """ _properties = Field._properties.copy() _properties.update({ 'type': 'datetime', 'widget': CalendarWidget, }) implements(IDateTimeField) security = ClassSecurityInfo() security.declarePrivate('set') def set(self, instance, value, **kwargs): """ Check if value is an actual date/time value. If not, attempt to convert it to one; otherwise, set to None. Assign all properties passed as kwargs to object. """ val = value if not value: val = None elif not isinstance(value, DateTime): for fmt in ['date_format_long', 'date_format_short']: fmtstr = instance.translate(fmt, domain='bika', mapping={}) fmtstr = fmtstr.replace(r"${", '%').replace('}', '') try: val = strptime(value, fmtstr) except ValueError: continue try: val = DateTime(*list(val)[:-6]) except DateTimeError: val = None if val.timezoneNaive(): # Use local timezone for tz naive strings # see http://dev.plone.org/plone/ticket/10141 zone = val.localZone(safelocaltime(val.timeTime())) parts = val.parts()[:-1] + (zone, ) val = DateTime(*parts) break else: logger.warning("DateTimeField failed to format date " "string '%s' with '%s'" % (value, fmtstr)) super(DateTimeField, self).set(instance, val, **kwargs)
class WorkflowAwareWidgetVisibility(object): """This adapter allows the schema definition to have different widget visibility settings for different workflow states in the primary review_state workflow. With this it is possible to write: StringField( 'fieldName', widget=StringWidget( label=_('field Name'), visible = { 'edit': 'visible', # regular AT uses these and they override 'view': 'visible', # everything, without 'edit' you cannot edit 'wf_state': {'edit': 'invisible', 'view': 'visible' }, 'other_state': {'edit': 'visible', 'view': 'invisible'}, } The rules about defaults, "hidden", "visible" and "invisible" are the same as those from the default Products.Archetypes.Widget.TypesWidget#isVisible """ implements(IATWidgetVisibility) def __init__(self, context): self.context = context self.sort = 100 def __call__(self, context, mode, field, default): """ """ state = default if default else 'visible' workflow = getToolByName(self.context, 'portal_workflow') try: review_state = workflow.getInfoFor(self.context, 'review_state') except WorkflowException: return state vis_dic = field.widget.visible if type(vis_dic) is not DictType or review_state not in vis_dic: return state inner_vis_dic = vis_dic.get(review_state, state) if inner_vis_dic is _marker: state = state if type(inner_vis_dic) is DictType: state = inner_vis_dic.get(mode, state) state = state elif not inner_vis_dic: state = 'invisible' elif inner_vis_dic < 0: state = 'hidden' return state
class FormulaValidator: """ Validate keywords in calculation formula entry """ implements(IValidator) name = "formulavalidator" def __call__(self, value, *args, **kwargs): if not value: return True instance = kwargs['instance'] # fieldname = kwargs['field'].getName() request = kwargs.get('REQUEST', {}) form = request.form interim_fields = form.get('InterimFields') translate = getToolByName(instance, 'translation_service').translate bsc = getToolByName(instance, 'bika_setup_catalog') interim_keywords = interim_fields and \ [f['keyword'] for f in interim_fields] or [] keywords = re.compile(r"\[([^\.^\]]+)\]").findall(value) for keyword in keywords: # Check if the service keyword exists and is active. dep_service = bsc(getKeyword=keyword, inactive_state="active") if not dep_service and \ not keyword in interim_keywords: msg = _("Validation failed: Keyword '${keyword}' is invalid", mapping={'keyword': safe_unicode(keyword)}) return to_utf8(translate(msg)) # Wildcards # LIMS-1769 Allow to use LDL and UDL in calculations # https://jira.bikalabs.com/browse/LIMS-1769 allowedwds = ['LDL', 'UDL', 'BELOWLDL', 'ABOVEUDL'] keysandwildcards = re.compile(r"\[([^\]]+)\]").findall(value) keysandwildcards = [k for k in keysandwildcards if '.' in k] keysandwildcards = [k.split('.', 1) for k in keysandwildcards] errwilds = [k[1] for k in keysandwildcards if k[0] not in keywords] if len(errwilds) > 0: msg = _("Wildcards for interims are not allowed: ${wildcards}", mapping={'wildcards': safe_unicode(', '.join(errwilds))}) return to_utf8(translate(msg)) wildcards = [k[1] for k in keysandwildcards if k[0] in keywords] wildcards = [wd for wd in wildcards if wd not in allowedwds] if len(wildcards) > 0: msg = _("Invalid wildcards found: ${wildcards}", mapping={'wildcards': safe_unicode(', '.join(wildcards))}) return to_utf8(translate(msg)) return True