示例#1
0
def before_transition_handler(instance, event):
    """Always update the modification date before a WF transition.

    This ensures that all cache keys are invalidated.
    """
    parent = api.get_parent(instance)
    if api.get_portal_type(instance) == "AnalysisRequest":
        update_ar_modification_dates(instance)
    elif api.get_portal_type(parent) == "AnalysisRequest":
        update_ar_modification_dates(parent)
    else:
        update_modification_date(instance)
示例#2
0
    def metadata_to_searchable_text(self, brain, key, value):
        """Parse the given metadata to text

        :param brain: ZCatalog Brain
        :param key: The name of the metadata column
        :param value: The raw value of the metadata column
        :returns: Searchable and translated unicode value or None
        """
        if not value:
            return u""
        if value is Missing.Value:
            return u""
        if api.is_uid(value):
            return u""
        if isinstance(value, (bool)):
            return u""
        if isinstance(value, (list, tuple)):
            for v in value:
                return self.metadata_to_searchable_text(brain, key, v)
        if isinstance(value, (dict)):
            for k, v in value.items():
                return self.metadata_to_searchable_text(brain, k, v)
        if self.is_date(value):
            return self.to_str_date(value)
        if "state" in key.lower():
            return self.translate_review_state(value,
                                               api.get_portal_type(brain))
        if not isinstance(value, basestring):
            value = str(value)
        return safe_unicode(value)
示例#3
0
def get_generated_number(context, config, variables, **kw):
    """Generate a new persistent number with the number generator for the
    sequence type "Generated"
    """

    # separator where to split the ID
    separator = kw.get('separator', '-')

    # allow portal_type override
    portal_type = kw.get("portal_type") or api.get_portal_type(context)

    # The ID format for string interpolation, e.g. WS-{seq:03d}
    id_template = config.get("form", "")

    # The split length defines where the variable part of the ID template begins
    split_length = config.get("split_length", 1)

    # The prefix tempalte is the static part of the ID
    prefix_template = slice(id_template, separator=separator, end=split_length)

    # get the number generator
    number_generator = getUtility(INumberGenerator)

    # generate the key for the number generator storage
    prefix = prefix_template.format(**variables)

    # normalize out any unicode characters like Ö, É, etc. from the prefix
    prefix = api.normalize_filename(prefix)

    # The key used for the storage
    key = make_storage_key(portal_type, prefix)

    # Handle flushed storage
    if key not in number_generator:
        max_num = 0
        existing = get_ids_with_prefix(portal_type, prefix)
        numbers = map(
            lambda id: get_seq_number_from_id(id, id_template, prefix),
            existing)
        # figure out the highest number in the sequence
        if numbers:
            max_num = max(numbers)
        # set the number generator
        logger.info("*** SEEDING Prefix '{}' to {}".format(prefix, max_num))
        number_generator.set_number(key, max_num)

    if not kw.get("dry_run", False):
        # Generate a new number
        # NOTE Even when the number exceeds the given ID sequence format,
        #      it will overflow gracefully, e.g.
        #      >>> {sampleId}-R{seq:03d}'.format(sampleId="Water", seq=999999)
        #      'Water-R999999‘
        number = number_generator.generate_number(key=key)
    else:
        # => This allows us to "preview" the next generated ID in the UI
        # TODO Show the user the next generated number somewhere in the UI
        number = number_generator.get(key, 1)

    # Return an int or Alphanumber
    return get_alpha_or_number(number, id_template)
示例#4
0
    def get_default_attributes(self, obj):
        """Returns the default attributes from the object to keep mapped
        against the SQL database
        """
        portal_type = api.get_portal_type(obj)
        if portal_type not in self.get_multiplexed_types():
            return []

        def is_field_supported(field):
            if field.getName() in NON_SUPPORTED_FIELD_NAMES:
                return False
            if field.type in NON_SUPPORTED_FIELD_TYPES:
                return False
            return True

        # Grab only attributes that make sense!
        fields = api.get_fields(obj).values()
        fields = filter(is_field_supported, fields)

        # Get the ids of the fields to store
        attrs = map(lambda f: f.getName(), fields)
        if not attrs:
            return []

        # Always keep the UID
        if "UID" not in attrs:
            attrs.append("UID")
        return attrs
