Beispiel #1
0
class PricelistEmailView(BrowserView):
    form_template = ViewPageTemplateFile("templates/pricelist_email_form.pt")
    template = ViewPageTemplateFile("templates/pricelist_email.pt")
    lineitems_pt = ViewPageTemplateFile("templates/pricelist_content.pt")

    def __call__(self):
        if 'submitted' in self.request:
            self.items = self.context.objectValues()
            self.pricelist_content = self.lineitems_pt()

            portal = context.portal_url.getPortalObject()
            lab = context.bika_labinfo.laboratory
            request = context.REQUEST

            ar_query_results = portal.portal_mailtemplates.getTemplate(
                'bika', request.mail_template)

            headers = {}
            headers['Date'] = DateTime().rfc822()
            from_addr = headers['From'] = formataddr(
                (encode_header(lab.Title()), lab.getEmailAddress())
            )

            if 'Contact_email_address' in request:
                contact_address = request.Contact_email_address
                msg = 'portal_status_message=Pricelist sent to %s' % (
                    contact_address)
            else:
                contact = context.reference_catalog.lookupObject(request.Contact_uid)
                contact_address = formataddr(
                    (encode_header(contact.getFullname()),
                      contact.getEmailAddress())
                )
                msg = 'portal_status_message=Pricelist sent to %s at %s' % (
                    contact.Title(), contact.getEmailAddress())

            to_addrs = []
            to_addr = headers['To'] = contact_address
            to_addrs.append(to_addr)
            # send copy to lab
            to_addrs.append(from_addr)

            to_addrs = tuple(to_addrs)
            info = {'request': request,
                    'pricelist': context,
                    'portal': portal}

            message = pmt.createMessage(
                'bika', request.mail_template, info, headers, text_format='html')
            sendmail(portal, from_addr, to_addrs, message)

            request.RESPONSE.redirect('%s?%s' % (context.absolute_url(), msg))

            return self.template()
        else:
            return self.form_template()

    def getPreferredCurrencyAbreviation(self):
        return self.context.bika_setup.getCurrency()
Beispiel #2
0
class PricelistPrintView(BrowserView):
    template = ViewPageTemplateFile("templates/pricelist_print.pt")
    lineitems_pt = ViewPageTemplateFile("templates/pricelist_content.pt")

    def __call__(self):
        self.items = self.context.objectValues()
        self.pricelist_content = self.lineitems_pt()
        return self.template()

    def getPreferredCurrencyAbreviation(self):
        return self.context.bika_setup.getCurrency()
Beispiel #3
0
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
Beispiel #4
0
class InvoicePrintView(InvoiceView):

    template = ViewPageTemplateFile(
        "templates/analysisrequest_invoice_print.pt")

    def __call__(self):
        return InvoiceView.__call__(self)
class ARResultsInterpretationView(BrowserView):
    """ Renders the view for ResultsInterpration per Department
    """
    template = ViewPageTemplateFile(
        "templates/analysisrequest_results_interpretation.pt")

    def __init__(self, context, request, **kwargs):
        super(ARResultsInterpretationView, self).__init__(context, request)
        self.context = context

    def __call__(self):
        wf = getToolByName(self.context, 'portal_workflow')
        mtool = getToolByName(self.context, 'portal_membership')
        self.allow_edit = mtool.checkPermission('Modify portal content',
                                                self.context)
        return self.template()

    def getText(self, department, mode='raw'):
        """ Returns the text saved for the selected department.
        """
        row = self.context.getResultsInterpretationByDepartment(department)
        rt = RichTextValue(row.get('richtext', ''), 'text/plain', 'text/html')
        if mode == 'output':
            return rt.output
        else:
            return rt.raw
Beispiel #6
0
class PathBarViewlet(ViewletBase):
    index = ViewPageTemplateFile('templates/path_bar.pt')

    def update(self):
        super(PathBarViewlet, self).update()

        self.is_rtl = self.portal_state.is_rtl()

        breadcrumbs_view = getMultiAdapter((self.context, self.request),
                                           name='breadcrumbs_view')
        self.breadcrumbs = breadcrumbs_view.breadcrumbs()
Beispiel #7
0
class AnalysisRequestsView(_ARV, _ARAV):
    template = ViewPageTemplateFile(
        "../analysisrequest/templates/analysisrequests.pt")
    ar_add = ViewPageTemplateFile("../analysisrequest/templates/ar_add.pt")
    implements(IViewView)

    def __init__(self, context, request):
        super(AnalysisRequestsView, self).__init__(context, request)

    def contentsMethod(self, contentFilter):
        #bc = getToolByName(self.context, 'bika_catalog')
        #import pdb;pdb.set_trace()
        #if 'BatchUID' not in contentFilter.keys():
        #    contentFilter['BatchUID'] = self.context.UID()
        #return bc(contentFilter)
        return self.context.getBackReferences("AnalysisRequestBatch")

    def __call__(self):
        self.context_actions = {}
        mtool = getToolByName(self.context, 'portal_membership')
        if mtool.checkPermission(AddAnalysisRequest, self.portal):
            self.context_actions[self.context.translate(_('Add new'))] = {
                'url': self.context.absolute_url() + \
                    "/portal_factory/"
                    "AnalysisRequest/Request new analyses/ar_add?ar_count=1",
                'icon': '++resource++bika.lims.images/add.png'}

        return super(AnalysisRequestsView, self).__call__()

    def getMemberDiscountApplies(self):
        client = self.context.getClient()
        return client and client.getMemberDiscountApplies() or False

    def getRestrictedCategories(self):
        client = self.context.getClient()
        return client and client.getRestrictedCategories() or []

    def getDefaultCategories(self):
        client = self.context.getClient()
        return client and client.getDefaultCategories() or []
Beispiel #8
0
class View(BrowserView):

    template = ViewPageTemplateFile('templates/supplyorder_view.pt')
    title = _('Supply Order')

    def __call__(self):
        context = self.context
        portal = self.portal
        setup = portal.bika_setup
        # Disable the add new menu item
        context.setConstrainTypesMode(1)
        context.setLocallyAllowedTypes(())
        # Collect general data
        self.orderDate = self.ulocalized_time(context.getOrderDate())
        self.contact = context.getContact()
        self.contact = self.contact.getFullname() if self.contact else ''
        self.subtotal = '%.2f' % context.getSubtotal()
        self.vat = '%.2f' % context.getVATAmount()
        self.total = '%.2f' % context.getTotal()
        # Set the title
        self.title = context.Title()
        # Collect order item data
        items = context.supplyorder_lineitems

        self.items = []
        for item in items:
            prodid = item['Product']
            product = setup.bika_labproducts[prodid]
            price = float(item['Price'])
            vat = float(item['VAT'])
            qty = float(item['Quantity'])
            self.items.append({
                'title': product.Title(),
                'description': product.Description(),
                'volume': product.getVolume(),
                'unit': product.getUnit(),
                'price': price,
                'vat': '%s%%' % vat,
                'quantity': qty,
                'totalprice': '%.2f' % (price * qty)
            })
        self.items = sorted(self.items, key=itemgetter('title'))
        # Render the template
        return self.template()

    def getPreferredCurrencyAbreviation(self):
        return self.context.bika_setup.getCurrency()
