Exemplo n.º 1
0
def prepublish(obj):
    """Returns True if 'prepublish' transition can be applied to the Analysis
    Request passed in.
    Returns true if the Analysis Request is active (not in a cancelled/inactive
    state), the 'publish' transition cannot be performed yet, and at least one
    of its analysis is under to_be_verified state or has been already verified.
    As per default DC workflow definition in bika_ar_workflow, note that
    prepublish does not transitions the Analysis Request to any other state
    different from the actual one, neither its children. This 'fake' transition
    is only used for the prepublish action to be displayed when the Analysis
    Request' status is other than verified, so the labman can generate a
    provisional report, also if results are not yet definitive.
    :returns: true or false
    """
    if not isBasicTransitionAllowed(obj):
        return False

    if isTransitionAllowed(obj, 'publish'):
        return False

    analyses = obj.getAnalyses(full_objects=True)
    for an in analyses:
        # If the analysis is not active, omit
        if not isActive(an):
            continue

        # Check if the current state is 'verified'
        status = getCurrentState(an)
        if status in ['verified', 'to_be_verified']:
            return True

    # This analysis request has no single result ready to be verified or
    # verified yet. In this situation, it doesn't make sense to publish a
    # provisional results reports without a single result to display
    return False
Exemplo n.º 2
0
def prepublish(obj):
    """Returns True if 'prepublish' transition can be applied to the Analysis
    Request passed in.
    Returns true if the Analysis Request is active (not in a cancelled/inactive
    state), the 'publish' transition cannot be performed yet, and at least one
    of its analysis is under to_be_verified state or has been already verified.
    As per default DC workflow definition in bika_ar_workflow, note that
    prepublish does not transitions the Analysis Request to any other state
    different from the actual one, neither its children. This 'fake' transition
    is only used for the prepublish action to be displayed when the Analysis
    Request' status is other than verified, so the labman can generate a
    provisional report, also if results are not yet definitive.
    :returns: true or false
    """
    if not isBasicTransitionAllowed(obj):
        return False

    if isTransitionAllowed(obj, 'publish'):
        return False

    analyses = obj.getAnalyses(full_objects=True)
    for an in analyses:
        # If the analysis is not active, omit
        if not isActive(an):
            continue

        # Check if the current state is 'verified'
        status = getCurrentState(an)
        if status in ['verified', 'to_be_verified']:
            return True

    # This analysis request has no single result ready to be verified or
    # verified yet. In this situation, it doesn't make sense to publish a
    # provisional results reports without a single result to display
    return False
Exemplo n.º 3
0
 def isItemAllowed(self, obj):
     """
     Only valid reference samples (neither expired nor disposed) are allowed
     """
     if not obj.isValid() or not isActive(obj):
         return False
     return super(ReferenceSamplesView, self).isItemAllowed(obj)
Exemplo n.º 4
0
 def isItemAllowed(self, obj):
     """
     Only valid reference samples (neither expired nor disposed) are allowed
     """
     if not obj.isValid() or not isActive(obj):
         return False
     return super(ReferenceSamplesView, self).isItemAllowed(obj)
Exemplo n.º 5
0
def fix_service_status_inconsistences():
    catalog = api.get_tool('bika_setup_catalog')
    brains = catalog(portal_type='AnalysisService')
    for brain in brains:
        obj = api.get_object(brain)
        if not isActive(obj):
            continue

        # If this service is active, then all the services this service
        # depends on must be active too, as well as the calculation
        calculation = obj.getCalculation()
        if not calculation:
            continue

        dependencies = calculation.getDependentServices()
        for dependency in dependencies:
            dependency = api.get_object(dependency)
            if not isActive(dependency):
                _change_inactive_state(dependency, 'active')
Exemplo n.º 6
0
def fix_service_status_inconsistences():
    catalog = api.get_tool('bika_setup_catalog')
    brains = catalog(portal_type='AnalysisService')
    for brain in brains:
        obj = api.get_object(brain)
        if not isActive(obj):
            continue

        # If this service is active, then all the services this service
        # depends on must be active too, as well as the calculation
        calculation = obj.getCalculation()
        if not calculation:
            continue

        dependencies = calculation.getDependentServices()
        for dependency in dependencies:
            dependency = api.get_object(dependency)
            if not isActive(dependency):
                _change_inactive_state(dependency, 'active')
Exemplo n.º 7
0
def fix_service_profile_template_inconsistences():
    catalog = api.get_tool('bika_setup_catalog')
    brains = catalog(portal_type='AnalysisService')
    for brain in brains:
        obj = api.get_object(brain)
        if isActive(obj):
            continue

        # If this service is inactive, be sure is not used neither in Profiles
        # nor in AR Templates
        obj.after_deactivate_transition_event()
