def folderitem(self, obj, item, index): """Applies new properties to the item (Client) that is currently being rendered as a row in the list :param obj: client to be rendered as a row in the list :param item: dict representation of the client, suitable for the list :param index: current position of the item within the list :type obj: ATContentType/DexterityContentType :type item: dict :type index: int :return: the dict representation of the item :rtype: dict """ url = obj.absolute_url() title = obj.Title() item['Description'] = obj.Description() item["replace"]["Title"] = get_link(url, value=title) # Icons after_icons = "" if obj.getBlank(): after_icons += get_image("blank.png", title=t(_("Blank"))) if obj.getHazardous(): after_icons += get_image("hazardous.png", title=t(_("Hazardous"))) if after_icons: item["after"]["Title"] = after_icons return item
def _folder_item_specifications(self, analysis_brain, item): """Set the results range to the item passed in""" # Everyone can see valid-ranges item['Specification'] = '' analysis = api.get_object(analysis_brain) results_range = analysis.getResultsRange() if not results_range: return # Display the specification interval item["Specification"] = get_formatted_interval(results_range, "") # Show an icon if out of range out_range, out_shoulders = is_out_of_range(analysis_brain) if not out_range: return # At least is out of range img = get_image("exclamation.png", title=_("Result out of range")) if not out_shoulders: img = get_image("warning.png", title=_("Result in shoulder range")) self._append_html_element(item, "Result", img) # Grades grade = api.get_grade_number(analysis_brain) if grade: span = " <span class='small grade_{}'>G{}</span>".format( grade, grade) self._append_html_element(item, "Result", span)
def _folder_item_specifications(self, analysis_brain, item): """Set the results range to the item passed in""" # Everyone can see valid-ranges item['Specification'] = '' results_range = analysis_brain.getResultsRange if not results_range: return min_str = results_range.get('min', '') max_str = results_range.get('max', '') min_str = api.is_floatable(min_str) and "{0}".format(min_str) or "" max_str = api.is_floatable(max_str) and "{0}".format(max_str) or "" specs = ", ".join([val for val in [min_str, max_str] if val]) if not specs: return item["Specification"] = "[{}]".format(specs) # Show an icon if out of range out_range, out_shoulders = is_out_of_range(analysis_brain) if not out_range: return # At least is out of range img = get_image("exclamation.png", title=_("Result out of range")) if not out_shoulders: img = get_image("warning.png", title=_("Result in shoulder range")) self._append_html_element(item, "Result", img)
def folderitem(self, obj, item, index): """Service triggered each time an item is iterated in folderitems. The use of this service prevents the extra-loops in child objects. :obj: the instance of the class to be foldered :item: dict containing the properties of the object to be used by the template :index: current index of the item """ # ensure we have an object and not a brain obj = api.get_object(obj) uid = api.get_uid(obj) url = api.get_url(obj) title = api.get_title(obj) # get the category if self.show_categories_enabled(): category = obj.getCategoryTitle() if category not in self.categories: self.categories.append(category) item["category"] = category config = self.configuration.get(uid, {}) hidden = config.get("hidden", False) item["replace"]["Title"] = get_link(url, value=title) item["Price"] = self.format_price(obj.Price) item["allow_edit"] = self.get_editable_columns() item["selected"] = False item["Hidden"] = hidden item["selected"] = uid in self.configuration # Add methods methods = obj.getMethods() if methods: links = map( lambda m: get_link( m.absolute_url(), value=m.Title(), css_class="link"), methods) item["replace"]["Methods"] = ", ".join(links) else: item["methods"] = "" # Icons after_icons = "" if obj.getAccredited(): after_icons += get_image( "accredited.png", title=_("Accredited")) if obj.getAttachmentOption() == "r": after_icons += get_image( "attach_reqd.png", title=_("Attachment required")) if obj.getAttachmentOption() == "n": after_icons += get_image( "attach_no.png", title=_("Attachment not permitted")) if after_icons: item["after"]["Title"] = after_icons return item
def folderitem(self, obj, item, index): """Applies new properties to the item (Client) that is currently being rendered as a row in the list :param obj: client to be rendered as a row in the list :param item: dict representation of the client, suitable for the list :param index: current position of the item within the list :type obj: ATContentType/DexterityContentType :type item: dict :type index: int :return: the dict representation of the item :rtype: dict """ obj = api.get_object(obj) # XXX Refactor expiration to a proper place # ---------------------------- 8< ------------------------------------- if item.get("review_state", "current") == "current": # Check expiry date exdate = obj.getExpiryDate() if exdate: expirydate = DT2dt(exdate).replace(tzinfo=None) if (datetime.today() > expirydate): # Trigger expiration self.workflow.doActionFor(obj, "expire") item["review_state"] = "expired" item["obj"] = obj if self.contentFilter.get('review_state', '') \ and item.get('review_state', '') == 'expired': # This item must be omitted from the list return None # ---------------------------- >8 ------------------------------------- url = api.get_url(obj) id = api.get_id(obj) item["ID"] = id item["replace"]["ID"] = get_link(url, value=id) item["DateSampled"] = self.ulocalized_time( obj.getDateSampled(), long_format=True) item["DateReceived"] = self.ulocalized_time(obj.getDateReceived()) item["DateOpened"] = self.ulocalized_time(obj.getDateOpened()) item["ExpiryDate"] = self.ulocalized_time(obj.getExpiryDate()) # Icons after_icons = '' if obj.getBlank(): after_icons += get_image( "blank.png", title=t(_("Blank"))) if obj.getHazardous(): after_icons += get_image( "hazardous.png", title=t(_("Hazardous"))) if after_icons: item["after"]["ID"] = after_icons return item
def folderitem(self, obj, item, index): """Processed once per analysis """ cat = obj.getCategoryTitle() # Category (upper C) is for display column value item["Category"] = cat if self.do_cats: # category is for bika_listing to groups entries item["category"] = cat if cat not in self.categories: self.categories.append(cat) analyses = [a.UID() for a in self.fieldvalue] item["selected"] = item["uid"] in analyses item["class"]["Title"] = "service_title" # Price item["Price"] = self.format_price(obj.Price) item["class"]["Price"] = "nowrap" # Icons after_icons = "" if obj.getAccredited(): after_icons += get_image("accredited.png", title=_("Accredited")) if obj.getAttachmentOption() == "r": after_icons += get_image("attach_reqd.png", title=_("Attachment required")) if obj.getAttachmentOption() == "n": after_icons += get_image("attach_no.png", title=_("Attachment not permitted")) if after_icons: item["after"]["Title"] = after_icons if self.profile: # Display analyses for this Analysis Service in results? ser = self.profile.getAnalysisServiceSettings(obj.UID()) item["allow_edit"] = [ "Hidden", ] item["Hidden"] = ser.get("hidden", obj.getHidden()) # Add methods methods = obj.getMethods() if methods: links = map( lambda m: get_link( m.absolute_url(), value=m.Title(), css_class="link"), methods) item["replace"]["Methods"] = ", ".join(links) else: item["methods"] = "" return item
def folderitem(self, obj, item, index): """Service triggered each time an item is iterated in folderitems. The use of this service prevents the extra-loops in child objects. :obj: the instance of the class to be foldered :item: dict containing the properties of the object to be used by the template :index: current index of the item """ # ensure we have an object and not a brain obj = api.get_object(obj) uid = api.get_uid(obj) url = api.get_url(obj) title = api.get_title(obj) # get the category if self.show_categories_enabled(): category = obj.getCategoryTitle() if category not in self.categories: self.categories.append(category) item["category"] = category rr = self.referenceresults.get(uid, {}) item["Title"] = title item["replace"]["Title"] = get_link(url, value=title) item["allow_edit"] = self.get_editable_columns() item["required"] = self.get_required_columns() item["selected"] = rr and True or False item["result"] = rr.get("result", "") item["min"] = rr.get("min", "") item["max"] = rr.get("max", "") item["error"] = rr.get("error", "") # Icons after_icons = "" if obj.getAccredited(): after_icons += get_image( "accredited.png", title=_("Accredited")) if obj.getAttachmentOption() == "r": after_icons += get_image( "attach_reqd.png", title=_("Attachment required")) if obj.getAttachmentOption() == "n": after_icons += get_image( "attach_no.png", title=_("Attachment not permitted")) if after_icons: item["after"]["Title"] = after_icons return item
def folderitem(self, obj, item, index): """Service triggered each time an item is iterated in folderitems. The use of this service prevents the extra-loops in child objects. :obj: the instance of the class to be foldered :item: dict containing the properties of the object to be used by the template :index: current index of the item """ DueDate = obj.getDueDate item["getDateReceived"] = self.ulocalized_time(obj.getDateReceived) item["getDueDate"] = self.ulocalized_time(DueDate) if DueDate and DueDate < DateTime(): item["after"]["DueDate"] = get_image("late.png", title=t(_("Late Analysis"))) # Add Priority column priority_sort_key = obj.getPrioritySortkey if not priority_sort_key: # Default priority is Medium = 3. # The format of PrioritySortKey is <priority>.<created> priority_sort_key = "3.%s" % obj.created.ISO8601() priority = priority_sort_key.split(".")[0] priority_text = t(PRIORITIES.getValue(priority)) html = "<div title='{}' class='priority-ico priority-{}'><div>" item["replace"]["Priority"] = html.format(priority_text, priority) return item
def _folder_item_assigned_worksheet(self, analysis_brain, item): """Adds an icon to the item dict if the analysis is assigned to a worksheet and if the icon is suitable for the current context :param analysis_brain: Brain that represents an analysis :param item: analysis' dictionary counterpart that represents a row """ if not IAnalysisRequest.providedBy(self.context): # We want this icon to only appear if the context is an AR return if analysis_brain.worksheetanalysis_review_state != 'assigned': # No need to go further. This analysis is not assigned to any WS return analysis_obj = self.get_object(analysis_brain) worksheet = analysis_obj.getBackReferences('WorksheetAnalysis') if not worksheet: # No worksheet assigned. Do nothing return worksheet = worksheet[0] title = t( _("Assigned to: ${worksheet_id}", mapping={'worksheet_id': safe_unicode(worksheet.id)})) img = get_image('worksheet.png', title=title) anchor = get_link(worksheet.absolute_url(), img) self._append_html_element(item, 'state_title', anchor)
def _folder_item_duedate(self, analysis_brain, item): """Set the analysis' due date to the item passed in. :param analysis_brain: Brain that represents an analysis :param item: analysis' dictionary counterpart that represents a row """ # Note that if the analysis is a Reference Analysis, `getDueDate` # returns the date when the ReferenceSample expires. If the analysis is # a duplicate, `getDueDate` returns the due date of the source analysis due_date = analysis_brain.getDueDate if not due_date: return None due_date_str = self.ulocalized_time(due_date, long_format=0) item['DueDate'] = due_date_str # If the Analysis is late/overdue, display an icon capture_date = analysis_brain.getResultCaptureDate capture_date = capture_date or DateTime() if capture_date > due_date: # The analysis is late or overdue img = get_image('late.png', title=t(_("Late Analysis")), width='16px', height='16px') item['replace']['DueDate'] = '{} {}'.format(due_date_str, img)
def get_icon_for(self, typename): """Returns the big image icon by its (type-)name """ image = "{}_big.png".format(typename) return get_image(image, width="20px", style="vertical-align: baseline;")
def folderitem(self, obj, item, index): # Date of Birth dob = obj.getBirthDate item['getBirthDate'] = dob and self.ulocalized_time(dob) or "" try: item["age"] = dob and get_age_ymd(dob) or "" except: # Wrong date?? msg = _("Date of Birth might be wrong") img = get_image("exclamation.png", title=msg) item["replace"]["age"] = img # make the columns patient title, patient ID and client patient ID # redirect to the Analysis Requests of the patient ars_url = "{}/{}".format(api.get_url(obj), "analysisrequests") for column in ['Title', 'getPatientID', 'getClientPatientID']: value = getattr(obj, column, None) if value: item["replace"][column] = get_link(ars_url, value) # Display the internal/external icons, but only if the logged-in user # does not belong to an external client if not self.is_external_user(): # Renders an icon (shared/private/warn) next to the title of the # item based on the client item["before"]["Title"] = get_client_aware_html_image(obj) return item
def folderitem(self, obj, item, index): item = super(QCAnalysesView, self).folderitem(obj, item, index) obj = self.get_object(obj) # Fill Worksheet cell worksheet = obj.getWorksheet() if not worksheet: return item # Fill the Worksheet cell ws_id = api.get_id(worksheet) ws_url = api.get_url(worksheet) item["replace"]["Worksheet"] = get_link(ws_url, value=ws_id) if IDuplicateAnalysis.providedBy(obj): an_type = "d" img_name = "duplicate.png" parent = obj.getRequest() else: an_type = obj.getReferenceType() img_name = an_type == "c" and "control.png" or "blank.png" parent = obj.aq_parent # Render the image an_type = QCANALYSIS_TYPES.getValue(an_type) item['before']['Service'] = get_image(img_name, title=an_type) # Fill the Parent cell parent_url = api.get_url(parent) parent_id = api.get_id(parent) item["replace"]["Parent"] = get_link(parent_url, value=parent_id) return item
def folderitem(self, obj, item, index): """Augment folder listing item """ url = item.get("url") title = item.get("Title") item["replace"]["Title"] = get_link(url, value=title) item["getType"] = _(obj.getType()[0]) item["getDownFrom"] = self.localize_date(obj.getDownFrom()) item["getDownTo"] = self.localize_date(obj.getDownTo()) item["getMaintainer"] = obj.getMaintainer() status = obj.getCurrentState() statustext = obj.getCurrentStateI18n() statusimg = "" if status == mstatus.CLOSED: statusimg = "instrumentmaintenance_closed.png" item["state_class"] = "state-inactive" elif status == mstatus.CANCELLED: statusimg = "instrumentmaintenance_cancelled.png" item["state_class"] = "state-cancelled" elif status == mstatus.INQUEUE: statusimg = "instrumentmaintenance_inqueue.png" item["state_class"] = "state-open" elif status == mstatus.OVERDUE: statusimg = "instrumentmaintenance_overdue.png" item["state_class"] = "state-open" elif status == mstatus.PENDING: statusimg = "instrumentmaintenance_pending.png" item["state_class"] = "state-pending" item["replace"]["getCurrentState"] = get_image(statusimg, title=statustext) return item
def _folder_item_specifications(self, analysis_brain, item): """Set the results range to the item passed in""" # Everyone can see valid-ranges item['Specification'] = '' results_range = analysis_brain.getResultsRange if not results_range: return # Display the specification interval item["Specification"] = get_formatted_interval(results_range, "") # Show an icon if out of range out_range, out_shoulders = is_out_of_range(analysis_brain) if not out_range: return # At least is out of range img = get_image("exclamation.png", title=_("Result out of range")) if not out_shoulders: img = get_image("warning.png", title=_("Result in shoulder range")) self._append_html_element(item, "Result", img)
def _folder_item_result(self, analysis_brain, item): """Set the analysis' result to the item passed in. :param analysis_brain: Brain that represents an analysis :param item: analysis' dictionary counterpart that represents a row """ item["Result"] = "" if not self.has_permission(ViewResults, analysis_brain): # If user has no permissions, don"t display the result but an icon img = get_image("to_follow.png", width="16px", height="16px") item["before"]["Result"] = img return result = analysis_brain.getResult capture_date = analysis_brain.getResultCaptureDate capture_date_str = self.ulocalized_time(capture_date, long_format=0) item["Result"] = result item["CaptureDate"] = capture_date_str item["result_captured"] = capture_date_str item["string_result"] = False # Edit mode enabled of this Analysis if self.is_analysis_edition_allowed(analysis_brain): # Allow to set Remarks item["allow_edit"].append("Remarks") # Set the results field editable if self.is_result_edition_allowed(analysis_brain): item["allow_edit"].append("Result") # Prepare result options choices = analysis_brain.getResultOptions if choices: # N.B.we copy here the list to avoid persistent changes choices = copy(choices) # By default set empty as the default selected choice choices.insert(0, dict(ResultValue="", ResultText="")) item["choices"]["Result"] = choices else: # If not choices, set whether the result must be floatable obj = self.get_object(analysis_brain) item["string_result"] = obj.getStringResult() if not result: return obj = self.get_object(analysis_brain) formatted_result = obj.getFormattedResult(sciformat=int(self.scinot), decimalmark=self.dmk) item["formatted_result"] = formatted_result
def _folder_item_reflex_icons(self, analysis_brain, item): """Adds an icon to the item dictionary if the analysis has been automatically generated due to a reflex rule :param analysis_brain: Brain that represents an analysis :param item: analysis' dictionary counterpart that represents a row """ if not analysis_brain.getIsReflexAnalysis: # Do nothing return img = get_image('reflexrule.png', title=t(_('It comes form a reflex rule'))) self._append_html_element(item, 'Service', img)
def _folder_item_result(self, analysis_brain, item): """Set the analysis' result to the item passed in. :param analysis_brain: Brain that represents an analysis :param item: analysis' dictionary counterpart that represents a row """ item['Result'] = '' if not self.has_permission(ViewResults, analysis_brain): # If user has no permissions, don't display the result but an icon img = get_image('to_follow.png', width='16px', height='16px') item['before']['Result'] = img return result = analysis_brain.getResult capture_date = analysis_brain.getResultCaptureDate capture_date_str = self.ulocalized_time(capture_date, long_format=0) item['Result'] = result item['CaptureDate'] = capture_date_str item['result_captured'] = capture_date_str if self.is_analysis_edition_allowed(analysis_brain): item['allow_edit'].extend(['Remarks']) item['allow_edit'].extend(['Result']) # If this analysis has a predefined set of options as result, # tell the template that selection list (choices) must be # rendered instead of an input field for the introduction of # result. choices = analysis_brain.getResultOptions if choices: # N.B.we copy here the list to avoid persistent changes choices = copy(choices) # By default set empty as the default selected choice choices.insert(0, dict(ResultValue="", ResultText="")) item['choices']['Result'] = choices # Wake up the object only if necessary. If there is no result set, then # there is no need to go further with formatted result if not result: return # TODO: Performance, we wake-up the full object here full_obj = self.get_object(analysis_brain) formatted_result = full_obj.getFormattedResult(sciformat=int( self.scinot), decimalmark=self.dmk) item['formatted_result'] = formatted_result
def folder_item(self, obj, item, index): batch = api.get_object(obj) # Doctor doctor = get_field_value(batch, "Doctor", None) item["Doctor"] = doctor and doctor.Title() or "" item["replace"]["Doctor"] = doctor and get_link( api.get_url(doctor), doctor.Title()) # Onset Date onset = get_field_value(batch, "OnsetDate", None) item["OnsetDate"] = onset and self.listing.ulocalized_time(onset) or "" # Patient item["Patient"] = "" item["getPatientID"] = "" item["getClientPatientID"] = "" item["PatientAgeOnsetDate"] = "" patient = get_field_value(batch, "Patient", None) if patient: url = api.get_url(patient) item["Patient"] = patient.Title() item["replace"]["Patient"] = get_link(url, patient.Title()) item["getPatientID"] = patient.id item["replace"]["getPatientID"] = get_link(url, patient.id) pid = patient.getClientPatientID() pid_link = pid and get_link(url, pid) or "" item["getClientPatientID"] = pid or "" item["replace"]["getClientPatientID"] = pid_link dob = patient.getBirthDate() if onset and dob: try: age_ymd = get_age_ymd(patient.getBirthDate(), onset) item["replace"]["PatientAgeOnsetDate"] = age_ymd except: # Wrong date?? msg = _("Date of Birth or Case Onset Date are wrong") img = get_image("exclamation.png", title=msg) item["replace"]["PatientAgeOnsetDate"] = img # Display the internal/external icons, but only if the logged-in user # does not belong to an external client if not self.is_external_user: item["before"]["BatchID"] = get_client_aware_html_image(obj) return item
def render_remarks_tag(self, ar): """Renders a remarks image icon """ uid = api.get_uid(ar) url = ar.absolute_url() title = ar.Title() tooltip = _("Remarks of {}").format(title) # Note: The 'href' is picked up by the overlay handler, see # bika.lims.worksheet.coffee attrs = { "css_class": "slot-remarks", "title": tooltip, "uid": uid, "href": "{}/base_view".format(url), } return get_image("remarks_ico.png", **attrs)
def folderitem(self, obj, item, index): """Applies new properties to the item (Client) that is currently being rendered as a row in the list :param obj: client to be rendered as a row in the list :param item: dict representation of the client, suitable for the list :param index: current position of the item within the list :type obj: ATContentType/DexterityContentType :type item: dict :type index: int :return: the dict representation of the item :rtype: dict """ obj = api.get_object(obj) url = obj.absolute_url() title = obj.Title() item["replace"]["Title"] = get_link(url, value=title) instruments = obj.getInstruments() if instruments: links = map( lambda i: get_link(i.absolute_url(), i.Title()), instruments) item["replace"]["Instrument"] = ", ".join(links) else: item["Instrument"] = "" calculation = obj.getCalculation() if calculation: title = calculation.Title() url = calculation.absolute_url() item["Calculation"] = title item["replace"]["Calculation"] = get_link(url, value=title) else: item["Calculation"] = "" manual_entry_of_results_allowed = obj.isManualEntryOfResults() item["ManualEntry"] = manual_entry_of_results_allowed item["replace"]["ManualEntry"] = " " if manual_entry_of_results_allowed: item["replace"]["ManualEntry"] = get_image("ok.png") return item
def folderitem(self, obj, item, index): """Augment folder listing item with additional data """ obj = api.get_object(obj) url = item.get("url") title = item.get("Title") item["replace"]["Title"] = get_link(url, value=title) item["getDate"] = self.localize_date(obj.getDate()) item["getValidFrom"] = self.localize_date(obj.getValidFrom()) item["getValidTo"] = self.localize_date(obj.getValidTo()) if obj.getInternal() is True: item["replace"]["getAgency"] = "" item["state_class"] = "%s %s" % \ (item["state_class"], "internalcertificate") item["getDocument"] = "" item["replace"]["getDocument"] = "" doc = self.get_document(obj) if doc and doc.get_size() > 0: filename = doc.filename download_url = "{}/at_download/Document".format(url) anchor = get_link(download_url, filename) item["getDocument"] = filename item["replace"]["getDocument"] = anchor # Latest valid certificate if obj == self.latest_certificate: item["state_class"] = "state-published" # Valid certificate elif obj in self.valid_certificates: item["state_class"] = "state-valid state-published" # Invalid certificates else: img = get_image("exclamation.png", title=t(_("Out of date"))) item["replace"]["getValidTo"] = "%s %s" % (item["getValidTo"], img) item["state_class"] = "state-invalid" return item
def _folder_item_remarks(self, analysis_brain, item): """Renders the Remarks field for the passed in analysis and if the edition of the analysis is permitted, adds a button to toggle the visibility of remarks field :param analysis_brain: Brain that represents an analysis :param item: analysis' dictionary counterpart that represents a row""" item['Remarks'] = analysis_brain.getRemarks if not self.is_analysis_edition_allowed(analysis_brain): # Edition not allowed, do not add the remarks toggle button, the # remarks field will be displayed without the option to hide it return if not self.context.bika_setup.getEnableAnalysisRemarks(): # Remarks not enabled in Setup, so don't display the balloon button return # Analysis can be edited. Add the remarks toggle button title = t(_("Add Remark")) img = get_image('comment_ico.png', title=title) kwargs = {'class': "add-remark"} anchor = get_link('#', img, **kwargs) self._append_html_element(item, 'Service', anchor, after=False)
def get_slot_header_data(self, obj): """Prepare the data for the slot header template """ item_obj = None item_title = "" item_url = "" item_img = "" item_img_url = "" item_img_text = "" additional_item_icons = [] parent_obj = None parent_title = "" parent_url = "" parent_img = "" parent_img_text = "" additional_parent_icons = [] sample_type_obj = None sample_type_title = "" sample_type_url = "" sample_type_img = "" sample_type_img_text = "" if IDuplicateAnalysis.providedBy(obj): # item request = obj.getRequest() item_obj = request item_title = api.get_id(request) item_url = api.get_url(request) item_img = "duplicate.png" item_img_url = api.get_url(request) item_img_text = t(_("Duplicate")) # additional item icons additional_item_icons.append(self.render_remarks_tag(request)) # parent client = request.getClient() parent_obj = client parent_title = api.get_title(client) parent_url = api.get_url(client) parent_img = "client.png" parent_img_text = t(_("Client")) # sample type sample_type = request.getSampleType() sample_type_title = request.getSampleTypeTitle() sample_type_url = api.get_url(sample_type) sample_type_img = "sampletype.png" sample_type_img_text = t(_("Sample Type")) elif IReferenceAnalysis.providedBy(obj): # item sample = obj.getSample() item_obj = sample item_title = api.get_id(sample) item_url = api.get_url(sample) item_img_url = api.get_url(sample) item_img = "control.png" item_img_text = t(_("Control")) if obj.getReferenceType() == "b": item_img = "blank.png" item_img_text = t(_("Blank")) # parent supplier = obj.getSupplier() parent_obj = supplier parent_title = api.get_title(supplier) parent_url = api.get_url(supplier) parent_img = "supplier.png" parent_img_text = t(_("Supplier")) elif IRoutineAnalysis.providedBy(obj): # item request = obj.getRequest() item_obj = request item_title = api.get_id(request) item_url = api.get_url(request) item_img = "sample.png" item_img_url = api.get_url(request) item_img_text = t(_("Sample")) # additional item icons additional_item_icons.append(self.render_remarks_tag(request)) # parent client = obj.getClient() parent_obj = client parent_title = api.get_title(client) parent_url = api.get_url(client) parent_img = "client.png" parent_img_text = t(_("Client")) # sample type client_ref = request.getClientReference() client_sid = request.getClientSampleID() tokens = filter(None, [client_ref, client_sid]) sample_type_title = ' / '.join(tokens) sample_type = obj.getSampleType() sample_type_img = "sampletype.png" sample_type_img_text = t(_("Tank / Blend ID")) return { # item "item_obj": item_obj, "item_title": item_title, "item_url": item_url, "item_img": get_image(item_img, title=item_img_text), "item_img_url": item_img_url, "additional_item_icons": additional_item_icons, # parent "parent_obj": parent_obj, "parent_title": parent_title, "parent_url": parent_url, "parent_img": get_image(parent_img, title=parent_img_text), "additional_parent_icons": additional_parent_icons, # sample type "sample_type_obj": sample_type_obj, "sample_type_title": sample_type_title, "sample_type_url": sample_type_url, "sample_type_img": get_image(sample_type_img, title=sample_type_img_text), }
def __init__(self, context, request): super(AnalysesView, self).__init__(context, request) self.context = context self.request = request self.analyst = None self.instrument = None self.contentFilter = { "getWorksheetUID": api.get_uid(context), "sort_on": "sortable_title", } self.icon = "{}/{}".format( self.portal_url, "++resource++bika.lims.images/worksheet_big.png") self.allow_edit = True self.show_categories = False self.expand_all_categories = False self.show_search = False self.bika_setup = api.get_bika_setup() self.uids_strpositions = self.get_uids_strpositions() self.items_rowspans = dict() self.columns = collections.OrderedDict(( ("Pos", { "sortable": False, "title": _("Position") }), ("Service", { "sortable": False, "title": _("Analysis") }), ("Method", { "sortable": False, "ajax": True, "title": _("Method") }), ("Instrument", { "sortable": False, "ajax": True, "title": _("Instrument") }), ("DetectionLimitOperand", { "title": _("DL"), "sortable": False, "ajax": True, "autosave": True, "toggle": False }), ("Result", { "title": _("Result"), "ajax": True, "sortable": False }), ("retested", { "title": get_image("retested.png", title=t(_("Retested"))), "toggle": False, "type": "boolean" }), ("Specification", { "title": _("Specification"), "sortable": False }), ("Uncertainty", { "sortable": False, "title": _("+-") }), ("DueDate", { "sortable": False, "title": _("Due Date") }), ("state_title", { "sortable": False, "title": _("State") }), ("Attachments", { "sortable": False, "title": _("Attachments") }), )) # Inject Remarks column for listing if self.is_analysis_remarks_enabled(): self.columns["Remarks"] = { "title": "Remarks", "ajax": True, "toggle": False, "sortable": False, "type": "remarks" } self.review_states = [ { "id": "default", "title": _("All"), "contentFilter": {}, "columns": self.columns.keys(), }, ]
def folderitem(self, obj, item, index): """Service triggered each time an item is iterated in folderitems. The use of this service prevents the extra-loops in child objects. :obj: the instance of the class to be foldered :item: dict containing the properties of the object to be used by the template :index: current index of the item """ # ensure we have an object and not a brain obj = api.get_object(obj) uid = api.get_uid(obj) # settings for this analysis service_settings = self.context.getAnalysisServiceSettings(uid) hidden = service_settings.get("hidden", obj.getHidden()) # get the category category = obj.getCategoryTitle() item["category"] = category if category not in self.categories: self.categories.append(category) price = obj.getPrice() keyword = obj.getKeyword() if uid in self.analyses: analysis = self.analyses[uid] # Might differ from the service keyword keyword = analysis.getKeyword() # Mark the row as disabled if the analysis has been submitted item["disabled"] = ISubmitted.providedBy(analysis) # get the hidden status of the analysis hidden = analysis.getHidden() # get the price of the analysis price = analysis.getPrice() # get the specification of this object rr = self.get_results_range() spec = rr.get(keyword, ResultsRangeDict()) item["Title"] = obj.Title() item["Unit"] = obj.getUnit() item["Price"] = price item["before"]["Price"] = self.get_currency_symbol() item["allow_edit"] = self.get_editable_columns(obj) item["selected"] = uid in self.selected item["min"] = str(spec.get("min", "")) item["max"] = str(spec.get("max", "")) item["warn_min"] = str(spec.get("warn_min", "")) item["warn_max"] = str(spec.get("warn_max", "")) item["Hidden"] = hidden # Append info link before the service # see: bika.lims.site.coffee for the attached event handler item["before"]["Title"] = get_link( "analysisservice_info?service_uid={}".format(uid), value="<span class='glyphicon glyphicon-info-sign'></span>", css_class="service_info") # Icons after_icons = "" if obj.getAccredited(): after_icons += get_image("accredited.png", title=t(_("Accredited"))) if obj.getAttachmentOption() == "r": after_icons += get_image("attach_reqd.png", title=t(_("Attachment required"))) if obj.getAttachmentOption() == "n": after_icons += get_image("attach_no.png", title=t(_('Attachment not permitted'))) if after_icons: item["after"]["Title"] = after_icons return item
def folderitem(self, obj, item, index): # Additional info from AnalysisRequest to be added in the item # generated by default by bikalisting. # Call the folderitem method from the base class item = super(SamplesView, self).folderitem(obj, item, index) if not item: return None item["Creator"] = self.user_fullname(obj.Creator) # If we redirect from the folderitems view we should check if the # user has permissions to medify the element or not. priority_sort_key = obj.getPrioritySortkey if not priority_sort_key: # Default priority is Medium = 3. # The format of PrioritySortKey is <priority>.<created> priority_sort_key = "3.%s" % obj.created.ISO8601() priority = priority_sort_key.split(".")[0] priority_text = PRIORITIES.getValue(priority) priority_div = """<div class="priority-ico priority-%s"> <span class="notext">%s</span><div> """ item["replace"]["Priority"] = priority_div % (priority, priority_text) item["replace"]["getProfilesTitle"] = obj.getProfilesTitleStr analysesnum = obj.getAnalysesNum if analysesnum: num_verified = str(analysesnum[0]) num_total = str(analysesnum[1]) item["getAnalysesNum"] = "{0}/{1}".format(num_verified, num_total) else: item["getAnalysesNum"] = "" # Progress progress_perc = obj.getProgress item["Progress"] = progress_perc item["replace"]["Progress"] = get_progress_bar_html(progress_perc) item["BatchID"] = obj.getBatchID if obj.getBatchID: item['replace']['BatchID'] = "<a href='%s'>%s</a>" % \ (obj.getBatchURL, obj.getBatchID) # TODO: SubGroup ??? # val = obj.Schema().getField('SubGroup').get(obj) # item['SubGroup'] = val.Title() if val else '' item["SamplingDate"] = self.str_date(obj.getSamplingDate) item["getDateReceived"] = self.str_date(obj.getDateReceived) item["getDueDate"] = self.str_date(obj.getDueDate) item["getDatePublished"] = self.str_date(obj.getDatePublished) item["getDateVerified"] = self.str_date(obj.getDateVerified) if self.is_printing_workflow_enabled: item["Printed"] = "" printed = obj.getPrinted if hasattr(obj, "getPrinted") else "0" print_icon = "" if printed == "0": print_icon = get_image("delete.png", title=t(_("Not printed yet"))) elif printed == "1": print_icon = get_image("ok.png", title=t(_("Printed"))) elif printed == "2": print_icon = get_image( "exclamation.png", title=t(_("Republished after last print"))) item["after"]["Printed"] = print_icon item["SamplingDeviation"] = obj.getSamplingDeviationTitle item["getStorageLocation"] = obj.getStorageLocationTitle after_icons = "" if obj.assigned_state == 'assigned': after_icons += get_image("worksheet.png", title=t(_("All analyses assigned"))) if item["review_state"] == 'invalid': after_icons += get_image("delete.png", title=t(_("Results have been withdrawn"))) due_date = obj.getDueDate if due_date and due_date < (obj.getDatePublished or DateTime()): due_date_str = self.ulocalized_time(due_date) img_title = "{}: {}".format(t(_("Late Analyses")), due_date_str) after_icons += get_image("late.png", title=img_title) if obj.getSamplingDate and obj.getSamplingDate > DateTime(): after_icons += get_image("calendar.png", title=t(_("Future dated sample"))) if obj.getInvoiceExclude: after_icons += get_image("invoice_exclude.png", title=t(_("Exclude from invoice"))) if obj.getHazardous: after_icons += get_image("hazardous.png", title=t(_("Hazardous"))) if obj.getInternalUse: after_icons += get_image("locked.png", title=t(_("Internal use"))) if after_icons: item['after']['getId'] = after_icons item['Created'] = self.ulocalized_time(obj.created, long_format=1) if obj.getContactUID: item['ClientContact'] = obj.getContactFullName item['replace']['ClientContact'] = "<a href='%s'>%s</a>" % \ (obj.getContactURL, obj.getContactFullName) else: item["ClientContact"] = "" # TODO-performance: If SamplingWorkflowEnabled, we have to get the # full object to check the user permissions, so far this is # a performance hit. if obj.getSamplingWorkflowEnabled: # We don't do anything with Sampling Date. # User can modify Sampling date # inside AR view. In this listing view, # we only let the user to edit Date Sampled # and Sampler if he wants to make 'sample' transaction. if not obj.getDateSampled: datesampled = self.ulocalized_time( DateTime(), long_format=True) item["class"]["getDateSampled"] = "provisional" else: datesampled = self.ulocalized_time(obj.getDateSampled, long_format=True) sampler = obj.getSampler if sampler: item["replace"]["getSampler"] = obj.getSamplerFullName if "Sampler" in self.roles and not sampler: sampler = self.member.id item["class"]["getSampler"] = "provisional" # sampling workflow - inline edits for Sampler and Date Sampled if item["review_state"] == 'to_be_sampled': # We need to get the full object in order to check # the permissions full_object = obj.getObject() checkPermission = \ self.context.portal_membership.checkPermission # TODO Do we really need this check? if checkPermission(TransitionSampleSample, full_object): item["required"] = ["getSampler", "getDateSampled"] item["allow_edit"] = ["getSampler", "getDateSampled"] # TODO-performance: hit performance while getting the # sample object... # TODO Can LabManagers be a Sampler?! samplers = getUsers(full_object, ["Sampler", ]) username = self.member.getUserName() users = [({ "ResultValue": u, "ResultText": samplers.getValue(u)}) for u in samplers] item['choices'] = {'getSampler': users} Sampler = sampler and sampler or \ (username in samplers.keys() and username) or '' sampler = Sampler else: datesampled = self.ulocalized_time(obj.getDateSampled, long_format=True) sampler = obj.getSamplerFullName if obj.getSampler else '' else: datesampled = self.ulocalized_time(obj.getDateSampled, long_format=True) sampler = "" item["getDateSampled"] = datesampled item["getSampler"] = sampler # These don't exist on ARs # XXX This should be a list of preservers... item["getPreserver"] = "" item["getDatePreserved"] = "" # Assign parent and children partitions of this sample if self.show_partitions: item["parent"] = obj.getRawParentAnalysisRequest item["children"] = obj.getDescendantsUIDs or [] return item
def __init__(self, context, request): super(SamplesView, self).__init__(context, request) self.catalog = CATALOG_ANALYSIS_REQUEST_LISTING self.contentFilter = { "sort_on": "created", "sort_order": "descending", "isRootAncestor": True, # only root ancestors } self.title = self.context.translate(_("Samples")) self.description = "" self.show_select_column = True self.form_id = "samples" self.context_actions = {} self.icon = "{}{}".format( self.portal_url, "/senaite_theme/icon/sample") self.url = api.get_url(self.context) # Toggle some columns if the sampling workflow is enabled sampling_enabled = api.get_setup().getSamplingWorkflowEnabled() self.columns = collections.OrderedDict(( ("Priority", { "title": "", "index": "getPrioritySortkey", "sortable": True, }), ("Progress", { "title": "Progress", "index": "getProgress", "sortable": True, "toggle": True}), ("getId", { "title": _("Sample ID"), "attr": "getId", "replace_url": "getURL", "index": "getId"}), ("getClientOrderNumber", { "title": _("Client Order"), "sortable": True, "toggle": False}), ("Creator", { "title": _("Creator"), "index": "getCreatorFullName", "sortable": True, "toggle": True}), ("Created", { "title": _("Date Registered"), "index": "created", "toggle": False}), ("SamplingDate", { "title": _("Expected Sampling Date"), "index": "getSamplingDate", "toggle": sampling_enabled}), ("getDateSampled", { "title": _("Date Sampled"), "toggle": True, "input_class": "datetimepicker_nofuture", "input_width": "10"}), ("getDatePreserved", { "title": _("Date Preserved"), "toggle": False, "input_class": "datetimepicker_nofuture", "input_width": "10", "sortable": False}), # no datesort without index ("getDateReceived", { "title": _("Date Received"), "toggle": False}), ("getDueDate", { "title": _("Due Date"), "toggle": False}), ("getDateVerified", { "title": _("Date Verified"), "input_width": "10", "toggle": False}), ("getDatePublished", { "title": _("Date Published"), "toggle": False}), ("BatchID", { "title": _("SDG ID"), "index": "getBatchID", "sortable": True, "toggle": False}), ("Client", { "title": _("Client"), "index": "getClientTitle", "attr": "getClientTitle", "replace_url": "getClientURL", "toggle": True}), ("ClientID", { "title": _("Client ID"), "index": "getClientID", "attr": "getClientID", "replace_url": "getClientURL", "toggle": True}), ("Province", { "title": _("Province"), "sortable": True, "index": "getProvince", "attr": "getProvince", "toggle": False}), ("District", { "title": _("District"), "sortable": True, "index": "getDistrict", "attr": "getDistrict", "toggle": False}), ("getClientReference", { "title": _("Client Ref"), "sortable": True, "index": "getClientReference", "toggle": False}), ("getClientSampleID", { "title": _("Client SID"), "toggle": False}), ("ClientContact", { "title": _("Contact"), "sortable": True, "index": "getContactFullName", "toggle": False}), ("getSampleTypeTitle", { "title": _("Sample Type"), "sortable": True, "toggle": True}), ("getSamplePointTitle", { "title": _("Sample Point"), "sortable": True, "index": "getSamplePointTitle", "toggle": False}), ("getStorageLocation", { "title": _("Storage Location"), "sortable": True, "index": "getStorageLocationTitle", "toggle": False}), ("SamplingDeviation", { "title": _("Sampling Deviation"), "sortable": True, "index": "getSamplingDeviationTitle", "toggle": False}), ("getSampler", { "title": _("Sampler"), "toggle": sampling_enabled}), ("getPreserver", { "title": _("Preserver"), "sortable": False, "toggle": False}), ("getProfilesTitle", { "title": _("Profile"), "sortable": True, "index": "getProfilesTitle", "toggle": False}), ("getAnalysesNum", { "title": _("Number of Analyses"), "sortable": True, "index": "getAnalysesNum", "toggle": False}), ("getTemplateTitle", { "title": _("Template"), "sortable": True, "index": "getTemplateTitle", "toggle": False}), ("Printed", { "title": _("Printed"), "sortable": False, "index": "getPrinted", "toggle": False}), ("state_title", { "title": _("State"), "sortable": True, "index": "review_state"}), )) # custom print transition print_stickers = { "id": "print_stickers", "title": _("Print stickers"), "url": "{}/workflow_action?action=print_stickers".format(self.url) } self.review_states = [ { "id": "default", "title": _("Active"), "contentFilter": { "review_state": ( "sample_registered", "scheduled_sampling", "to_be_sampled", "sample_due", "sample_received", "to_be_preserved", "to_be_verified", "verified", ), "sort_on": "created", "sort_order": "descending", }, "custom_transitions": [print_stickers], "columns": self.columns.keys(), }, { "id": "to_be_sampled", "title": _("To Be Sampled"), "contentFilter": { "review_state": ("to_be_sampled",), "sort_on": "created", "sort_order": "descending"}, "custom_transitions": [print_stickers], "columns": self.columns.keys() }, { "id": "to_be_preserved", "title": _("To Be Preserved"), "contentFilter": { "review_state": ("to_be_preserved",), "sort_on": "created", "sort_order": "descending", }, "custom_transitions": [print_stickers], "columns": self.columns.keys(), }, { "id": "scheduled_sampling", "title": _("Scheduled sampling"), "contentFilter": { "review_state": ("scheduled_sampling",), "sort_on": "created", "sort_order": "descending", }, "custom_transitions": [print_stickers], "columns": self.columns.keys(), }, { "id": "sample_due", "title": _("Due"), "contentFilter": { "review_state": ( "to_be_sampled", "to_be_preserved", "sample_due"), "sort_on": "created", "sort_order": "descending"}, "custom_transitions": [print_stickers], "columns": self.columns.keys(), }, { "id": "sample_received", "title": _("Received"), "contentFilter": { "review_state": "sample_received", "sort_on": "created", "sort_order": "descending", }, "custom_transitions": [print_stickers], "columns": self.columns.keys(), }, { "id": "to_be_verified", "title": _("To be verified"), "contentFilter": { "review_state": "to_be_verified", "sort_on": "created", "sort_order": "descending", }, "custom_transitions": [print_stickers], "columns": self.columns.keys(), }, { "id": "verified", "title": _("Verified"), "contentFilter": { "review_state": "verified", "sort_on": "created", "sort_order": "descending", }, "custom_transitions": [print_stickers], "columns": self.columns.keys(), }, { "id": "published", "title": _("Published"), "contentFilter": { "review_state": ("published"), "sort_on": "created", "sort_order": "descending", }, "custom_transitions": [], "columns": self.columns.keys(), }, { "id": "dispatched", "title": _("Dispatched"), "flat_listing": True, "confirm_transitions": ["restore"], "contentFilter": { "review_state": ("dispatched"), "sort_on": "created", "sort_order": "descending", }, "custom_transitions": [], "columns": self.columns.keys(), }, { "id": "cancelled", "title": _("Cancelled"), "contentFilter": { "review_state": "cancelled", "sort_on": "created", "sort_order": "descending", }, "custom_transitions": [], "columns": self.columns.keys(), }, { "id": "invalid", "title": _("Invalid"), "contentFilter": { "review_state": "invalid", "sort_on": "created", "sort_order": "descending", }, "custom_transitions": [print_stickers], "columns": self.columns.keys(), }, { "id": "all", "title": _("All"), "contentFilter": { "sort_on": "created", "sort_order": "descending", }, "custom_transitions": [print_stickers], "columns": self.columns.keys(), }, { "id": "rejected", "title": _("Rejected"), "contentFilter": { "review_state": "rejected", "sort_on": "created", "sort_order": "descending", }, "custom_transitions": [print_stickers], "columns": self.columns.keys(), }, { "id": "assigned", "title": get_image("assigned.png", title=t(_("Assigned"))), "contentFilter": { "assigned_state": "assigned", "review_state": ("sample_received",), "sort_on": "created", "sort_order": "descending", }, "custom_transitions": [print_stickers], "columns": self.columns.keys(), }, { "id": "unassigned", "title": get_image("unassigned.png", title=t(_("Unsassigned"))), "contentFilter": { "assigned_state": "unassigned", "review_state": ( "sample_received", ), "sort_on": "created", "sort_order": "descending", }, "custom_transitions": [print_stickers], "columns": self.columns.keys(), }, { "id": "late", "title": get_image("late.png", title=t(_("Late"))), "contentFilter": { # Query only for unpublished ARs that are late "review_state": ( "sample_received", "to_be_verified", "verified", ), "getDueDate": { "query": DateTime(), "range": "max", }, "sort_on": "created", "sort_order": "descending", }, "custom_transitions": [print_stickers], "columns": self.columns.keys(), } ]
def folderitem(self, obj, item, index): """Service triggered each time an item is iterated in folderitems. The use of this service prevents the extra-loops in child objects. :obj: the instance of the class to be foldered :item: dict containing the properties of the object to be used by the template :index: current index of the item """ # ensure we have an object and not a brain obj = api.get_object(obj) url = api.get_url(obj) title = api.get_title(obj) keyword = obj.getKeyword() # dynamic analysisspecs dspecs = self.get_dynamic_analysisspecs() dspec = dspecs.get(keyword) # show the dynamic specification icon next to the Keyword if dspec: item["before"]["Keyword"] = get_image( "dynamic_analysisspec.png", title=_( "Found Dynamic Analysis Specification for '{}' in '{}'". format(keyword, self.dynamic_spec.Title()))) # get the category if self.show_categories_enabled(): category = obj.getCategoryTitle() if category not in self.categories: self.categories.append(category) item["category"] = category item["Title"] = title item["replace"]["Title"] = get_link(url, value=title) item["choices"]["min_operator"] = self.min_operator_choices item["choices"]["max_operator"] = self.max_operator_choices item["allow_edit"] = self.get_editable_columns() item["required"] = self.get_required_columns() spec = self.specification.get(keyword, {}) item["selected"] = spec and True or False item["min_operator"] = spec.get("min_operator", "geq") item["min"] = spec.get("min", "") item["max_operator"] = spec.get("max_operator", "leq") item["max"] = spec.get("max", "") item["warn_min"] = spec.get("warn_min", "") item["warn_max"] = spec.get("warn_max", "") item["hidemin"] = spec.get("hidemin", "") item["hidemax"] = spec.get("hidemax", "") item["rangecomment"] = spec.get("rangecomment", "") # Add methods methods = obj.getMethods() if methods: links = map( lambda m: get_link( m.absolute_url(), value=m.Title(), css_class="link"), methods) item["replace"]["Methods"] = ", ".join(links) else: item["methods"] = "" # Icons after_icons = "" if obj.getAccredited(): after_icons += get_image("accredited.png", title=_("Accredited")) if obj.getAttachmentOption() == "r": after_icons += get_image("attach_reqd.png", title=_("Attachment required")) if obj.getAttachmentOption() == "n": after_icons += get_image("attach_no.png", title=_("Attachment not permitted")) if after_icons: item["after"]["Title"] = after_icons return item
def __init__(self, context, request): super(AnalysisRequestsView, self).__init__(context, request) # hide the right column request.set("disable_plone.rightcolumn", 1) # hide the editable border if self.context.portal_type == "AnalysisRequestsFolder": self.request.set("disable_border", 1) # catalog used for the query self.catalog = CATALOG_ANALYSIS_REQUEST_LISTING self.contentFilter = { "sort_on": "created", "sort_order": "descending", "isRootAncestor": True, # only root ancestors } self.context_actions = {} self.allow_edit = True self.show_select_row = False self.show_select_column = True self.form_id = "analysisrequests" ar_image_path = "/++resource++bika.lims.images/sample_big.png" self.icon = "{}{}".format(self.portal_url, ar_image_path) self.title = self.context.translate(_("Samples")) self.description = "" SamplingWorkflowEnabled = \ self.context.bika_setup.getSamplingWorkflowEnabled() self.columns = collections.OrderedDict(( ("Priority", { "title": "", "index": "getPrioritySortkey", "sortable": True, }), ("Progress", { "title": "Progress", "sortable": False, "toggle": True }), ("getId", { "title": _("Sample ID"), "attr": "getId", "replace_url": "getURL", "index": "getId" }), ("getClientOrderNumber", { "title": _("Client Order"), "sortable": True, "toggle": False }), ("Creator", { "title": _("Creator"), "index": "getCreatorFullName", "sortable": True, "toggle": True }), ("Created", { "title": _("Date Registered"), "index": "created", "toggle": False }), ("SamplingDate", { "title": _("Expected Sampling Date"), "index": "getSamplingDate", "toggle": SamplingWorkflowEnabled }), ("getDateSampled", { "title": _("Date Sampled"), "toggle": True, "input_class": "datetimepicker_nofuture", "input_width": "10" }), ("getDatePreserved", { "title": _("Date Preserved"), "toggle": False, "input_class": "datetimepicker_nofuture", "input_width": "10", "sortable": False }), # no datesort without index ("getDateReceived", { "title": _("Date Received"), "toggle": False }), ("getDueDate", { "title": _("Due Date"), "toggle": False }), ("getDateVerified", { "title": _("Date Verified"), "input_width": "10", "toggle": False }), ("getDatePublished", { "title": _("Date Published"), "toggle": False }), ("BatchID", { "title": _("Batch ID"), "index": "getBatchID", "sortable": True, "toggle": False }), ("Client", { "title": _("Client"), "index": "getClientTitle", "attr": "getClientTitle", "replace_url": "getClientURL", "toggle": True }), ("ClientID", { "title": _("Plant ID"), "index": "getClientID", "attr": "getClientID", "replace_url": "getClientURL", "toggle": True }), ("Province", { "title": _("Province"), "sortable": True, "index": "getProvince", "attr": "getProvince", "toggle": False }), ("District", { "title": _("District"), "sortable": True, "index": "getDistrict", "attr": "getDistrict", "toggle": False }), ("getClientReference", { "title": _("VesselTank"), "sortable": True, "index": "getClientReference", "toggle": False }), ("getClientSampleID", { "title": _("Blend Code"), "toggle": False }), ("ClientContact", { "title": _("Contact"), "sortable": True, "index": "getContactFullName", "toggle": False }), ("getSampleTypeTitle", { "title": _("Sample Type"), "sortable": True, "toggle": True }), ("getSamplePointTitle", { "title": _("Sample Point"), "sortable": True, "index": "getSamplePointTitle", "toggle": False }), ("getStorageLocation", { "title": _("Storage Location"), "sortable": True, "index": "getStorageLocationTitle", "toggle": False }), ("SamplingDeviation", { "title": _("Sampling Deviation"), "sortable": True, "index": "getSamplingDeviationTitle", "toggle": False }), ("getSampler", { "title": _("Sampler"), "toggle": SamplingWorkflowEnabled }), ("getPreserver", { "title": _("Preserver"), "sortable": False, "toggle": False }), ("getProfilesTitle", { "title": _("Profile"), "sortable": True, "index": "getProfilesTitle", "toggle": False }), ("getAnalysesNum", { "title": _("Number of Analyses"), "sortable": True, "index": "getAnalysesNum", "toggle": False }), ("getTemplateTitle", { "title": _("Template"), "sortable": True, "index": "getTemplateTitle", "toggle": False }), ("Printed", { "title": _("Printed"), "sortable": False, "index": "getPrinted", "toggle": False }), ("state_title", { "title": _("State"), "sortable": True, "index": "review_state" }), )) # custom print transition print_stickers = { "id": "print_stickers", "title": _("Print stickers"), "url": "workflow_action?action=print_stickers" } self.review_states = [ { "id": "default", "title": _("Active"), "contentFilter": { "review_state": ( "sample_registered", "scheduled_sampling", "to_be_sampled", "sample_due", "sample_received", "attachment_due", "to_be_preserved", "to_be_verified", "verified", ), "sort_on": "created", "sort_order": "descending", }, "custom_transitions": [print_stickers], "columns": self.columns.keys(), }, { "id": "to_be_sampled", "title": _("To Be Sampled"), "contentFilter": { "review_state": ("to_be_sampled", ), "sort_on": "created", "sort_order": "descending" }, "custom_transitions": [print_stickers], "columns": self.columns.keys() }, { "id": "to_be_preserved", "title": _("To Be Preserved"), "contentFilter": { "review_state": ("to_be_preserved", ), "sort_on": "created", "sort_order": "descending", }, "custom_transitions": [print_stickers], "columns": self.columns.keys(), }, { "id": "scheduled_sampling", "title": _("Scheduled sampling"), "contentFilter": { "review_state": ("scheduled_sampling", ), "sort_on": "created", "sort_order": "descending", }, "custom_transitions": [print_stickers], "columns": self.columns.keys(), }, { "id": "sample_due", "title": _("Due"), "contentFilter": { "review_state": ("to_be_sampled", "to_be_preserved", "sample_due"), "sort_on": "created", "sort_order": "descending" }, "custom_transitions": [print_stickers], "columns": self.columns.keys(), }, { "id": "sample_received", "title": _("Received"), "contentFilter": { "review_state": "sample_received", "sort_on": "created", "sort_order": "descending", }, "custom_transitions": [print_stickers], "columns": self.columns.keys(), }, { "id": "to_be_verified", "title": _("To be verified"), "contentFilter": { "review_state": "to_be_verified", "sort_on": "created", "sort_order": "descending", }, "custom_transitions": [print_stickers], "columns": self.columns.keys(), }, { "id": "verified", "title": _("Verified"), "contentFilter": { "review_state": "verified", "sort_on": "created", "sort_order": "descending", }, "custom_transitions": [print_stickers], "columns": self.columns.keys(), }, { "id": "published", "title": _("Published"), "contentFilter": { "review_state": ("published"), "sort_on": "created", "sort_order": "descending", }, "custom_transitions": [], "columns": self.columns.keys(), }, { "id": "cancelled", "title": _("Cancelled"), "contentFilter": { "review_state": "cancelled", "sort_on": "created", "sort_order": "descending", }, "custom_transitions": [], "columns": self.columns.keys(), }, { "id": "invalid", "title": _("Invalid"), "contentFilter": { "review_state": "invalid", "sort_on": "created", "sort_order": "descending", }, "custom_transitions": [print_stickers], "columns": self.columns.keys(), }, { "id": "all", "title": _("All"), "contentFilter": { "sort_on": "created", "sort_order": "descending", }, "custom_transitions": [print_stickers], "columns": self.columns.keys(), }, { "id": "rejected", "title": _("Rejected"), "contentFilter": { "review_state": "rejected", "sort_on": "created", "sort_order": "descending", }, "custom_transitions": [ { "id": "print_stickers", "title": _("Print stickers"), "url": "workflow_action?action=print_stickers" }, ], "columns": self.columns.keys(), }, { "id": "assigned", "title": get_image("assigned.png", title=t(_("Assigned"))), "contentFilter": { "assigned_state": "assigned", "review_state": ( "sample_received", "attachment_due", ), "sort_on": "created", "sort_order": "descending", }, "custom_transitions": [print_stickers], "columns": self.columns.keys(), }, { "id": "unassigned", "title": get_image("unassigned.png", title=t(_("Unsassigned"))), "contentFilter": { "assigned_state": "unassigned", "review_state": ( "sample_received", "attachment_due", ), "sort_on": "created", "sort_order": "descending", }, "custom_transitions": [print_stickers], "columns": self.columns.keys(), }, { "id": "late", "title": get_image("late.png", title=t(_("Late"))), "contentFilter": { # Query only for unpublished ARs that are late "review_state": ( "sample_received", "attachment_due", "to_be_verified", "verified", ), "getDueDate": { "query": DateTime(), "range": "max", }, "sort_on": "created", "sort_order": "descending", }, "custom_transitions": [print_stickers], "columns": self.columns.keys(), } ]