Beispiel #9
0
class InstrumentReferenceAnalysesViewView(BrowserView):
    """ View of Reference Analyses linked to the Instrument.
        Only shows the Reference Analyses (Control and Blanks), the rest
        of regular and duplicate analyses linked to this instrument are
        not displayed.
        The Reference Analyses from an Instrument can be from Worksheets
        (QC analysis performed regularly for any Analysis Request) or
        attached directly to the instrument, without being linked to
        any Worksheet). In this case, the Reference Analyses are created
        automatically by the instrument import tool.
    """

    implements(IViewView)
    template = ViewPageTemplateFile(
        "templates/instrument_referenceanalyses.pt")

    def __init__(self, context, request):
        super(InstrumentReferenceAnalysesViewView,
              self).__init__(context, request)
        self.icon = self.portal_url + "/++resource++bika.lims.images/referencesample_big.png"
        self.title = self.context.translate(_("Internal Calibration Tests"))
        self.description = ""
        self._analysesview = None

    def __call__(self):
        return self.template()

    def get_analyses_table(self):
        """ Returns the table of Reference Analyses
        """
        return self.get_analyses_view().contents_table()

    def get_analyses_view(self):
        if not self._analysesview:
            # Creates the Analyses View if not exists yet
            self._analysesview = InstrumentReferenceAnalysesView(
                self.context, self.request, show_categories=False)
            self._analysesview.allow_edit = False
            self._analysesview.show_select_column = False
            self._analysesview.show_workflow_action_buttons = False
            self._analysesview.form_id = "%s_qcanalyses" % self.context.UID()
            self._analysesview.review_states[0]['transitions'] = [{}]

        return self._analysesview

    def get_analyses_json(self):
        return self.get_analyses_view().get_analyses_json()
Beispiel #10
0
class DocumentActionsViewlet(ViewletBase):
    """Overload the default to print pretty icons
    """

    index = ViewPageTemplateFile("templates/document_actions.pt")

    def render(self):
        portal_factory = getToolByName(self.context, 'portal_factory')
        if portal_factory.isTemporary(self.context):
            return self.index()
        self.actions = []
        portal_actions = getToolByName(self.context, 'portal_actions')
        actions = portal_actions.listFilteredActionsFor(self.context)
        if 'document_actions' in actions:
            for action in actions['document_actions']:
                self.actions.append(action)
        return self.index()
Beispiel #11
0
class AdministrationView(BrowserView):
    """ Administration View form
    """
    implements(IViewView)
    template = ViewPageTemplateFile("templates/administration.pt")

    def __call__(self):
        self.selection_macros = SelectionMacrosView(self.context, self.request)
        self.icon = self.portal_url + "/++resource++bika.lims.images/report_big.png"

        self.additional_reports = []
        adapters = getAdapters((self.context, ), IAdministrationReport)
        for name, adapter in adapters:
            report_dict = adapter(self.context, self.request)
            report_dict['id'] = name
            self.additional_reports.append(report_dict)

        return self.template()
Beispiel #12
0
class ImportView(BrowserView):
    """
    """
    implements(IViewView)
    template = ViewPageTemplateFile("import.pt")

    def __init__(self, context, request):
        super(ImportView, self).__init__(context, request)

        self.icon = ""
        self.title = self.context.translate(_("Import"))
        self.description = self.context.translate(_("Select a data interface"))

        request.set('disable_border', 1)

    def getDataInterfaces(self):
        return getDataInterfaces(self.context)

    def getSetupDatas(self):
        datasets = []
        adapters = getAdapters((self.context, ), ISetupDataSetList)
        for name, adapter in adapters:
            datasets.extend(adapter())
        return datasets

    def getProjectName(self):
        adapters = getAdapters((self.context, ), ISetupDataSetList)
        productnames = [name for name, adapter in adapters]
        if len(productnames) == 1:
            productnames[0] = 'bika.lims'
        return productnames[len(productnames) - 1]

    def __call__(self):
        if 'submitted' in self.request:
            if 'setupfile' in self.request.form or \
               'setupexisting' in self.request.form:
                lsd = LoadSetupData(self.context, self.request)
                return lsd()
            else:
                exim = instruments.getExim(self.request['exim'])
                return exim.Import(self.context, self.request)
        else:
            return self.template()
Beispiel #13
0
class ProductivityView(BrowserView):
    """ Productivity View form
    """
    implements(IViewView)
    template = ViewPageTemplateFile("templates/productivity.pt")

    def __call__(self):
        self.selection_macros = SelectionMacrosView(self.context, self.request)
        self.icon = self.portal_url + "/++resource++bika.lims.images/report_big.png"
        self.getAnalysts = getUsers(self.context,
                                    ['Manager', 'LabManager', 'Analyst'])

        self.additional_reports = []
        adapters = getAdapters((self.context, ), IProductivityReport)
        for name, adapter in adapters:
            report_dict = adapter(self.context, self.request)
            report_dict['id'] = name
            self.additional_reports.append(report_dict)

        return self.template()
Beispiel #14
0
class QualityControlView(BrowserView):
    """ QC View form
    """
    implements(IViewView)
    template = ViewPageTemplateFile("templates/qualitycontrol.pt")

    def __call__(self):
        self.selection_macros = SelectionMacrosView(self.context, self.request)
        self.icon = self.portal_url + "/++resource++bika.lims.images/report_big.png"

        self.additional_reports = []
        adapters = getAdapters((self.context, ), IQualityControlReport)
        for name, adapter in adapters:
            report_dict = adapter(self.context, self.request)
            report_dict['id'] = name
            self.additional_reports.append(report_dict)

        return self.template()

    def isSamplePointHidden(self):
        return isAttributeHidden('AnalysisRequest', 'SamplePoint')
Beispiel #15
0
class ReferenceAnalysesViewView(BrowserView):
    """ View of Reference Analyses linked to the Reference Sample.
    """

    implements(IViewView)
    template = ViewPageTemplateFile("templates/referencesample_analyses.pt")

    def __init__(self, context, request):
        super(ReferenceAnalysesViewView, self).__init__(context, request)
        self.icon = self.portal_url + "/++resource++bika.lims.images/referencesample_big.png"
        self.title = self.context.translate(_("Reference Analyses"))
        self.description = ""
        self._analysesview = None

    def __call__(self):
        return self.template()

    def get_analyses_table(self):
        """ Returns the table of Reference Analyses
        """
        return self.get_analyses_view().contents_table()

    def get_analyses_view(self):
        if not self._analysesview:
            # Creates the Analyses View if not exists yet
            self._analysesview = ReferenceAnalysesView(self.context,
                                                       self.request)
            self._analysesview.allow_edit = False
            self._analysesview.show_select_column = False
            self._analysesview.show_workflow_action_buttons = False
            self._analysesview.form_id = "%s_qcanalyses" % self.context.UID()
            self._analysesview.review_states[0]['transitions'] = [{}]
        return self._analysesview

    def getReferenceSampleId(self):
        return self.context.id

    def get_analyses_json(self):
        return self.get_analyses_view().get_analyses_json()
Beispiel #16
0
 def getReportTemplate(self):
     """ Returns the html template for the current ar and moves to
         the next ar to be processed. Uses the selected template
         specified in the request ('template' parameter)
     """
     templates_dir = 'templates/reports'
     embedt = self.request.form.get('template', self._DEFAULT_TEMPLATE)
     if embedt.find(':') >= 0:
         prefix, template = embedt.split(':')
         templates_dir = queryResourceDirectory('reports', prefix).directory
         embedt = template
     embed = ViewPageTemplateFile(os.path.join(templates_dir, embedt))
     reptemplate = ""
     try:
         reptemplate = embed(self)
     except:
         tbex = traceback.format_exc()
         arid = self._ars[self._current_ar_index].id
         reptemplate = "<div class='error-report'>%s - %s '%s':<pre>%s</pre></div>" % (
             arid, _("Unable to load the template"), embedt, tbex)
     self._nextAnalysisRequest()
     return reptemplate
Beispiel #17
0
class AnalysisRequestResultsNotRequestedView(AnalysisRequestManageResultsView):
    implements(IViewView)
    template = ViewPageTemplateFile(
        "templates/analysisrequest_analyses_not_requested.pt")

    def __call__(self):
        ar = self.context
        workflow = getToolByName(ar, 'portal_workflow')

        # If is a retracted AR, show the link to child AR and show a warn msg
        if workflow.getInfoFor(ar, 'review_state') == 'invalid':
            childar = hasattr(ar, 'getChildAnalysisRequest') \
                        and ar.getChildAnalysisRequest() or None
            childid = childar and childar.getRequestID() or None
            message = _(
                'This Analysis Request has been withdrawn and is shown '
                'for trace-ability purposes only. Retest: ${retest_child_id}.',
                mapping={"retest_child_id": childid if childid else ''})
            self.context.plone_utils.addPortalMessage(message, 'warning')

        # If is an AR automatically generated due to a Retraction, show it's
        # parent AR information
        if hasattr(ar, 'getParentAnalysisRequest') \
            and ar.getParentAnalysisRequest():
            par = ar.getParentAnalysisRequest()
            message = _(
                'This Analysis Request has been generated automatically due to '
                'the retraction of the Analysis Request ${retracted_request_id}.',
                mapping={"retracted_request_id": par.getRequestID()})
            self.context.plone_utils.addPortalMessage(message, 'info')

        can_do = getSecurityManager().checkPermission(ResultsNotRequested, ar)
        if workflow.getInfoFor(ar, 'cancellation_state') == "cancelled":
            self.request.response.redirect(ar.absolute_url())
        elif not (can_do):
            self.request.response.redirect(ar.absolute_url())
        else:
            return self.template()