Exemplo n.º 8
0
def fix_service_profile_template_inconsistences():
    catalog = api.get_tool('bika_setup_catalog')
    brains = catalog(portal_type='AnalysisService')
    for brain in brains:
        obj = api.get_object(brain)
        if isActive(obj):
            continue

        # If this service is inactive, be sure is not used neither in Profiles
        # nor in AR Templates
        obj.after_deactivate_transition_event()
Exemplo n.º 9
0
def verify(obj):
    """Returns True if 'verify' transition can be applied to the Analysis
    Request passed in. This is, returns true if all the analyses that contains
    have already been verified. Those analyses that are in an inactive state
    (cancelled, inactive) are dismissed, but at least one analysis must be in
    an active state (and verified), otherwise always return False. If the
    Analysis Request is in inactive state (cancelled/inactive), returns False
    Note this guard depends entirely on the current status of the children
    :returns: true or false
    """
    if not isBasicTransitionAllowed(obj):
        return False

    analyses = obj.getAnalyses(full_objects=True)
    invalid = 0
    for an in analyses:
        # The analysis has already been verified?
        if wasTransitionPerformed(an, 'verify'):
            continue

        # Maybe the analysis is in an 'inactive' state?
        if not isActive(an):
            invalid += 1
            continue

        # Maybe the analysis has been rejected or retracted?
        dettached = ['rejected', 'retracted', 'attachments_due']
        status = getCurrentState(an)
        if status in dettached:
            invalid += 1
            continue

        # At this point we can assume this analysis is an a valid state and
        # could potentially be verified, but the Analysis Request can only be
        # verified if all the analyses have been transitioned to verified
        return False

    # Be sure that at least there is one analysis in an active state, it
    # doesn't make sense to verify an Analysis Request if all the analyses that
    # contains are rejected or cancelled!
    return len(analyses) - invalid > 0
Exemplo n.º 10
0
def verify(obj):
    """Returns True if 'verify' transition can be applied to the Analysis
    Request passed in. This is, returns true if all the analyses that contains
    have already been verified. Those analyses that are in an inactive state
    (cancelled, inactive) are dismissed, but at least one analysis must be in
    an active state (and verified), otherwise always return False. If the
    Analysis Request is in inactive state (cancelled/inactive), returns False
    Note this guard depends entirely on the current status of the children
    :returns: true or false
    """
    if not isBasicTransitionAllowed(obj):
        return False

    analyses = obj.getAnalyses(full_objects=True)
    invalid = 0
    for an in analyses:
        # The analysis has already been verified?
        if wasTransitionPerformed(an, 'verify'):
            continue

        # Maybe the analysis is in an 'inactive' state?
        if not isActive(an):
            invalid += 1
            continue

        # Maybe the analysis has been rejected or retracted?
        dettached = ['rejected', 'retracted', 'attachments_due']
        status = getCurrentState(an)
        if status in dettached:
            invalid += 1
            continue

        # At this point we can assume this analysis is an a valid state and
        # could potentially be verified, but the Analysis Request can only be
        # verified if all the analyses have been transitioned to verified
        return False

    # Be sure that at least there is one analysis in an active state, it
    # doesn't make sense to verify an Analysis Request if all the analyses that
    # contains are rejected or cancelled!
    return len(analyses) - invalid > 0
Exemplo n.º 11
0
def guard_submit(context):
    if not IAnalysisRequest.providedBy(context):
        # Note that this guard is only used for bika_ar_workflow!
        return True

    logger.info("*** Custom Guard: submit **")
    if not isBasicTransitionAllowed(context):
        return False

    invalid = 0
    analyses = context.getAnalyses()
    for an in analyses:
        if an.review_state == 'to_be_verified':
            continue

        # The analysis has already been verified?
        an = api.get_object(an)
        if wasTransitionPerformed(an, 'submit'):
            continue

        # Maybe the analysis is in an 'inactive' state?
        if not isActive(an):
            invalid += 1
            continue

        # Maybe the analysis has been rejected or retracted?
        dettached = ['rejected', 'retracted', 'attachments_due']
        status = getCurrentState(an)
        if status in dettached:
            invalid += 1
            continue

        # At this point we can assume this analysis is an a valid state and
        # the AR could potentially be submitted, but the Analysis Request can
        # only be submitted if all the analyses have been submitted already
        return False

    # Be sure that at least there is one analysis in an active state, it
    # doesn't make sense to submit an Analysis Request if all the analyses that
    # contains are rejected or cancelled!
    return len(analyses) - invalid > 0