示例#5
0
    def _to_service(self, thing):
        """Convert to Analysis Service

        :param thing: UID/Catalog Brain/Object/Something
        :returns: Analysis Service object or None
        """

        # Convert UIDs to objects
        if api.is_uid(thing):
            thing = api.get_object_by_uid(thing, None)

        # Bail out if the thing is not a valid object
        if not api.is_object(thing):
            logger.warn("'{}' is not a valid object!".format(repr(thing)))
            return None

        # Ensure we have an object here and not a brain
        obj = api.get_object(thing)

        if IAnalysisService.providedBy(obj):
            return obj

        if IAnalysis.providedBy(obj):
            return obj.getAnalysisService()

        # An object, but neither an Analysis nor AnalysisService?
        # This should never happen.
        msg = "ARAnalysesField doesn't accept objects from {} type. " \
            "The object will be dismissed.".format(api.get_portal_type(obj))
        logger.warn(msg)
        return None
    def _to_service(self, thing):
        """Convert to Analysis Service

        :param thing: UID/Catalog Brain/Object/Something
        :returns: Analysis Service object or None
        """

        # Convert UIDs to objects
        if api.is_uid(thing):
            thing = api.get_object_by_uid(thing, None)

        # Bail out if the thing is not a valid object
        if not api.is_object(thing):
            logger.warn("'{}' is not a valid object!".format(repr(thing)))
            return None

        # Ensure we have an object here and not a brain
        obj = api.get_object(thing)

        if IAnalysisService.providedBy(obj):
            return obj

        if IAnalysis.providedBy(obj):
            return obj.getAnalysisService()

        # An object, but neither an Analysis nor AnalysisService?
        # This should never happen.
        portal_type = api.get_portal_type(obj)
        logger.error("ARAnalysesField doesn't accept objects from {} type. "
                     "The object will be dismissed.".format(portal_type))
        return None
示例#7
0
 def get_item_info(self, brain_or_object):
     """Return the data of this brain or object
     """
     portal_type = api.get_portal_type(brain_or_object)
     state = api.get_workflow_status_of(brain_or_object)
     return {
         "obj": brain_or_object,
         "uid": api.get_uid(brain_or_object),
         "url": api.get_url(brain_or_object),
         "id": api.get_id(brain_or_object),
         "title": api.get_title(brain_or_object),
         "portal_type": api.get_portal_type(brain_or_object),
         "review_state": state,
         "state_title": self.translate_review_state(state, portal_type),
         "state_class": "state-{}".format(state),
     }
示例#8
0
    def listing_identifier(self):
        """Identifier for similar listings

        This identifier is used as the local storage key for custom column
        configuration.

        Also see this issue for more details:
        https://github.com/senaite/senaite.core.listing/issues/16
        """
        key = None
        view_name = self.__name__
        portal_type = self.contentFilter.get("portal_type", None)
        # Handle the global Samples listing different, because the columns do
        # not match with the listings in Clients
        if api.get_portal_type(self.context) == "AnalysisRequestsFolder":
            key = "AnalysisRequestsListing"
        elif isinstance(portal_type, six.string_types):
            key = portal_type
        elif self.catalog == CATALOG_ANALYSIS_REQUEST_LISTING:
            key = "AnalysisRequest"
        elif self.catalog == CATALOG_ANALYSIS_LISTING:
            key = "Analysis"
        elif self.catalog == CATALOG_WORKSHEET_LISTING:
            key = "Worksheet"
        elif self.catalog == CATALOG_AUDITLOG:
            key = "Auditlog"
        else:
            return view_name
        return "-".join([key, view_name])
示例#9
0
def can_export(obj):
    """Decides if the object can be exported or not
    """
    if not api.is_object(obj):
        return False
    if api.get_portal_type(obj) in SKIP_TYPES:
        return False
    return True