Beispiel #18
0
class ViewView(BrowserView):
    """ Reference Sample View
    """
    implements(IViewView)
    template = ViewPageTemplateFile("templates/referencesample_view.pt")

    def __init__(self, context, request):
        BrowserView.__init__(self, context, request)
        self.icon = self.portal_url + "/++resource++bika.lims.images/referencesample_big.png"

    def __call__(self):
        rc = getToolByName(self.context, REFERENCE_CATALOG)
        self.results = {}  # {category_title: listofdicts}
        for r in self.context.getReferenceResults():
            service = rc.lookupObject(r['uid'])
            cat = service.getCategoryTitle()
            if cat not in self.results:
                self.results[cat] = []
            r['service'] = service
            self.results[cat].append(r)
        self.categories = self.results.keys()
        self.categories.sort()
        return self.template()
Beispiel #19
0
 def renderWSTemplate(self):
     """ Returns the current worksheet rendered with the template
         specified in the request (param 'template').
         Moves the iterator to the next worksheet available.
     """
     templates_dir = self._TEMPLATES_DIR
     embedt = self.request.get('template', self._DEFAULT_TEMPLATE)
     if embedt.find(':') >= 0:
         prefix, embedt = embedt.split(':')
         templates_dir = queryResourceDirectory(self._TEMPLATES_ADDON_DIR,
                                                prefix).directory
     embed = ViewPageTemplateFile(os.path.join(templates_dir, embedt))
     reptemplate = ""
     try:
         reptemplate = embed(self)
     except:
         tbex = traceback.format_exc()
         wsid = self._worksheets[self._current_ws_index].id
         reptemplate = "<div class='error-print'>%s - %s '%s':<pre>%s</pre></div>" % (
             wsid, _("Unable to load the template"), embedt, tbex)
     if self._current_ws_index < len(self._worksheets):
         self._current_ws_index += 1
     return reptemplate
Beispiel #20
0
 def renderItem(self):
     """ Renders the next available sticker.
         Uses the template specified in the request ('template' parameter) by
         default. If no template defined in the request, uses the default
         template set by default in Bika Setup > Stickers.
         If the template specified doesn't exist, uses the default
         bika.lims' Code_128_1x48mm.pt template (was sticker_small.pt).
     """
     curritem = self.nextItem()
     templates_dir = 'templates/stickers'
     embedt = self.getSelectedTemplate()
     if embedt.find(':') >= 0:
         prefix, embedt = embedt.split(':')
         templates_dir = queryResourceDirectory('stickers',
                                                prefix).directory
     fullpath = os.path.join(templates_dir, embedt)
     try:
         embed = ViewPageTemplateFile(fullpath)
         return embed(self)
     except:
         tbex = traceback.format_exc()
         stickerid = curritem[2].id if curritem[2] else curritem[1].id
         return "<div class='error'>%s - %s '%s':<pre>%s</pre></div>" % \
                 (stickerid, _("Unable to load the template"), embedt, tbex)
Beispiel #21
0
class SubmitForm(BrowserView):
    """ Redirect to specific report
    """
    implements(IViewView)
    frame_template = ViewPageTemplateFile("templates/report_frame.pt")
    # default and errors use this template:
    template = ViewPageTemplateFile("templates/productivity.pt")

    def __call__(self):
        """Create and render selected report
        """

        # if there's an error, we return productivity.pt which requires these.
        self.selection_macros = SelectionMacrosView(self.context, self.request)
        self.additional_reports = []
        adapters = getAdapters((self.context, ), IProductivityReport)
        for name, adapter in adapters:
            report_dict = adapter(self.context, self.request)
            report_dict['id'] = name
            self.additional_reports.append(report_dict)

        report_id = self.request.get('report_id', '')
        if not report_id:
            message = _("No report specified in request")
            self.logger.error(message)
            self.context.plone_utils.addPortalMessage(message, 'error')
            return self.template()

        self.date = DateTime()
        username = self.context.portal_membership.getAuthenticatedMember().getUserName()
        self.reporter = self.user_fullname(username)
        self.reporter_email = self.user_email(username)

        # signature image
        self.reporter_signature = ""
        c = [x for x in self.bika_setup_catalog(portal_type='LabContact')
             if x.getObject().getUsername() == username]
        if c:
            sf = c[0].getObject().getSignature()
            if sf:
                self.reporter_signature = sf.absolute_url() + "/Signature"

        lab = self.context.bika_setup.laboratory
        self.laboratory = lab
        self.lab_title = lab.getName()
        self.lab_address = lab.getPrintAddress()
        self.lab_email = lab.getEmailAddress()
        self.lab_url = lab.getLabURL()

        client = logged_in_client(self.context)
        if client:
            clientuid = client.UID()
            self.client_title = client.Title()
            self.client_address = client.getPrintAddress()
        else:
            clientuid = None
            self.client_title = None
            self.client_address = None

        # Render form output

        # the report can add file names to this list; they will be deleted
        # once the PDF has been generated.  temporary plot image files, etc.
        self.request['to_remove'] = []

        if "report_module" in self.request:
            module = self.request["report_module"]
        else:
            module = "bika.lims.browser.reports.%s" % report_id
        try:
            exec ("from %s import Report" % module)
            # required during error redirect: the report must have a copy of
            # additional_reports, because it is used as a surrogate view.
            Report.additional_reports = self.additional_reports
        except ImportError:
            message = "Report %s.Report not found (shouldn't happen)" % module
            self.logger.error(message)
            self.context.plone_utils.addPortalMessage(message, 'error')
            return self.template()

        # Report must return dict with:
        # - report_title - title string for pdf/history listing
        # - report_data - rendered report
        output = Report(self.context, self.request)()

        # if CSV output is chosen, report returns None
        if not output:
            return

        if type(output) in (str, unicode, bytes):
            # remove temporary files
            for f in self.request['to_remove']:
                os.remove(f)
            return output

        # The report output gets pulled through report_frame.pt
        self.reportout = output['report_data']
        framed_output = self.frame_template()

        # this is the good part
        result = createPdf(framed_output)

        # remove temporary files
        for f in self.request['to_remove']:
            os.remove(f)

        if result:
            # Create new report object
            reportid = self.aq_parent.generateUniqueId('Report')
            report = _createObjectByType("Report", self.aq_parent, reportid)
            report.edit(Client=clientuid)
            report.processForm()

            # write pdf to report object
            report.edit(title=output['report_title'], ReportFile=result)
            report.reindexObject()

            fn = "%s - %s" % (self.date.strftime(self.date_format_short),
                              _u(output['report_title']))

            setheader = self.request.RESPONSE.setHeader
            setheader('Content-Type', 'application/pdf')
            setheader("Content-Disposition",
                      "attachment;filename=\"%s\"" % _c(fn))
            self.request.RESPONSE.write(result)

        return
