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()
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()
class InstrumentCertificationsViewView(BrowserView): """ View of Instrument Certifications Shows the list of Instrument Certifications, either Internal and External Calibrations. """ implements(IViewView) template = ViewPageTemplateFile("templates/instrument_certifications.pt") _certificationsview = None def __call__(self): return self.template() def get_certifications_table(self): """ Returns the table of Certifications """ return self.get_certifications_view().contents_table() def get_certifications_view(self): """ Returns the Certifications Table view """ if not self._certificationsview: self._certificationsview = InstrumentCertificationsView( self.context, self.request) return self._certificationsview
class 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
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()
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 []
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()
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()
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()
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()
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()
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()
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')
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()
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
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()
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()
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 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)
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
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 ""
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() }
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 ""
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()
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()
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 ""
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())
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()