示例#10
0
 def get_portal_type_title(self, obj):
     """Returns the title of the portal type of the obj passed-in
     """
     portal = api.get_portal()
     portal_type = api.get_portal_type(obj)
     portal_type = portal.portal_types.getTypeInfo(portal_type)
     if portal_type:
         return portal_type.title
     return None
示例#11
0
def get_generated_number(context, config, variables, **kw):
    """Generate a new persistent number with the number generator for the
    sequence type "Generated"
    """

    # separator where to split the ID
    separator = kw.get('separator', '-')

    # allow portal_type override
    portal_type = kw.get("portal_type") or api.get_portal_type(context)

    # The ID format for string interpolation, e.g. WS-{seq:03d}
    id_template = config.get("form", "")

    # The split length defines where the variable part of the ID template begins
    split_length = config.get("split_length", 1)

    # The prefix tempalte is the static part of the ID
    prefix_template = slice(id_template, separator=separator, end=split_length)

    # get the number generator
    number_generator = getUtility(INumberGenerator)

    # generate the key for the number generator storage
    prefix = prefix_template.format(**variables)

    # normalize out any unicode characters like Ö, É, etc. from the prefix
    prefix = api.normalize_filename(prefix)

    # The key used for the storage
    key = make_storage_key(portal_type, prefix)

    # Handle flushed storage
    if key not in number_generator:
        max_num = 0
        existing = get_ids_with_prefix(portal_type, prefix)
        numbers = map(lambda id: get_seq_number_from_id(id, id_template, prefix), existing)
        # figure out the highest number in the sequence
        if numbers:
            max_num = max(numbers)
        # set the number generator
        logger.info("*** SEEDING Prefix '{}' to {}".format(prefix, max_num))
        number_generator.set_number(key, max_num)

    if not kw.get("dry_run", False):
        # Generate a new number
        # NOTE Even when the number exceeds the given ID sequence format,
        #      it will overflow gracefully, e.g.
        #      >>> {sampleId}-R{seq:03d}'.format(sampleId="Water", seq=999999)
        #      'Water-R999999‘
        number = number_generator.generate_number(key=key)
    else:
        # => This allows us to "preview" the next generated ID in the UI
        # TODO Show the user the next generated number somewhere in the UI
        number = number_generator.get(key, 1)
    return number
示例#12
0
def to_link(obj, key, value, **kw):
    """to link
    """
    value = to_string(obj, key, value)
    if not value:
        return ""
    if api.get_portal_type(obj) in LINK_TO_PARENT_TYPES:
        obj = api.get_parent(obj)
    url = addTokenToUrl(api.get_url(obj))
    return get_link(url, value)
示例#13
0
    def unindex(self, obj):
        if not self.supports_multiplex(obj):
            return

        # Delete the object from the SQL db
        uid = api.get_uid(obj)
        portal_type = api.get_portal_type(obj)
        operation = "DELETE FROM {} WHERE UID='{}'".format(portal_type, uid)
        self.execute(operation, raise_error=False)

        # Do something here
        logger.info("Multiplexer::Unindexing {}".format(repr(obj)))
示例#14
0
 def get_item_info(self, brain_or_object):
     """Return the data of this brain or object
     """
     return {
         "obj": brain_or_object,
         "uid": api.get_uid(brain_or_object),
         "url": api.get_url(brain_or_object),
         "id": api.get_id(brain_or_object),
         "title": api.get_title(brain_or_object),
         "portal_type": api.get_portal_type(brain_or_object),
         "review_state": api.get_workflow_status_of(brain_or_object),
     }