Beispiel #22
0
class NewVersionsViewlet(ViewletBase):
    """ Handle notifications related to new version of Bika LIMS

    1) Check pypi for new version
    2) Check prefs to see if upgrade steps are required.

    """

    index = ViewPageTemplateFile("templates/new_version.pt")

    def get_versions(self):
        """Configure self.versions, a list of product versions
        from portal.quickinstaller
        """
        self.versions = {}
        qi = self.context.portal_quickinstaller
        for key in qi.keys():
            self.versions[key] = qi.getProductVersion(key)

    def check_new_version(self):
        """Look for new updates at pypi
        """
        self.current_version = self.versions['bika.lims']
        if not self.current_version:
            self.has_new_version = False
            return
        url = "https://pypi.python.org/pypi/bika.lims/json"
        try:
            jsonstr = urllib.urlopen(url).read()
            self.pypi = json.loads(jsonstr)
            v = self.new_version = self.pypi['info']['version']
            self.new_date = \
                self.pypi['releases'][v][0]['upload_time'].split('T')[0]
        except Exception as e:
            logger.info("Failed to retrieve new version info: %s" % e)
            v = self.current_version
            self.new_date = ""
        self.has_new_version = v > self.current_version

    def check_new_upgrade_step(self):
        """Warn about upgrade steps that have not been run.  This will override
        the users choice in settings: un-executed upgrade steps are always
        alerted.
        """
        qi = self.context.portal_quickinstaller
        self.info = qi.upgradeInfo('bika.lims')
        if self.info['installedVersion'] < self.info['newVersion']:
            self.has_upgrade_step = True
        else:
            self.has_upgrade_step = False

    def check_session(self):
        """Return False if the session hint claims that we already checked.
        Return True if the session has no record, or if more than one day has
        passed since we last checked.
        """
        et = time.time()
        try:
            sdm = self.context.session_data_manager
        except AttributeError:
            # While testing, the session data manager is not yet instantiated.
            return False
        session = sdm.getSessionData(create=True)
        diff = et - session.get('bika.lims-version-check', et)
        if diff > 86400 or diff == 0:
            session['bika.lims-version-check'] = et
            return True
        else:
            return False

    def render(self):
        if not self.check_session():
            return ""

        self.get_versions()
        self.check_new_version()
        self.check_new_upgrade_step()

        mtool = getToolByName(self.context, 'portal_membership')
        member = mtool.getAuthenticatedMember()
        roles = member.getRoles()
        allowed = 'LabManager' in roles or 'Manager' in roles

        if allowed \
                and self.context.bika_setup.getShowNewReleasesInfo() \
                and self.has_new_version:
            return self.index()
        elif allowed and self.has_upgrade_step:
            return self.index()
        else:
            return ""
Beispiel #23
0
class AuthenticatorViewlet(ViewletBase):
    index = ViewPageTemplateFile('templates/authenticator.pt')
class Report(BrowserView):
    implements(IViewView)
    template = ViewPageTemplateFile("templates/report_out.pt")

    def __init__(self, context, request, report=None):
        self.report = report
        BrowserView.__init__(self, context, request)

    def __call__(self):

        # get all the data into datalines
        sc = getToolByName(self.context, 'bika_setup_catalog')
        bac = getToolByName(self.context, 'bika_analysis_catalog')
        rc = getToolByName(self.context, 'reference_catalog')
        self.report_content = {}
        parm_lines = {}
        parms = []
        headings = {}
        headings['header'] = _("Analyses per sample type")
        headings['subheader'] = _(
            "Number of analyses requested per sample type")

        count_all = 0
        query = {'portal_type': 'Analysis'}
        client_title = None
        if 'ClientUID' in self.request.form:
            client_uid = self.request.form['ClientUID']
            query['getClientUID'] = client_uid
            client = rc.lookupObject(client_uid)
            client_title = client.Title()
        else:
            client = logged_in_client(self.context)
            if client:
                client_title = client.Title()
                query['getClientUID'] = client.UID()
        if client_title:
            parms.append({
                'title': _('Client'),
                'value': client_title,
                'type': 'text'
            })

        date_query = formatDateQuery(self.context, 'Requested')
        if date_query:
            query['created'] = date_query
            requested = formatDateParms(self.context, 'Requested')
            parms.append({
                'title': _('Requested'),
                'value': requested,
                'type': 'text'
            })

        workflow = getToolByName(self.context, 'portal_workflow')
        if 'bika_analysis_workflow' in self.request.form:
            query['review_state'] = self.request.form['bika_analysis_workflow']
            review_state = workflow.getTitleForStateOnType(
                self.request.form['bika_analysis_workflow'], 'Analysis')
            parms.append({
                'title': _('Status'),
                'value': review_state,
                'type': 'text'
            })

        if 'bika_cancellation_workflow' in self.request.form:
            query['cancellation_state'] = self.request.form[
                'bika_cancellation_workflow']
            cancellation_state = workflow.getTitleForStateOnType(
                self.request.form['bika_cancellation_workflow'], 'Analysis')
            parms.append({
                'title': _('Active'),
                'value': cancellation_state,
                'type': 'text'
            })

        if 'bika_worksheetanalysis_workflow' in self.request.form:
            query['worksheetanalysis_review_state'] = self.request.form[
                'bika_worksheetanalysis_workflow']
            ws_review_state = workflow.getTitleForStateOnType(
                self.request.form['bika_worksheetanalysis_workflow'],
                'Analysis')
            parms.append({
                'title': _('Assigned to worksheet'),
                'value': ws_review_state,
                'type': 'text'
            })

        # and now lets do the actual report lines
        formats = {
            'columns': 2,
            'col_heads': [_('Sample type'),
                          _('Number of analyses')],
            'class': '',
        }

        datalines = []
        for sampletype in sc(portal_type="SampleType",
                             sort_on='sortable_title'):
            query['getSampleTypeUID'] = sampletype.UID
            analyses = bac(query)
            count_analyses = len(analyses)

            dataline = []
            dataitem = {'value': sampletype.Title}
            dataline.append(dataitem)
            dataitem = {'value': count_analyses}

            dataline.append(dataitem)

            datalines.append(dataline)

            count_all += count_analyses

        # footer data
        footlines = []
        footline = []
        footitem = {'value': _('Total'), 'class': 'total_label'}
        footline.append(footitem)
        footitem = {'value': count_all}
        footline.append(footitem)
        footlines.append(footline)

        self.report_content = {
            'headings': headings,
            'parms': parms,
            'formats': formats,
            'datalines': datalines,
            'footings': footlines
        }

        if self.request.get('output_format', '') == 'CSV':
            import csv
            import StringIO
            import datetime

            fieldnames = [
                'Sample Type',
                'Analyses',
            ]
            output = StringIO.StringIO()
            dw = csv.DictWriter(output,
                                extrasaction='ignore',
                                fieldnames=fieldnames)
            dw.writerow(dict((fn, fn) for fn in fieldnames))
            for row in datalines:
                dw.writerow({
                    'Sample Type': row[0]['value'],
                    'Analyses': row[1]['value'],
                })
            report_data = output.getvalue()
            output.close()
            date = datetime.datetime.now().strftime("%Y%m%d%H%M")
            setheader = self.request.RESPONSE.setHeader
            setheader('Content-Type', 'text/csv')
            setheader(
                "Content-Disposition",
                "attachment;filename=\"analysespersampletype_%s.csv\"" % date)
            self.request.RESPONSE.write(report_data)
        else:
            return {
                'report_title': t(headings['header']),
                'report_data': self.template()
            }