Exemplo n.º 12
0
def _children_are_ready(obj, transition_id, dettached_states=None):
    """Returns true if the children of the object passed in (worksheet) have
    been all transitioned in accordance with the 'transition_id' passed in. If
    dettached_states is provided, children with those states are dismissed, so
    they will not be taken into account in the evaluation. Nevertheless, at
    least one child with for which the transition_id performed is required for
    this function to return true (if all children are in dettached states, it
    always return False).
    """
    analyses = obj.getAnalyses()
    invalid = 0
    for an in analyses:
        # The analysis has already been transitioned?
        if wasTransitionPerformed(an, transition_id):
            continue

        # Maybe the analysis is in an 'inactive' state?
        if not isActive(an):
            invalid += 1
            continue

        # Maybe the analysis is in a dettached state?
        if dettached_states:
            status = getCurrentState(an)
            if status in dettached_states:
                invalid += 1
                continue

        # At this point we can assume this analysis is an a valid state and
        # could potentially be transitioned, but the Worksheet can only be
        # transitioned if all the analyses have been transitioned previously
        return False

    # Be sure that at least there is one analysis in an active state, it
    # doesn't make sense to transition a Worksheet if all the analyses that
    # contains are not valid
    return len(analyses) - invalid > 0
Exemplo n.º 13
0
    def __init__(self, context, request, **kwargs):
        BikaListingView.__init__(
            self,
            context,
            request,
            show_categories=context.bika_setup.getCategoriseAnalysisServices(),
            expand_all_categories=True)

        # prepare the content filter of this listing
        self.contentFilter = dict(kwargs)
        self.contentFilter.update({
            "portal_type": "Analysis",
            "sort_on": "sortable_title",
            "sort_order": "ascending",
        })

        # set the listing view config
        self.catalog = CATALOG_ANALYSIS_LISTING
        self.sort_order = 'ascending'
        self.context_actions = {}
        self.show_sort_column = False
        self.show_select_row = False
        self.show_select_column = False
        self.show_column_toggles = False
        self.pagesize = 999999
        self.form_id = 'analyses_form'
        self.context_active = isActive(context)
        self.interim_fields = {}
        self.interim_columns = {}
        self.specs = {}
        self.bsc = getToolByName(context, 'bika_setup_catalog')
        self.portal = getToolByName(context, 'portal_url').getPortalObject()
        self.portal_url = self.portal.absolute_url()
        self.rc = getToolByName(context, REFERENCE_CATALOG)
        self.dmk = context.bika_setup.getResultsDecimalMark()
        self.scinot = context.bika_setup.getScientificNotationResults()
        self.categories = []
        request.set('disable_plone.rightcolumn', 1)

        # each editable item needs it's own allow_edit
        # which is a list of field names.
        self.allow_edit = False

        self.columns = {
            # Although 'created' column is not displayed in the list (see
            # review_states to check the columns that will be rendered), this
            # column is needed to sort the list by create date
            'created': {
                'title': _('Date Created'),
                'toggle': False},
            'Service': {
                'title': _('Analysis'),
                'attr': 'Title',
                'index': 'sortable_title',
                'sortable': False},
            'Partition': {
                'title': _("Partition"),
                'attr': 'getSamplePartitionID',
                'sortable': False},
            'Method': {
                'title': _('Method'),
                'sortable': False,
                'toggle': True},
            'Instrument': {
                'title': _('Instrument'),
                'sortable': False,
                'toggle': True},
            'Analyst': {
                'title': _('Analyst'),
                'sortable': False,
                'toggle': True},
            'state_title': {
                'title': _('Status'),
                'sortable': False},
            'DetectionLimit': {
                'title': _('DL'),
                'sortable': False,
                'toggle': False},
            'Result': {
                'title': _('Result'),
                'input_width': '6',
                'input_class': 'ajax_calculate numeric',
                'sortable': False},
            'Specification': {
                'title': _('Specification'),
                'sortable': False},
            'Uncertainty': {
                'title': _('+-'),
                'sortable': False},
            'retested': {
                'title': "<img title='%s' "
                         "src='%s/++resource++bika.lims.images/retested.png"
                         "'/>" % \
                         (t(_('Retested')), self.portal_url),
                'type': 'boolean',
                'sortable': False},
            'Attachments': {
                'title': _('Attachments'),
                'sortable': False},
            'CaptureDate': {
                'title': _('Captured'),
                'index': 'getResultCaptureDate',
                'sortable': False},
            'DueDate': {
                'title': _('Due Date'),
                'index': 'getDueDate',
                'sortable': False},
            'Hidden': {
                'title': _('Hidden'),
                'toggle': True,
                'sortable': False,
                'input_class': 'autosave',
                'type': 'boolean'},
        }

        self.review_states = [
            {
                'id':
                'default',
                'title':
                _('All'),
                'contentFilter': {},
                'columns': [
                    'Service', 'Partition', 'DetectionLimit', 'Result',
                    'Specification', 'Method', 'Instrument', 'Analyst',
                    'Uncertainty', 'CaptureDate', 'DueDate', 'state_title',
                    'Hidden'
                ]
            },
        ]
        if not context.bika_setup.getShowPartitions():
            self.review_states[0]['columns'].remove('Partition')

        # This is used to cache analysis keywords with Point of Capture to
        # reduce the number objects that need to be woken up
        # Is managed by `is_analysis_edition_allowed` function
        self._keywords_poc_map = dict()

        # This is used to display method and instrument columns if there is at
        # least one analysis to be rendered that allows the assignment of method
        # and/or instrument
        self.show_methodinstr_columns = False