示例#15
0
def init_auditlog(portal):
    """Initialize the contents for the audit log
    """
    # reindex the auditlog folder to display the icon right in the setup
    portal.bika_setup.auditlog.reindexObject()

    # Initialize contents for audit logging
    start = time.time()
    uid_catalog = api.get_tool("uid_catalog")
    brains = uid_catalog()
    total = len(brains)

    logger.info("Initializing {} objects for the audit trail...".format(total))
    for num, brain in enumerate(brains):
        # Progress notification
        if num and num % 1000 == 0:
            transaction.commit()
            logger.info("{}/{} ojects initialized for audit logging".format(
                num, total))
        # End progress notification
        if num + 1 == total:
            end = time.time()
            duration = float(end - start)
            logger.info(
                "{} ojects initialized for audit logging in {:.2f}s".format(
                    total, duration))

        if api.get_portal_type(brain) in SKIP_TYPES_FOR_AUDIT_LOG:
            continue

        obj = api.get_object(brain)

        if not supports_snapshots(obj):
            continue

        if has_snapshots(obj):
            continue

        # Take one snapshot per review history item
        rh = api.get_review_history(obj, rev=False)
        for item in rh:
            actor = item.get("actor")
            user = get_user(actor)
            if user:
                # remember the roles of the actor
                item["roles"] = get_roles(user)
            # The review history contains the variable "time" which we will set
            # as the "modification" time
            timestamp = item.pop("time", DateTime())
            item["time"] = timestamp.ISO()
            item["modified"] = timestamp.ISO()
            item["remote_address"] = None
            take_snapshot(obj, **item)
示例#16
0
    def get_table_create(self, obj, attributes):
        portal_type = api.get_portal_type(obj)

        def to_column(attribute):
            # TODO We just always assume a varchar type here!
            return "`{}` varchar(191) NULL".format(attribute)

        # Build the create table operation
        base = "CREATE TABLE `{}` ({}, PRIMARY KEY (`UID`)) ENGINE=InnoDB " \
               "DEFAULT CHARSET=utf8mb4"
        cols = ", ".join(map(to_column, attributes))
        operation = base.format(portal_type, cols)
        logger.info(operation)
        return operation
示例#17
0
def get_type_id(context, **kw):
    """Returns the type id for the context passed in
    """
    portal_type = kw.get("portal_type", None)
    if portal_type:
        return portal_type

    # Override by provided marker interface
    if IAnalysisRequestPartition.providedBy(context):
        return "AnalysisRequestPartition"
    elif IAnalysisRequestRetest.providedBy(context):
        return "AnalysisRequestRetest"

    return api.get_portal_type(context)
示例#18
0
    def get_fields(self, portal_type=None):
        """Returns all schema fields of the selected query type

        IMPORTANT: Do not call from within `__init__` due to permissions
        """
        obj = self._create_temporary_object(portal_type=portal_type)
        if obj is None:
            return []
        fields = api.get_fields(obj)
        # drop ignored fields
        for field in IGNORE_FIELDS:
            fields.pop(field, None)
        # Inject Parent Field
        portal_type = api.get_portal_type(obj)
        parent_type = PARENT_TYPES.get(portal_type)
        if parent_type:
            field = ParentField(portal_type=parent_type)
            fields["Parent"] = field
        return fields
示例#19
0
    def to_super_model(obj):
        # avoid circular imports
        from senaite.core.supermodel import SuperModel

        # Object is already a SuperModel, return immediately
        if isinstance(obj, SuperModel):
            return obj

        # Only portal objects are supported
        if not api.is_object(obj):
            return None

        # Wrap the object into a specific Publication Object Adapter
        uid = api.get_uid(obj)
        portal_type = api.get_portal_type(obj)

        adapter = queryAdapter(uid, ISuperModel, name=portal_type)
        if adapter is None:
            return SuperModel(uid)
        return adapter
示例#20
0
    def get_insert_update(self, obj, attributes):
        """Returns a tuple of two values: SQL insert-update operation, and
        operation parameters values. The name of the SQL table is the portal
        type. Attributes represent both obj functions/attributes and SQL columns
        :param obj: the object to insert
        :param attributes: attributes/columns from the object to be inserted
        """
        record = self.get_info(obj, attributes)
        portal_type = api.get_portal_type(obj)

        # Build the base insert/update thingy
        attrs = map(lambda a: "`{}`".format(a), attributes)
        update_values = map(lambda v: "{}=VALUES({})".format(v, v), attrs)
        insert = "INSERT INTO {} ({}) VALUES ({}) ON DUPLICATE KEY UPDATE {}"\
            .format(portal_type, ", ".join(attrs),
                    ", ".join(["%s"]*len(attrs)),
                    ", ".join(update_values))

        # Get the values for the columns
        data = map(lambda column: record.get(column) or "", attributes)
        return insert, data