Beispiel #25
0
class InstrumentQCFailuresViewlet(ViewletBase):
    """ Print a viewlet showing failed instruments
    """

    index = ViewPageTemplateFile("templates/instrument_qc_failures_viewlet.pt")

    def __init__(self, context, request, view, manager=None):
        super(InstrumentQCFailuresViewlet, self).__init__(context,
                                                          request,
                                                          view,
                                                          manager=manager)
        self.nr_failed = 0
        self.failed = {
            'out-of-date': [],
            'qc-fail': [],
            'next-test': [],
            'validation': [],
            'calibration': []
        }

    def get_failed_instruments(self):
        """ Find all active instruments who have failed QC tests
            Find instruments whose certificate is out of date
            Find instruments which are disposed until next calibration test

            Return a dictionary with all info about expired/invalid instruments

        """
        bsc = getToolByName(self, 'bika_setup_catalog')
        insts = bsc(portal_type='Instrument', inactive_state='active')
        for i in insts:
            i = i.getObject()
            instr = {
                'uid': i.UID(),
                'title': i.Title(),
            }
            if i.isValidationInProgress():
                instr['link'] = '<a href="%s/validations">%s</a>' % (
                    i.absolute_url(), i.Title())
                self.nr_failed += 1
                self.failed['validation'].append(instr)
            elif i.isCalibrationInProgress():
                instr['link'] = '<a href="%s/calibrations">%s</a>' % (
                    i.absolute_url(), i.Title())
                self.nr_failed += 1
                self.failed['calibration'].append(instr)
            elif i.isOutOfDate():
                instr['link'] = '<a href="%s/certifications">%s</a>' % (
                    i.absolute_url(), i.Title())
                self.nr_failed += 1
                self.failed['out-of-date'].append(instr)
            elif not i.isQCValid():
                instr['link'] = '<a href="%s/referenceanalyses">%s</a>' % (
                    i.absolute_url(), i.Title())
                self.nr_failed += 1
                self.failed['qc-fail'].append(instr)
            elif i.getDisposeUntilNextCalibrationTest():
                instr['link'] = '<a href="%s/referenceanalyses">%s</a>' % (
                    i.absolute_url(), i.Title())
                self.nr_failed += 1
                self.failed['next-test'].append(instr)

    def render(self):

        mtool = getToolByName(self.context, 'portal_membership')
        member = mtool.getAuthenticatedMember()
        roles = member.getRoles()
        allowed = 'LabManager' in roles or 'Manager' in roles

        self.get_failed_instruments()

        if allowed and self.nr_failed:
            return self.index()
        else:
            return ""
Beispiel #26
0
class AnalysisRequestAddView(AnalysisRequestViewView):
    """ The main AR Add form
    """
    implements(IViewView, IAnalysisRequestAddView)
    template = ViewPageTemplateFile("templates/ar_add.pt")
    ar_add_by_row_template = ViewPageTemplateFile('templates/ar_add_by_row.pt')
    ar_add_by_col_template = ViewPageTemplateFile('templates/ar_add_by_col.pt')

    def __init__(self, context, request):
        AnalysisRequestViewView.__init__(self, context, request)
        self.came_from = "add"
        self.can_edit_sample = True
        self.can_edit_ar = True
        self.DryMatterService = self.context.bika_setup.getDryMatterService()
        request.set('disable_plone.rightcolumn', 1)
        self.layout = "columns"
        self.ar_count = self.request.get('ar_count', 4)
        try:
            self.ar_count = int(self.ar_count)
        except:
            self.ar_count = 4

    def __call__(self):
        self.request.set('disable_border', 1)
        if 'ajax_category_expand' in self.request.keys():
            cat = self.request.get('cat')
            asv = AnalysisServicesView(self.context,
                                       self.request,
                                       self.request['form_id'],
                                       category=cat,
                                       ar_count=self.ar_count)
            return asv()
        else:
            return self.template()

    def copy_to_new_specs(self):
        specs = {}
        copy_from = self.request.get('copy_from', "")
        if not copy_from:
            return {}
        uids = copy_from.split(",")

        n = 0
        for uid in uids:
            proxies = self.bika_catalog(UID=uid)
            rr = proxies[0].getObject().getResultsRange()
            new_rr = []
            for i, r in enumerate(rr):
                s_uid = self.bika_setup_catalog(portal_type='AnalysisService',
                                                getKeyword=r['keyword'])[0].UID
                r['uid'] = s_uid
                new_rr.append(r)
            specs[n] = new_rr
            n += 1
        return json.dumps(specs)

    def getContacts(self):
        adapter = getAdapter(self.context.aq_parent, name='getContacts')
        return adapter()

    def partitioned_services(self):
        bsc = getToolByName(self.context, 'bika_setup_catalog')
        ps = []
        for service in bsc(portal_type='AnalysisService'):
            service = service.getObject()
            if service.getPartitionSetup() \
                    or service.getSeparate():
                ps.append(service.UID())
        return json.dumps(ps)

    def get_fields_with_visibility(self, visibility, mode=None):
        mode = mode if mode else 'add'
        schema = self.context.Schema()
        fields = []
        for field in schema.fields():
            isVisible = field.widget.isVisible
            v = isVisible(self.context, mode, default='invisible', field=field)
            if v == visibility:
                fields.append(field)
        return fields

    def services_widget_content(self, poc, ar_count=None):
        """Return a table displaying services to be selected for inclusion
        in a new AR.  Used in add_by_row view popup, and add_by_col add view.

        :param ar_count: number of AR columns to generate columns for.
        :return: string: rendered HTML content of bika_listing_table.pt.
            If no items are found, returns "".
        """

        if not ar_count:
            ar_count = self.ar_count

        s = AnalysisServicesView(self.context,
                                 self.request,
                                 poc,
                                 ar_count=ar_count)
        s.form_id = poc
        s.folderitems()

        if not s.ar_add_items:
            return ''
        return s.contents_table()
Beispiel #27
0
class ajaxServicePopup(BrowserView):

    template = ViewPageTemplateFile("templates/analysisservice_popup.pt")

    def __init__(self, context, request):
        super(ajaxServicePopup, self).__init__(context, request)
        self.icon = self.portal_url + "/++resource++bika.lims.images/analysisservice_big.png"

    def __call__(self):
        CheckAuthenticator(self.request)
        bsc = getToolByName(self.context, 'bika_setup_catalog')
        uc = getToolByName(self.context, 'uid_catalog')

        service_title = self.request.get('service_title', '').strip()
        if not service_title:
            return ''

        analysis = uc(UID=self.request.get('analysis_uid', None))
        if analysis:
            analysis = analysis[0].getObject()
            self.request['ajax_load'] = 1
            tmp = LogView(analysis, self.request)
            self.log = tmp.folderitems()
            self.log.reverse()
        else:
            self.log = []

        brains = bsc(portal_type="AnalysisService",
                     title=to_unicode(service_title))
        if not brains:
            return ''

        self.service = brains[0].getObject()

        self.calc = self.service.getCalculation()

        self.partsetup = self.service.getPartitionSetup()

        # convert uids to comma-separated list of display titles
        for i, ps in enumerate(self.partsetup):

            self.partsetup[i]['separate'] = \
                ps.has_key('separate') and _('Yes') or _('No')

            if type(ps['sampletype']) == str:
                ps['sampletype'] = [
                    ps['sampletype'],
                ]
            sampletypes = []
            for st in ps['sampletype']:
                res = bsc(UID=st)
                sampletypes.append(res and res[0].Title or st)
            self.partsetup[i]['sampletype'] = ", ".join(sampletypes)

            if ps.has_key('container'):
                if type(ps['container']) == str:
                    self.partsetup[i]['container'] = [
                        ps['container'],
                    ]
                try:
                    containers = [bsc(UID=c)[0].Title for c in ps['container']]
                except IndexError:
                    containers = [c for c in ps['container']]
                self.partsetup[i]['container'] = ", ".join(containers)
            else:
                self.partsetup[i]['container'] = ''

            if ps.has_key('preservation'):
                if type(ps['preservation']) == str:
                    ps['preservation'] = [
                        ps['preservation'],
                    ]
                try:
                    preservations = [
                        bsc(UID=c)[0].Title for c in ps['preservation']
                    ]
                except IndexError:
                    preservations = [c for c in ps['preservation']]
                self.partsetup[i]['preservation'] = ", ".join(preservations)
            else:
                self.partsetup[i]['preservation'] = ''

        return self.template()