Exemplo n.º 14
0
    def __init__(self, context, request, **kwargs):
        super(AnalysesView, self).__init__(context, request, **kwargs)

        # prepare the content filter of this listing
        self.contentFilter = dict(kwargs)
        self.contentFilter.update({
            "portal_type": "Analysis",
            "sort_on": "sortable_title",
            "sort_order": "ascending",
        })

        # set the listing view config
        self.catalog = CATALOG_ANALYSIS_LISTING
        self.sort_order = "ascending"
        self.context_actions = {}

        self.show_select_row = False
        self.show_select_column = False
        self.show_column_toggles = False
        self.pagesize = 9999999
        self.form_id = "analyses_form"
        self.context_active = isActive(context)
        self.interim_fields = {}
        self.interim_columns = OrderedDict()
        self.specs = {}
        self.bsc = api.get_tool("bika_setup_catalog")
        self.portal = api.get_portal()
        self.portal_url = api.get_url(self.portal)
        self.rc = api.get_tool(REFERENCE_CATALOG)
        self.dmk = context.bika_setup.getResultsDecimalMark()
        self.scinot = context.bika_setup.getScientificNotationResults()
        self.categories = []

        # each editable item needs it's own allow_edit
        # which is a list of field names.
        self.allow_edit = False

        self.columns = OrderedDict((
            # Although 'created' column is not displayed in the list (see
            # review_states to check the columns that will be rendered), this
            # column is needed to sort the list by create date
            ("created", {
                "title": _("Date Created"),
                "toggle": False}),
            ("Service", {
                "title": _("Analysis"),
                "attr": "Title",
                "index": "sortable_title",
                "sortable": False}),
            ("Partition", {
                "title": _("Partition"),
                "attr": "getSamplePartitionID",
                "sortable": False}),
            ("Method", {
                "title": _("Method"),
                "sortable": False,
                "ajax": True,
                "toggle": True}),
            ("Instrument", {
                "title": _("Instrument"),
                "ajax": True,
                "sortable": False,
                "toggle": True}),
            ("Analyst", {
                "title": _("Analyst"),
                "sortable": False,
                "ajax": True,
                "toggle": True}),
            ("state_title", {
                "title": _("Status"),
                "sortable": False}),
            ("DetectionLimit", {
                "title": _("DL"),
                "sortable": False,
                "toggle": False}),
            ("Result", {
                "title": _("Result"),
                "input_width": "6",
                "input_class": "ajax_calculate numeric",
                "ajax": True,
                "sortable": False}),
            ("Specification", {
                "title": _("Specification"),
                "sortable": False}),
            ("Uncertainty", {
                "title": _("+-"),
                "sortable": False}),
            ("retested", {
                "title": _("Retested"),
                "type": "boolean",
                "sortable": False}),
            ("Attachments", {
                "title": _("Attachments"),
                "sortable": False}),
            ("CaptureDate", {
                "title": _("Captured"),
                "index": "getResultCaptureDate",
                "sortable": False}),
            ("DueDate", {
                "title": _("Due Date"),
                "index": "getDueDate",
                "sortable": False}),
            ("Hidden", {
                "title": _("Hidden"),
                "toggle": True,
                "sortable": False,
                "ajax": True,
                "type": "boolean"}),
        ))

        # Inject Remarks column for listing
        if self.analysis_remarks_enabled():
            self.columns["Remarks"] = {
                "title": "Remarks",
                "toggle": False,
                "sortable": False,
                "type": "remarks",
                "ajax": True,
            }

        self.review_states = [
            {
                "id": "default",
                "title": _("All"),
                "contentFilter": {},
                "columns": self.columns.keys()
             },
        ]

        # This is used to display method and instrument columns if there is at
        # least one analysis to be rendered that allows the assignment of
        # method and/or instrument
        self.show_methodinstr_columns = False