示例#21
0
def get_config(context, **kw):
    """Fetch the config dict from the Bika Setup for the given portal_type
    """
    # get the ID formatting config
    config_map = api.get_bika_setup().getIDFormatting()

    # allow portal_type override
    portal_type = kw.get("portal_type") or api.get_portal_type(context)

    # check if we have a config for the given portal_type
    for config in config_map:
        if config['portal_type'].lower() == portal_type.lower():
            return config

    # return a default config
    default_config = {
        'form': '%s-{seq}' % portal_type.lower(),
        'sequence_type': 'generated',
        'prefix': '%s' % portal_type.lower(),
    }
    return default_config
示例#22
0
def get_config(context, **kw):
    """Fetch the config dict from the Bika Setup for the given portal_type
    """
    # get the ID formatting config
    config_map = api.get_bika_setup().getIDFormatting()

    # allow portal_type override
    portal_type = kw.get("portal_type") or api.get_portal_type(context)

    # check if we have a config for the given portal_type
    for config in config_map:
        if config['portal_type'].lower() == portal_type.lower():
            return config

    # return a default config
    default_config = {
        'form': '%s-{seq}' % portal_type.lower(),
        'sequence_type': 'generated',
        'prefix': '%s' % portal_type.lower(),
    }
    return default_config
示例#23
0
    def _get_service_uid(self, item):
        if api.is_uid(item):
            return item

        if not api.is_object(item):
            logger.warn("Not an UID: {}".format(item))
            return None

        obj = api.get_object(item)
        if IAnalysisService.providedBy(obj):
            return api.get_uid(obj)

        if IAnalysis.providedBy(obj) and IRequestAnalysis.providedBy(obj):
            return obj.getServiceUID()

        # An object, but neither an Analysis nor AnalysisService?
        # This should never happen.
        msg = "ARAnalysesField doesn't accept objects from {} type. " \
              "The object will be dismissed."
        logger.warn(msg.format(api.get_portal_type(obj)))
        return None
示例#24
0
    def get_icon_for(self, brain_or_object):
        """Get the navigation portlet icon for the brain or object

        The cache key ensures that the lookup is done only once per domain name
        """
        portal_types = api.get_tool("portal_types")
        fti = portal_types.getTypeInfo(api.get_portal_type(brain_or_object))
        icon = fti.getIcon()
        if not icon:
            return ""
        # Always try to get the big icon for high-res displays
        icon_big = icon.replace(".png", "_big.png")
        # fall back to a default icon if the looked up icon does not exist
        if self.context.restrictedTraverse(icon_big, None) is None:
            icon_big = None
        portal_url = api.get_url(api.get_portal())
        title = api.get_title(brain_or_object)
        html_tag = "<img title='{}' src='{}/{}' width='16' />".format(
            title, portal_url, icon_big or icon)
        logger.debug("Generated Icon Tag for {}: {}".format(
            api.get_path(brain_or_object), html_tag))
        return html_tag
示例#25
0
    def make_catalog_query(self, context, field, value):
        """Create a catalog query for the field
        """

        # get the catalogs for the context
        catalogs = api.get_catalogs_for(context)
        # context not in any catalog?
        if not catalogs:
            logger.warn("UniqueFieldValidator: Context '{}' is not assigned"
                        "to any catalog!".format(repr(context)))
            return None

        # take the first catalog
        catalog = catalogs[0]

        # Check if the field accessor is indexed
        field_index = field.getName()
        accessor = field.getAccessor(context)
        if accessor:
            field_index = accessor.__name__

        # return if the field is not indexed
        if field_index not in catalog.indexes():
            return None

        # build a catalog query
        query = {
            "portal_type": api.get_portal_type(context),
            "path": {
                "query": api.get_parent_path(context),
                "depth": 1,
            }
        }
        query[field_index] = value
        logger.info("UniqueFieldValidator:Query={}".format(query))
        return query