Beispiel #28
0
class WorksheetPrintView(BrowserView):
    """ Print view for a worksheet. This view acts as a placeholder, so
        the user can select the preferred options (AR by columns, AR by
        rows, etc.) for printing. Both a print button and pdf button
        are shown.
    """

    template = ViewPageTemplateFile("worksheet/templates/worksheet_print.pt")
    _DEFAULT_TEMPLATE = 'ar_by_column.pt'
    _DEFAULT_NUMCOLS = 4
    _TEMPLATES_DIR = 'worksheet/templates/print'
    # Add-on folder to look for templates
    _TEMPLATES_ADDON_DIR = 'worksheets'
    _current_ws_index = 0
    _worksheets = []

    def __init__(self, context, request):
        super(WorksheetPrintView, self).__init__(context, request)
        self._worksheets = [self.context]

    def __call__(self):
        """ Entry point of WorksheetPrintView.
            If context.portal_type is a Worksheet, then the PrintView
            is initialized to manage only that worksheet. If the
            context.portal_type is a WorksheetFolder and there are
            items selected in the request (items param), the PrintView
            will show the preview for all the selected Worksheets.
            By default, returns a HTML-encoded template, but if the
            request contains a param 'pdf' with value 1, will flush a
            pdf for the worksheet.
        """

        if self.context.portal_type == 'Worksheet':
            self._worksheets = [self.context]

        elif self.context.portal_type == 'WorksheetFolder' \
            and self.request.get('items', ''):
            uids = self.request.get('items').split(',')
            uc = getToolByName(self.context, 'uid_catalog')
            self._worksheets = [obj.getObject() for obj in uc(UID=uids)]

        else:
            # Warn and redirect to referer
            logger.warning('WorksheetPrintView: type not allowed: %s' %
                           self.context.portal_type)
            self.destination_url = self.request.get_header(
                "referer", self.context.absolute_url())

        # Generate PDF?
        if self.request.form.get('pdf', '0') == '1':
            return self._flush_pdf()
        else:
            return self.template()

    def getWSTemplates(self):
        """ Returns a DisplayList with the available templates found in
            templates/worksheets
        """
        this_dir = os.path.dirname(os.path.abspath(__file__))
        templates_dir = os.path.join(this_dir, self._TEMPLATES_DIR)
        tempath = '%s/%s' % (templates_dir, '*.pt')
        templates = [t.split('/')[-1] for t in glob.glob(tempath)]
        out = []
        for template in templates:
            out.append({'id': template, 'title': template[:-3]})
        for templates_resource in iterDirectoriesOfType(
                self._TEMPLATES_ADDON_DIR):
            prefix = templates_resource.__name__
            templates = [
                tpl for tpl in templates_resource.listDirectory()
                if tpl.endswith('.pt')
            ]
            for template in templates:
                out.append({
                    'id': '{0}:{1}'.format(prefix, template),
                    'title': '{0} ({1})'.format(template[:-3], prefix),
                })
        return out

    def renderWSTemplate(self):
        """ Returns the current worksheet rendered with the template
            specified in the request (param 'template').
            Moves the iterator to the next worksheet available.
        """
        templates_dir = self._TEMPLATES_DIR
        embedt = self.request.get('template', self._DEFAULT_TEMPLATE)
        if embedt.find(':') >= 0:
            prefix, embedt = embedt.split(':')
            templates_dir = queryResourceDirectory(self._TEMPLATES_ADDON_DIR,
                                                   prefix).directory
        embed = ViewPageTemplateFile(os.path.join(templates_dir, embedt))
        reptemplate = ""
        try:
            reptemplate = embed(self)
        except:
            tbex = traceback.format_exc()
            wsid = self._worksheets[self._current_ws_index].id
            reptemplate = "<div class='error-print'>%s - %s '%s':<pre>%s</pre></div>" % (
                wsid, _("Unable to load the template"), embedt, tbex)
        if self._current_ws_index < len(self._worksheets):
            self._current_ws_index += 1
        return reptemplate

    def getCSS(self):
        """ Returns the css style to be used for the current template.
            If the selected template is 'default.pt', this method will
            return the content from 'default.css'. If no css file found
            for the current template, returns empty string
        """
        template = self.request.get('template', self._DEFAULT_TEMPLATE)
        content = ''
        if template.find(':') >= 0:
            prefix, template = template.split(':')
            resource = queryResourceDirectory(self._TEMPLATES_ADDON_DIR,
                                              prefix)
            css = '{0}.css'.format(template[:-3])
            if css in resource.listDirectory():
                content = resource.readFile(css)
        else:
            this_dir = os.path.dirname(os.path.abspath(__file__))
            templates_dir = os.path.join(this_dir, self._TEMPLATES_DIR)
            path = '%s/%s.css' % (templates_dir, template[:-3])
            with open(path, 'r') as content_file:
                content = content_file.read()
        return content

    def getNumColumns(self):
        """ Returns the number of columns to display
        """
        return int(self.request.get('numcols', self._DEFAULT_NUMCOLS))

    def getWorksheets(self):
        """ Returns the list of worksheets to be printed
        """
        return self._worksheets

    def getWorksheet(self):
        """ Returns the current worksheet from the list. Returns None when
            the iterator reaches the end of the array.
        """
        ws = None
        if self._current_ws_index < len(self._worksheets):
            ws = self._ws_data(self._worksheets[self._current_ws_index])
        return ws

    def splitList(self, elements, chunksnum):
        """ Splits a list to a n lists with chunksnum number of elements
            each one.
            For a list [3,4,5,6,7,8,9] with chunksunum 4, the method
            will return the following list of groups:
            [[3,4,5,6],[7,8,9]]
        """
        if len(elements) < chunksnum:
            return [elements]
        groups = zip(*[elements[i::chunksnum] for i in range(chunksnum)])
        if len(groups) * chunksnum < len(elements):
            groups.extend(
                [elements[-(len(elements) - len(groups) * chunksnum):]])
        return groups

    def _lab_data(self):
        """ Returns a dictionary that represents the lab object
            Keys: obj, title, url, address, confidence, accredited,
                  accreditation_body, accreditation_logo, logo
        """
        portal = self.context.portal_url.getPortalObject()
        lab = self.context.bika_setup.laboratory
        lab_address = lab.getPostalAddress() \
                        or lab.getBillingAddress() \
                        or lab.getPhysicalAddress()
        if lab_address:
            _keys = ['address', 'city', 'state', 'zip', 'country']
            _list = [
                "<div>%s</div>" % lab_address.get(v) for v in _keys
                if lab_address.get(v)
            ]
            lab_address = "".join(_list)
        else:
            lab_address = ''

        return {
            'obj': lab,
            'title': to_utf8(lab.Title()),
            'url': to_utf8(lab.getLabURL()),
            'address': to_utf8(lab_address),
            'confidence': lab.getConfidence(),
            'accredited': lab.getLaboratoryAccredited(),
            'accreditation_body': to_utf8(lab.getAccreditationBody()),
            'accreditation_logo': lab.getAccreditationBodyLogo(),
            'logo': "%s/logo_print.png" % portal.absolute_url()
        }

    def _ws_data(self, ws):
        """ Creates an ws dict, accessible from the view and from each
            specific template.
            Keys: obj, id, url, template_title, remarks, date_printed,
                ars, createdby, analyst, printedby, analyses_titles,
                portal, laboratory
        """
        data = {
            'obj': ws,
            'id': ws.id,
            'url': ws.absolute_url(),
            'template_title': ws.getWorksheetTemplateTitle(),
            'remarks': ws.getRemarks(),
            'date_printed': self.ulocalized_time(DateTime(), long_format=1),
            'date_created': self.ulocalized_time(ws.created(), long_format=1)
        }

        # Sub-objects
        data['ars'] = self._analyses_data(ws)
        data['createdby'] = self._createdby_data(ws)
        data['analyst'] = self._analyst_data(ws)
        data['printedby'] = self._printedby_data(ws)
        ans = []
        for ar in data['ars']:
            ans.extend([an['title'] for an in ar['analyses']])
        data['analyses_titles'] = list(set(ans))

        portal = self.context.portal_url.getPortalObject()
        data['portal'] = {'obj': portal, 'url': portal.absolute_url()}
        data['laboratory'] = self._lab_data()
        return data

    def _createdby_data(self, ws):
        """ Returns a dict that represents the user who created the ws
            Keys: username, fullmame, email
        """
        username = ws.getOwner().getUserName()
        return {
            'username': username,
            'fullname': to_utf8(self.user_fullname(username)),
            'email': to_utf8(self.user_email(username))
        }

    def _analyst_data(self, ws):
        """ Returns a dict that represent the analyst assigned to the
            worksheet.
            Keys: username, fullname, email
        """
        username = ws.getAnalyst()
        return {
            'username': username,
            'fullname': to_utf8(self.user_fullname(username)),
            'email': to_utf8(self.user_email(username))
        }

    def _printedby_data(self, ws):
        """ Returns a dict that represents the user who prints the ws
            Keys: username, fullname, email
        """
        data = {}
        member = self.context.portal_membership.getAuthenticatedMember()
        if member:
            username = member.getUserName()
            data['username'] = username
            data['fullname'] = to_utf8(self.user_fullname(username))
            data['email'] = to_utf8(self.user_email(username))

            c = [
                x for x in self.bika_setup_catalog(portal_type='LabContact')
                if x.getObject().getUsername() == username
            ]
            if c:
                sf = c[0].getObject().getSignature()
                if sf:
                    data['signature'] = sf.absolute_url() + "/Signature"

        return data

    def _analyses_data(self, ws):
        """ Returns a list of dicts. Each dict represents an analysis
            assigned to the worksheet
        """
        ans = ws.getAnalyses()
        layout = ws.getLayout()
        an_count = len(ans)
        pos_count = 0
        prev_pos = 0
        requestids = []
        ars = {}
        samples = {}
        clients = {}
        for an in ans:
            # Build the analysis-specific dict
            if an.portal_type == "DuplicateAnalysis":
                andict = self._analysis_data(an.getAnalysis())
                andict['id'] = an.getReferenceAnalysesGroupID()
                andict['obj'] = an
                andict['type'] = "DuplicateAnalysis"
                andict['reftype'] = 'd'
            else:
                andict = self._analysis_data(an)

            # Analysis position
            pos = [slot['position'] for slot in layout \
                if slot['analysis_uid'] == an.UID()][0]
            # compensate for possible bad data (dbw#104)
            if type(pos) in (list, tuple) and pos[0] == 'new':
                pos = prev_pos
            pos = int(pos)
            prev_pos = pos

            # This will allow to sort automatically all the analyses,
            # also if they have the same initial position.
            andict['tmp_position'] = (pos * 100) + pos_count
            andict['position'] = pos
            pos_count += 1

            # Look for the analysis request, client and sample info and
            # group the analyses per Analysis Request
            reqid = andict['request_id']
            if an.portal_type in ("ReferenceAnalysis", "DuplicateAnalysis"):
                reqid = an.getReferenceAnalysesGroupID()

            if reqid not in ars:
                arobj = an.aq_parent
                if an.portal_type == "DuplicateAnalysis":
                    arobj = an.getAnalysis().aq_parent

                ar = self._ar_data(arobj)
                ar['client'] = self._client_data(arobj.aq_parent)
                ar['sample'] = self._sample_data(an.getSample())
                ar['analyses'] = []
                ar['tmp_position'] = andict['tmp_position']
                ar['position'] = andict['position']
                if an.portal_type in ("ReferenceAnalysis",
                                      "DuplicateAnalysis"):
                    ar['id'] = an.getReferenceAnalysesGroupID()
                    ar['url'] = an.absolute_url()

            else:
                ar = ars[reqid]
                if (andict['tmp_position'] < ar['tmp_position']):
                    ar['tmp_position'] = andict['tmp_position']
                    ar['position'] = andict['position']

            # Sort analyses by position
            ans = ar['analyses']
            ans.append(andict)
            ans.sort(
                lambda x, y: cmp(x.get('tmp_position'), y.get('tmp_position')))
            ar['analyses'] = ans
            ars[reqid] = ar

        ars = [ar for ar in ars.itervalues()]

        # Sort analysis requests by position
        ars.sort(
            lambda x, y: cmp(x.get('tmp_position'), y.get('tmp_position')))
        return ars

    def _analysis_data(self, analysis):
        """ Returns a dict that represents the analysis
        """
        decimalmark = analysis.aq_parent.aq_parent.getDecimalMark()
        keyword = analysis.getKeyword()
        service = analysis.getService()
        andict = {'obj': analysis,
                  'id': analysis.id,
                  'title': analysis.Title(),
                  'keyword': keyword,
                  'scientific_name': service.getScientificName(),
                  'accredited': service.getAccredited(),
                  'point_of_capture': to_utf8(POINTS_OF_CAPTURE.getValue(service.getPointOfCapture())),
                  'category': to_utf8(service.getCategoryTitle()),
                  'result': analysis.getResult(),
                  'unit': to_utf8(service.getUnit()),
                  'formatted_unit': format_supsub(to_utf8(service.getUnit())),
                  'capture_date': analysis.getResultCaptureDate(),
                  'request_id': analysis.aq_parent.getId(),
                  'formatted_result': '',
                  'uncertainty': analysis.getUncertainty(),
                  'formatted_uncertainty': '',
                  'retested': analysis.getRetested(),
                  'remarks': to_utf8(analysis.getRemarks()),
                  'resultdm': to_utf8(analysis.getResultDM()),
                  'outofrange': False,
                  'type': analysis.portal_type,
                  'reftype': analysis.getReferenceType() \
                            if hasattr(analysis, 'getReferenceType')
                            else None,
                  'worksheet': None,
                  'specs': {},
                  'formatted_specs': ''}

        andict['refsample'] = analysis.getSample().id \
                            if analysis.portal_type == 'Analysis' \
                            else '%s - %s' % (analysis.aq_parent.id, analysis.aq_parent.Title())

        # Which analysis specs must be used?
        # Try first with those defined at AR Publish Specs level
        if analysis.portal_type == 'ReferenceAnalysis':
            # The analysis is a Control or Blank. We might use the
            # reference results instead other specs
            uid = analysis.getServiceUID()
            specs = analysis.aq_parent.getResultsRangeDict().get(uid, {})

        elif analysis.portal_type == 'DuplicateAnalysis':
            specs = analysis.getAnalysisSpecs()

        else:
            ar = analysis.aq_parent
            specs = ar.getPublicationSpecification()
            if not specs or keyword not in specs.getResultsRangeDict():
                specs = analysis.getAnalysisSpecs()
            specs = specs.getResultsRangeDict().get(keyword, {}) \
                    if specs else {}

        andict['specs'] = specs
        scinot = self.context.bika_setup.getScientificNotationReport()
        andict['formatted_result'] = analysis.getFormattedResult(
            specs=specs, sciformat=int(scinot), decimalmark=decimalmark)

        fs = ''
        if specs.get('min', None) and specs.get('max', None):
            fs = '%s - %s' % (specs['min'], specs['max'])
        elif specs.get('min', None):
            fs = '> %s' % specs['min']
        elif specs.get('max', None):
            fs = '< %s' % specs['max']
        andict['formatted_specs'] = formatDecimalMark(fs, decimalmark)
        andict['formatted_uncertainty'] = format_uncertainty(
            analysis,
            analysis.getResult(),
            decimalmark=decimalmark,
            sciformat=int(scinot))

        # Out of range?
        if specs:
            adapters = getAdapters((analysis, ), IResultOutOfRange)
            bsc = getToolByName(self.context, "bika_setup_catalog")
            for name, adapter in adapters:
                ret = adapter(specification=specs)
                if ret and ret['out_of_range']:
                    andict['outofrange'] = True
                    break
        return andict

    def _sample_data(self, sample):
        """ Returns a dict that represents the sample
            Keys: obj, id, url, client_sampleid, date_sampled,
                  sampling_date, sampler, date_received, composite,
                  date_expired, date_disposal, date_disposed, adhoc,
                  remarks
        """
        data = {}
        if sample:
            data = {
                'obj':
                sample,
                'id':
                sample.id,
                'url':
                sample.absolute_url(),
                'date_sampled':
                self.ulocalized_time(sample.getDateSampled(), long_format=0),
                'date_received':
                self.ulocalized_time(sample.getDateReceived(), long_format=0),
            }

            if sample.portal_type == "ReferenceSample":
                data['sample_type'] = None
                data['sample_point'] = None
            else:
                data['sample_type'] = self._sample_type(sample)
                data['sample_point'] = self._sample_point(sample)
        return data

    def _sample_type(self, sample=None):
        """ Returns a dict that represents the sample type assigned to
            the sample specified
            Keys: obj, id, title, url
        """
        data = {}
        sampletype = sample.getSampleType() if sample else None
        if sampletype:
            data = {
                'obj': sampletype,
                'id': sampletype.id,
                'title': sampletype.Title(),
                'url': sampletype.absolute_url()
            }
        return data

    def _sample_point(self, sample=None):
        """ Returns a dict that represents the sample point assigned to
            the sample specified
            Keys: obj, id, title, url
        """
        samplepoint = sample.getSamplePoint() if sample else None
        data = {}
        if samplepoint:
            data = {
                'obj': samplepoint,
                'id': samplepoint.id,
                'title': samplepoint.Title(),
                'url': samplepoint.absolute_url()
            }
        return data

    def _ar_data(self, ar):
        """ Returns a dict that represents the analysis request
        """
        if not ar:
            return {}

        if ar.portal_type == "AnalysisRequest":
            return {
                'obj':
                ar,
                'id':
                ar.getRequestID(),
                'date_received':
                self.ulocalized_time(ar.getDateReceived(), long_format=0),
                'date_sampled':
                self.ulocalized_time(ar.getDateSampled(), long_format=0),
                'url':
                ar.absolute_url(),
            }
        elif ar.portal_type == "ReferenceSample":
            return {
                'obj':
                ar,
                'id':
                ar.id,
                'date_received':
                self.ulocalized_time(ar.getDateReceived(), long_format=0),
                'date_sampled':
                self.ulocalized_time(ar.getDateSampled(), long_format=0),
                'url':
                ar.absolute_url(),
            }
        else:
            return {
                'obj': ar,
                'id': ar.id,
                'date_received': "",
                'date_sampled': "",
                'url': ar.absolute_url(),
            }

    def _client_data(self, client):
        """ Returns a dict that represents the client specified
            Keys: obj, id, url, name
        """
        data = {}
        if client:
            data['obj'] = client
            data['id'] = client.id
            data['url'] = client.absolute_url()
            data['name'] = to_utf8(client.getName())
        return data

    def _flush_pdf():
        """ Generates a PDF using the current layout as the template and
            returns the chunk of bytes.
        """
        return ""
Beispiel #29
0
class AnalysisServiceCopy(BrowserView):
    template = ViewPageTemplateFile('templates/analysisservice_copy.pt')
    # should never be copied between services
    skip_fieldnames = [
        'UID',
        'id',
        'title',
        'ShortTitle',
        'Keyword',
    ]
    created = []

    def create_service(self, src_uid, dst_title, dst_keyword):
        folder = self.context.bika_setup.bika_analysisservices
        dst_service = _createObjectByType("AnalysisService", folder, tmpID())
        # manually set keyword and title
        dst_service.setKeyword(dst_keyword)
        dst_service.setTitle(dst_title)
        dst_service.unmarkCreationFlag()
        _id = renameAfterCreation(dst_service)
        dst_service = folder[_id]
        return dst_service

    def validate_service(self, dst_service):
        # validate entries
        validator = ServiceKeywordValidator()
        # baseschema uses uniquefieldvalidator on title, this is sufficient.
        res = validator(dst_service.getKeyword(), instance=dst_service)
        if res is not True:
            self.savepoint.rollback()
            self.created = []
            self.context.plone_utils.addPortalMessage(res, 'info')
            return False
        return True

    def copy_service(self, src_uid, dst_title, dst_keyword):
        uc = getToolByName(self.context, 'uid_catalog')
        src_service = uc(UID=src_uid)[0].getObject()
        dst_service = self.create_service(src_uid, dst_title, dst_keyword)
        if self.validate_service(dst_service):
            # copy field values
            for field in src_service.Schema().fields():
                fieldname = field.getName()
                if field.getType() == "Products.Archetypes.Field.ComputedField" \
                        or fieldname in self.skip_fieldnames:
                    continue
                getter = field.getAccessor(src_service)
                setter = dst_service.Schema()[fieldname].getMutator(
                    dst_service)
                setter(getter())
            dst_service.reindexObject()
            return dst_title
        else:
            return False

    def __call__(self):
        uc = getToolByName(self.context, 'uid_catalog')
        if 'copy_form_submitted' not in self.request:
            uids = self.request.form.get('uids', [])
            self.services = []
            for uid in uids:
                proxies = uc(UID=uid)
                if proxies:
                    self.services.append(proxies[0].getObject())
            return self.template()
        else:
            self.savepoint = savepoint()
            sources = self.request.form.get('uids', [])
            titles = self.request.form.get('dst_title', [])
            keywords = self.request.form.get('dst_keyword', [])
            self.created = []
            for i, s in enumerate(sources):
                if not titles[i]:
                    message = _('Validation failed: title is required')
                    self.context.plone_utils.addPortalMessage(message, 'info')
                    self.savepoint.rollback()
                    self.created = []
                    break
                if not keywords[i]:
                    message = _('Validation failed: keyword is required')
                    self.context.plone_utils.addPortalMessage(message, 'info')
                    self.savepoint.rollback()
                    self.created = []
                    break
                title = self.copy_service(s, titles[i], keywords[i])
                if title:
                    self.created.append(title)
            if len(self.created) > 1:
                message = t(
                    _('${items} were successfully created.',
                      mapping={'items':
                               safe_unicode(', '.join(self.created))}))
            elif len(self.created) == 1:
                message = t(
                    _('${item} was successfully created.',
                      mapping={'item': safe_unicode(self.created[0])}))
            else:
                message = _('No new items were created.')
            self.context.plone_utils.addPortalMessage(message, 'info')
            self.request.response.redirect(self.context.absolute_url())