示例#26
0
    def make_catalog_query(self, context, field, value):
        """Create a catalog query for the field
        """

        # get the catalogs for the context
        catalogs = api.get_catalogs_for(context)
        # context not in any catalog?
        if not catalogs:
            logger.warn("UniqueFieldValidator: Context '{}' is not assigned"
                        "to any catalog!".format(repr(context)))
            return None

        # take the first catalog
        catalog = catalogs[0]

        # Check if the field accessor is indexed
        field_index = field.getName()
        accessor = field.getAccessor(context)
        if accessor:
            field_index = accessor.__name__

        # return if the field is not indexed
        if field_index not in catalog.indexes():
            return None

        # build a catalog query
        query = {
            "portal_type": api.get_portal_type(context),
            "path": {
                "query": api.get_parent_path(context),
                "depth": 1,
            }
        }
        query[field_index] = value
        logger.info("UniqueFieldValidator:Query={}".format(query))
        return query
示例#27
0
def get_portal_type(brain_or_object):
    """Proxy to senaite.api.get_portal_type
    """
    return api.get_portal_type(brain_or_object)
示例#28
0
def get_portal_type(brain_or_object):
    """Proxy to bika.lims.api.get_portal_type
    """
    return api.get_portal_type(brain_or_object)
示例#29
0
def get_variables(context, **kw):
    """Prepares a dictionary of key->value pairs usable for ID formatting
    """

    # allow portal_type override
    portal_type = kw.get("portal_type") or api.get_portal_type(context)

    # The variables map hold the values that might get into the construced id
    variables = {
        'context': context,
        'id': api.get_id(context),
        'portal_type': portal_type,
        'year': get_current_year(),
        'parent': api.get_parent(context),
        'seq': 0,
    }

    # Augment the variables map depending on the portal type
    if portal_type == "AnalysisRequest":
        variables.update({
            'sampleId': context.getSample().getId(),
            'sample': context.getSample(),
        })

    elif portal_type == "SamplePartition":
        variables.update({
            'sampleId': context.aq_parent.getId(),
            'sample': context.aq_parent,
        })

    elif portal_type == "Sample":
        # get the prefix of the assigned sample type
        sample_id = context.getId()
        sample_type = context.getSampleType()
        sampletype_prefix = sample_type.getPrefix()

        date_now = DateTime()
        sampling_date = context.getSamplingDate()
        date_sampled = context.getDateSampled()

        # Try to get the date sampled and sampling date
        if sampling_date:
            samplingDate = DT2dt(sampling_date)
        else:
            # No Sample Date?
            logger.error("Sample {} has no sample date set".format(sample_id))
            # fall back to current date
            samplingDate = DT2dt(date_now)

        if date_sampled:
            dateSampled = DT2dt(date_sampled)
        else:
            # No Sample Date?
            logger.error("Sample {} has no sample date set".format(sample_id))
            dateSampled = DT2dt(date_now)

        variables.update({
            'clientId': context.aq_parent.getClientID(),
            'dateSampled': dateSampled,
            'samplingDate': samplingDate,
            'sampleType': sampletype_prefix,
        })

    return variables
示例#30
0
 def supports_multiplex(self, obj):
     """Returns whether the obj supports multiplex
     """
     return api.get_portal_type(obj) in self.get_multiplexed_types()
示例#31
0
 def get_portal_type(self, obj):
     """Returns the portal type of the object
     """
     if not api.is_object(obj):
         return None
     return api.get_portal_type(obj)
示例#32
0
def get_portal_type(brain_or_object):
    """Proxy to bika.lims.api.get_portal_type
    """
    return api.get_portal_type(brain_or_object)
示例#33
0
 def get_parent_objects(self, context):
     """Return all objects of the same type from the parent object
     """
     parent_object = api.get_parent(context)
     portal_type = api.get_portal_type(context)
     return parent_object.objectValues(portal_type)