Beispiel #30
0
class InvoiceView(BrowserView):

    implements(IInvoiceView)

    template = ViewPageTemplateFile("templates/invoice.pt")
    content = ViewPageTemplateFile("templates/invoice_content.pt")

    def __init__(self, context, request):
        super(InvoiceView, self).__init__(context, request)
        request.set('disable_border', 1)

    def __call__(self):
        context = self.context
        workflow = getToolByName(context, 'portal_workflow')
        # Gather relted objects
        batch = context.aq_parent
        client = context.getClient()
        analysis_request = context.getAnalysisRequest() if context.getAnalysisRequest() else None
        # Gather general data
        self.invoiceId = context.getId()
        self.invoiceDate = self.ulocalized_time(context.getInvoiceDate())
        self.subtotal = '%0.2f' % context.getSubtotal()
        self.VATAmount = '%0.2f' % context.getVATAmount()
        self.total = '%0.2f' % context.getTotal()
        # Create the batch range
        start = self.ulocalized_time(batch.getBatchStartDate())
        end = self.ulocalized_time(batch.getBatchEndDate())
        self.batchRange = "%s to %s" % (start, end)
        # Gather client data
        self.clientName = client.Title()
        self.clientURL = client.absolute_url()
        self.clientPhone = client.getPhone()
        self.clientFax = client.getFax()
        self.clientEmail = client.getEmailAddress()
        self.clientAccountNumber = client.getAccountNumber()
        # currency info
        locale = locales.getLocale('en')
        self.currency = self.context.bika_setup.getCurrency()
        self.symbol = locale.numbers.currencies[self.currency].symbol
        # Get an available client address in a preferred order
        self.clientAddress = None
        addresses = (
            client.getBillingAddress(),
            client.getPostalAddress(),
            client.getPhysicalAddress(),
        )
        for address in addresses:
            if address.get('address'):
                self.clientAddress = address
                break
        # Gather the line items
        items = context.invoice_lineitems
        self.items = [{
            'invoiceDate': self.ulocalized_time(item['ItemDate']),
            'description': item['ItemDescription'],
            'orderNo': item['OrderNumber'],
            'orderNoURL': item['AnalysisRequest'].absolute_url(),
            'subtotal': item['Subtotal'],
            'VATAmount': item['VATAmount'],
            'total': item['Total'],
        } for item in items]
        # Render the template
        return self.template()