示例#34
0
def get_variables(context, **kw):
    """Prepares a dictionary of key->value pairs usable for ID formatting
    """

    # allow portal_type override
    portal_type = kw.get("portal_type") or api.get_portal_type(context)

    # The variables map hold the values that might get into the constructed id
    variables = {
        'context': context,
        'id': api.get_id(context),
        'portal_type': portal_type,
        'year': get_current_year(),
        'parent': api.get_parent(context),
        'seq': 0,
    }

    # Augment the variables map depending on the portal type
    if portal_type == "AnalysisRequest":
        variables.update({
            'sampleId': context.getSample().getId(),
            'sample': context.getSample(),
        })

    elif portal_type == "SamplePartition":
        variables.update({
            'sampleId': context.aq_parent.getId(),
            'sample': context.aq_parent,
        })

    elif portal_type == "Sample":
        # get the prefix of the assigned sample type
        sample_id = context.getId()
        sample_type = context.getSampleType()
        sampletype_prefix = sample_type.getPrefix()

        date_now = DateTime()
        sampling_date = context.getSamplingDate()
        date_sampled = context.getDateSampled()

        # Try to get the date sampled and sampling date
        if sampling_date:
            samplingDate = DT2dt(sampling_date)
        else:
            # No Sample Date?
            logger.error("Sample {} has no sample date set".format(sample_id))
            # fall back to current date
            samplingDate = DT2dt(date_now)

        if date_sampled:
            dateSampled = DT2dt(date_sampled)
        else:
            # No Sample Date?
            logger.error("Sample {} has no sample date set".format(sample_id))
            dateSampled = DT2dt(date_now)

        variables.update({
            'clientId': context.aq_parent.getClientID(),
            'dateSampled': dateSampled,
            'samplingDate': samplingDate,
            'sampleType': sampletype_prefix,
        })

    return variables
示例#35
0
 def get_parent_objects(self, context):
     """Return all objects of the same type from the parent object
     """
     parent_object = api.get_parent(context)
     portal_type = api.get_portal_type(context)
     return parent_object.objectValues(portal_type)
示例#36
0
    def get_raw_query(self):
        """Returns the raw query to use for current search, based on the
        base query + update query
        """
        query = super(ClientAwareReferenceWidgetAdapter, self).get_raw_query()
        logger.info("===============================================")
        logger.info("Custom client-aware reference widget vocabulary")
        logger.info(repr(query))

        # Get the portal types from the query
        portal_type = self.get_portal_type(query)
        if not portal_type:
            # Don't know the type we are searching for, do nothing
            return query

        if portal_type not in self.client_aware_types:
            # The portal type is not client aware, do nothing
            return query

        # Try to resolve the client from the query
        client = self.get_client_from_query(query, purge=True)

        # Resolve the client from the context chain
        client = get_client_from_chain(self.context) or client

        # Resolve the criteria for filtering
        criteria = {}

        if portal_type in self.widely_shared_types:

            # The portal type can be shared widely (e.g. Sample Type)
            criteria = self.resolve_query(portal_type, client, True)

        elif portal_type in self.internally_shared_types:

            # The portal type can be shared among internal clients (e.g Batch)
            criteria = resolve_query_for_shareable(portal_type, client)

        elif portal_type == "Client":

            # Special case, when the item to look for is a Client
            context_portal_type = api.get_portal_type(self.context)
            if context_portal_type in self.internally_shared_types:

                # Current context can be shared internally (e.g. Batch)
                if client:
                    # Display only the current Client in searches
                    criteria = self.resolve_query(portal_type, client, False)

                else:
                    # Display all internal clients
                    internal_clients = api.get_portal().internal_clients
                    criteria = {
                        "path": {
                            "query": api.get_path(internal_clients),
                            "depth": 1
                        }
                    }

            else:
                # Display current client only (if client != None) or all them
                criteria = self.resolve_query(portal_type, client, False)

        elif client:
            # Portal type is not shareable in any way (e.g Contact)
            criteria = self.resolve_query(portal_type, client, False)

        query.update(criteria)
        logger.info(repr(query))
        logger.info("===============================================")
        return query