diff --git a/CHANGES.rst b/CHANGES.rst index c1fd570a30..129a08c2d2 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -7,6 +7,7 @@ Changelog **Added** +- #666 Added Unpublished filter in Analysis Requests list **Changed** @@ -23,6 +24,10 @@ Changelog **Fixed** +- #666 "Rejected" filter is displayed in AR lists regardless of Setup setting +- #666 "To be preserved" filter is displayed in AR lists regardless of Setup setting +- #666 "Scheduled sampling" is displayed in AR lists regardless of Setup setting +- #666 "To be sampled" filter is displayed in AR lists regardless of Setup setting - #664 Improved async transition loading and workflow button rendering in listing tables - #658 Worksheet listing view shows old- invalid Analysts - #663 AR Report Listing shows all Reports diff --git a/bika/lims/browser/analysisrequest/analysisrequests.py b/bika/lims/browser/analysisrequest/analysisrequests.py index a45518f0fc..d6607127e9 100644 --- a/bika/lims/browser/analysisrequest/analysisrequests.py +++ b/bika/lims/browser/analysisrequest/analysisrequests.py @@ -5,58 +5,64 @@ # Copyright 2018 by it's authors. # Some rights reserved. See LICENSE.rst, CONTRIBUTORS.rst. +import collections import json import traceback -from plone.api import user - from DateTime import DateTime -from Products.Archetypes import PloneMessageFactory as PMF -from Products.CMFCore.permissions import ModifyPortalContent -from Products.CMFCore.utils import getToolByName -from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile + from bika.lims import bikaMessageFactory as _ +from bika.lims import api from bika.lims import logger -from bika.lims.browser.analysisrequest.analysisrequests_filter_bar \ - import AnalysisRequestsBikaListingFilterBar +from bika.lims.browser.analysisrequest.analysisrequests_filter_bar import \ + AnalysisRequestsBikaListingFilterBar from bika.lims.browser.bika_listing import BikaListingView from bika.lims.catalog import CATALOG_ANALYSIS_REQUEST_LISTING from bika.lims.config import PRIORITIES -from bika.lims.permissions import SampleSample, ManageAnalysisRequests, \ - AddAnalysisRequest from bika.lims.permissions import Verify as VerifyPermission -from bika.lims.utils import getUsers -from bika.lims.utils import t +from bika.lims.permissions import (AddAnalysisRequest, ManageAnalysisRequests, + SampleSample) +from bika.lims.utils import getUsers, t from collective.taskqueue.interfaces import ITaskQueue +from plone.api import user from plone.app.layout.globals.interfaces import IViewView -from plone.protect import CheckAuthenticator -from plone.protect import PostOnly +from plone.protect import CheckAuthenticator, PostOnly +from Products.Archetypes import PloneMessageFactory as PMF +from Products.CMFCore.permissions import ModifyPortalContent +from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile from zope.component import queryUtility from zope.interface import implements class AnalysisRequestsView(BikaListingView): - """Base for all lists of ARs + """Listing View for all Analysis Requests in the System """ + implements(IViewView) + template = ViewPageTemplateFile("templates/analysisrequests.pt") ar_add = ViewPageTemplateFile("templates/ar_add.pt") - implements(IViewView) def __init__(self, context, request): super(AnalysisRequestsView, self).__init__(context, request) - request.set('disable_plone.rightcolumn', 1) - # Setting up the catalog and query dictionary + # 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': 'reverse', - 'path': {"query": "/", "level": 0}, - 'cancellation_state': 'active', - } - self.context_actions = {} + # see: https://docs.plone.org/develop/plone/searching_and_indexing/query.html#searching-for-content-within-a-folder + self.contentFilter = { + "sort_on": "created", + "sort_order": "descending", + "path": {"query": "/", "depth": 2}, + "cancellation_state": "active", + } - if self.context.portal_type == "AnalysisRequestsFolder": - self.request.set('disable_border', 1) + self.context_actions = {} if self.view_url.find("analysisrequests") == -1: self.view_url = self.view_url + "/analysisrequests" @@ -80,744 +86,531 @@ def __init__(self, context, request): self.context.bika_setup.\ getDisplayAdvancedFilterBarForAnalysisRequests() - self.columns = { - 'Priority': { - 'title': '', - 'index': 'getPrioritySortkey', - 'sortable': True, }, - 'Progress': { - 'title': 'Progress', - 'sortable': False, - 'toggle': True}, - 'getId': { - 'title': _('Request ID'), - 'attr': 'getId', - 'replace_url': 'getURL', - 'index': 'getId'}, - 'getClientOrderNumber': { - 'title': _('Client Order'), - 'sortable': True, - 'toggle': True}, - 'Creator': { - 'title': PMF('Creator'), - 'index': 'getCreatorFullName', - 'sortable': True, - 'toggle': True}, - 'Created': { - 'title': PMF('Date Created'), - 'index': 'created', - 'toggle': False}, - 'getSample': { - 'title': _("Sample"), - 'attr': 'getSampleID', - 'index': 'getSampleID', - 'replace_url': 'getSampleURL', - 'toggle': True, }, - 'BatchID': { - 'title': _("Batch ID"), - 'index': 'getBatchID', - 'sortable': True, - 'toggle': True}, - 'Client': { - 'title': _('Client'), - 'index': 'getClientTitle', - 'attr': 'getClientTitle', - 'replace_url': 'getClientURL', - 'toggle': True}, - 'Province': { - 'title': _('Province'), - 'sortable': True, - 'index': 'getProvince', - 'attr': 'getProvince', - 'toggle': True}, - 'District': { - 'title': _('District'), - 'sortable': True, - 'index': 'getDistrict', - 'attr': 'getDistrict', - 'toggle': True}, - 'getClientReference': { - 'title': _('Client Ref'), - 'sortable': True, - 'index': 'getClientReference', - 'toggle': True}, - 'getClientSampleID': { - 'title': _('Client SID'), - 'toggle': True}, - '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}, - # 'AdHoc': {'title': _('Ad-Hoc'), - # 'toggle': False}, - 'SamplingDate': { - 'title': _('Expected Sampling Date'), - 'index': 'getSamplingDate', - 'toggle': SamplingWorkflowEnabled}, - 'getDateSampled': { - 'title': _('Date Sampled'), - 'toggle': True, - 'input_class': 'datetimepicker_nofuture', - 'input_width': '10'}, - 'getDateVerified': { - 'title': _('Date Verified'), - 'input_width': '10'}, - 'getSampler': { - 'title': _('Sampler'), - 'toggle': SamplingWorkflowEnabled}, - 'getDatePreserved': { - 'title': _('Date Preserved'), - 'toggle': False, - 'input_class': 'datetimepicker_nofuture', - 'input_width': '10', - 'sortable': False}, # no datesort without index - 'getPreserver': { - 'title': _('Preserver'), - 'sortable': False, - 'toggle': False}, - 'getDateReceived': { - 'title': _('Date Received'), - 'toggle': False}, - 'getDatePublished': { - 'title': _('Date Published'), - 'toggle': False}, - 'state_title': { - 'title': _('State'), - 'sortable': True, - 'index': 'review_state'}, - '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}, + self.columns = collections.OrderedDict(( + ("Priority", { + "title": "", + "index": "getPrioritySortkey", + "sortable": True, }), + ("Progress", { + "title": "Progress", + "sortable": False, + "toggle": True}), + ("getId", { + "title": _("Request ID"), + "attr": "getId", + "replace_url": "getURL", + "index": "getId"}), + ("getClientOrderNumber", { + "title": _("Client Order"), + "sortable": True, + "toggle": True}), + ("Creator", { + "title": PMF("Creator"), + "index": "getCreatorFullName", + "sortable": True, + "toggle": True}), + ("Created", { + "title": PMF("Date Created"), + "index": "created", + "toggle": False}), + ("getSample", { + "title": _("Sample"), + "attr": "getSampleID", + "index": "getSampleID", + "replace_url": "getSampleURL", + "toggle": True, }), + ("BatchID", { + "title": _("Batch ID"), + "index": "getBatchID", + "sortable": True, + "toggle": True}), + ("Client", { + "title": _("Client"), + "index": "getClientTitle", + "attr": "getClientTitle", + "replace_url": "getClientURL", + "toggle": True}), + ("Province", { + "title": _("Province"), + "sortable": True, + "index": "getProvince", + "attr": "getProvince", + "toggle": True}), + ("District", { + "title": _("District"), + "sortable": True, + "index": "getDistrict", + "attr": "getDistrict", + "toggle": True}), + ("getClientReference", { + "title": _("Client Ref"), + "sortable": True, + "index": "getClientReference", + "toggle": True}), + ("getClientSampleID", { + "title": _("Client SID"), + "toggle": True}), + ("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}), + ("SamplingDate", { + "title": _("Expected Sampling Date"), + "index": "getSamplingDate", + "toggle": SamplingWorkflowEnabled}), + ("getDateSampled", { + "title": _("Date Sampled"), + "toggle": True, + "input_class": "datetimepicker_nofuture", + "input_width": "10"}), + ("getDateVerified", { + "title": _("Date Verified"), + "input_width": "10"}), + ("getSampler", { + "title": _("Sampler"), + "toggle": SamplingWorkflowEnabled}), + ("getDatePreserved", { + "title": _("Date Preserved"), + "toggle": False, + "input_class": "datetimepicker_nofuture", + "input_width": "10", + "sortable": False}), # no datesort without index + ("getPreserver", { + "title": _("Preserver"), + "sortable": False, + "toggle": False}), + ("getDateReceived", { + "title": _("Date Received"), + "toggle": False}), + ("getDatePublished", { + "title": _("Date Published"), + "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': {'sort_on': 'Created', - 'sort_order': 'reverse'}, - 'transitions': [{'id': 'sample'}, - {'id': 'preserve'}, - {'id': 'receive'}, - {'id': 'retract'}, - {'id': 'verify'}, - {'id': 'prepublish'}, - {'id': 'publish'}, - {'id': 'republish'}, - {'id': 'cancel'}, - {'id': 'reinstate'}], - 'custom_transitions': [{ - 'id': 'print_stickers', - 'title': _('Print stickers'), - 'url': 'workflow_action?action=print_stickers'}], - 'columns': ['Priority', - 'Progress', - 'getId', - 'getSample', - 'BatchID', - # 'SubGroup', - 'Client', - 'Province', - 'District', - 'Creator', - 'Created', - 'getClientOrderNumber', - 'getClientReference', - 'ClientContact', - 'getClientSampleID', - 'getProfilesTitle', - 'getTemplateTitle', - 'getSampleTypeTitle', - 'getSamplePointTitle', - 'getStorageLocation', - 'SamplingDeviation', - # 'AdHoc', - 'SamplingDate', - 'getDateSampled', - 'getSampler', - 'getDatePreserved', - 'getPreserver', - 'getDateReceived', - 'getAnalysesNum', - 'getDateVerified', - 'state_title']}, - {'id': 'to_be_sampled', - 'title': _('To Be Sampled'), - 'contentFilter': {'review_state': ('to_be_sampled',), - 'sort_on': 'Created', - 'sort_order': 'reverse'}, - 'transitions': [ - {'id': 'sample'}, - {'id': 'submit'}, - {'id': 'cancel'}, - ], - 'custom_transitions': [{ - 'id': 'print_stickers', - 'title': _('Print stickers'), - 'url': 'workflow_action?action=print_stickers'}], - 'columns': ['Priority', - 'getId', - 'getSample', - 'BatchID', - # 'SubGroup', - 'Client', - 'Province', - 'District', - 'getProfilesTitle', - 'getTemplateTitle', - 'Creator', - 'Created', - 'getClientOrderNumber', - 'getClientReference', - 'getClientSampleID', - 'ClientContact', - 'getDateSampled', - 'getSampler', - 'getDatePreserved', - 'getPreserver', - 'getSampleTypeTitle', - 'getSamplePointTitle', - 'getStorageLocation', - 'SamplingDeviation', - # 'AdHoc', - 'getAnalysesNum', - 'getDateVerified', - 'state_title']}, - {'id': 'to_be_preserved', - 'title': _('To Be Preserved'), - 'contentFilter': {'review_state': ('to_be_preserved',), - 'sort_on': 'Created', - 'sort_order': 'reverse'}, - 'transitions': [{'id': 'preserve'}, - {'id': 'cancel'}, - ], - 'custom_transitions': [{ - 'id': 'print_stickers', - 'title': _('Print stickers'), - 'url': 'workflow_action?action=print_stickers'}], - 'columns': ['Priority', - 'getId', - 'getSample', - 'BatchID', - # 'SubGroup', - 'Client', - 'getProfilesTitle', - 'getTemplateTitle', - 'Creator', - 'Created', - 'getClientOrderNumber', - 'getClientReference', - 'getClientSampleID', - 'ClientContact', - 'getDateSampled', - 'getSampler', - 'getDatePreserved', - 'getPreserver', - 'getSampleTypeTitle', - 'getSamplePointTitle', - 'getStorageLocation', - 'SamplingDeviation', - # 'AdHoc', - 'getAnalysesNum', - 'getDateVerified', - 'state_title']}, - {'id': 'scheduled_sampling', - 'title': _('Scheduled sampling'), - 'contentFilter': {'review_state': ('scheduled_sampling',), - 'sort_on': 'Created', - 'sort_order': 'reverse'}, - 'transitions': [{'id': 'sample'}, - {'id': 'cancel'}, - ], - 'custom_transitions': [{ - 'id': 'print_stickers', - 'title': _('Print stickers'), - 'url': 'workflow_action?action=print_stickers'}], - 'columns': ['Priority', - 'getId', - 'getSample', - 'BatchID', - # 'SubGroup', - 'Client', - 'Province', - 'District', - 'getProfilesTitle', - 'getTemplateTitle', - 'Creator', - 'Created', - 'getClientOrderNumber', - 'getClientReference', - 'getClientSampleID', - 'ClientContact', - 'getDateSampled', - 'getSampler', - 'getDatePreserved', - 'getPreserver', - 'getSampleTypeTitle', - 'getSamplePointTitle', - 'getStorageLocation', - 'SamplingDeviation', - # 'AdHoc', - 'getAnalysesNum', - 'getDateVerified', - 'state_title']}, - {'id': 'sample_due', - 'title': _('Due'), - 'contentFilter': {'review_state': ('to_be_sampled', - 'to_be_preserved', - 'sample_due'), - 'sort_on': 'Created', - 'sort_order': 'reverse'}, - 'transitions': [{'id': 'sample'}, - {'id': 'preserve'}, - {'id': 'receive'}, - {'id': 'cancel'}, - {'id': 'reinstate'}], - 'custom_transitions': [{ - 'id': 'print_stickers', - 'title': _('Print stickers'), - 'url': 'workflow_action?action=print_stickers'}], - 'columns': ['Priority', - 'getId', - 'getSample', - 'BatchID', - # 'SubGroup', - 'Client', - 'Province', - 'District', - 'getProfilesTitle', - 'getTemplateTitle', - 'Creator', - 'Created', - 'getClientOrderNumber', - 'getClientReference', - 'getClientSampleID', - 'ClientContact', - 'getDateSampled', - 'getSampler', - 'getDatePreserved', - 'getPreserver', - 'getSampleTypeTitle', - 'getSamplePointTitle', - 'getStorageLocation', - 'SamplingDeviation', - # 'AdHoc', - 'getAnalysesNum', - 'getDateVerified', - 'state_title']}, - {'id': 'sample_received', - 'title': _('Received'), - 'contentFilter': {'review_state': 'sample_received', - 'sort_on': 'Created', - 'sort_order': 'reverse'}, - 'transitions': [{'id': 'prepublish'}, - {'id': 'cancel'}, - {'id': 'reinstate'}], - 'custom_transitions': [{ - 'id': 'print_stickers', - 'title': _('Print stickers'), - 'url': 'workflow_action?action=print_stickers'}], - 'columns': ['Priority', - 'getId', - 'getSample', - 'BatchID', - # 'SubGroup', - 'Client', - 'Province', - 'District', - 'getProfilesTitle', - 'getTemplateTitle', - 'Creator', - 'Created', - 'getClientOrderNumber', - 'getClientReference', - 'getClientSampleID', - 'ClientContact', - 'getSampleTypeTitle', - 'getSamplePointTitle', - 'getStorageLocation', - 'SamplingDeviation', - # 'AdHoc', - 'getDateSampled', - 'getSampler', - 'getDatePreserved', - 'getPreserver', - 'getAnalysesNum', - 'getDateVerified', - 'getDateReceived']}, - {'id': 'to_be_verified', - 'title': _('To be verified'), - 'contentFilter': {'review_state': 'to_be_verified', - 'sort_on': 'Created', - 'sort_order': 'reverse'}, - 'transitions': [{'id': 'retract'}, - {'id': 'verify'}, - {'id': 'prepublish'}, - {'id': 'cancel'}, - {'id': 'reinstate'}], - 'custom_transitions': [{ - 'id': 'print_stickers', - 'title': _('Print stickers'), - 'url': 'workflow_action?action=print_stickers'}], - 'columns': ['Priority', - 'getId', - 'getSample', - 'BatchID', - # 'SubGroup', - 'Client', - 'Province', - 'District', - 'getProfilesTitle', - 'getTemplateTitle', - 'Creator', - 'Created', - 'getClientOrderNumber', - 'getClientReference', - 'getClientSampleID', - 'ClientContact', - 'getSampleTypeTitle', - 'getSamplePointTitle', - 'getStorageLocation', - 'SamplingDeviation', - # 'AdHoc', - 'getDateSampled', - 'getSampler', - 'getDatePreserved', - 'getPreserver', - 'getAnalysesNum', - 'getDateVerified', - 'getDateReceived']}, - {'id': 'verified', - 'title': _('Verified'), - 'contentFilter': {'review_state': 'verified', - 'sort_on': 'Created', - 'sort_order': 'reverse'}, - 'transitions': [{'id': 'publish'}, - {'id': 'cancel'}, - ], - 'custom_transitions': [{ - 'id': 'print_stickers', - 'title': _('Print stickers'), - 'url': 'workflow_action?action=print_stickers'}], - 'columns': ['Priority', - 'getId', - 'getSample', - 'BatchID', - # 'SubGroup', - 'Client', - 'Province', - 'District', - 'getProfilesTitle', - 'getTemplateTitle', - 'Creator', - 'Created', - 'getClientOrderNumber', - 'getClientReference', - 'getClientSampleID', - 'ClientContact', - 'getSampleTypeTitle', - 'getSamplePointTitle', - 'getStorageLocation', - 'SamplingDeviation', - # 'AdHoc', - 'getDateSampled', - 'getSampler', - 'getDatePreserved', - 'getPreserver', - 'getAnalysesNum', - 'getDateVerified', - 'getDateReceived']}, - {'id': 'published', - 'title': _('Published'), - 'contentFilter': {'review_state': ('published', 'invalid'), - 'sort_on': 'Created', - 'sort_order': 'reverse'}, - 'transitions': [{'id': 'republish'}], - 'custom_transitions': [], - 'columns': ['Priority', - 'getId', - 'getSample', - 'BatchID', - # 'SubGroup', - 'Client', - 'Province', - 'District', - 'getProfilesTitle', - 'getTemplateTitle', - 'Creator', - 'Created', - 'getClientOrderNumber', - 'getClientReference', - 'getClientSampleID', - 'ClientContact', - 'getSampleTypeTitle', - 'getSamplePointTitle', - 'getStorageLocation', - 'SamplingDeviation', - # 'AdHoc', - 'getDateSampled', - 'getSampler', - 'getDatePreserved', - 'getPreserver', - 'getDateReceived', - 'getAnalysesNum', - 'getDateVerified', - 'Printed', - 'getDatePublished']}, - {'id': 'cancelled', - 'title': _('Cancelled'), - 'contentFilter': {'cancellation_state': 'cancelled', - 'review_state': ( - 'sample_registered', - 'to_be_sampled', - 'to_be_preserved', - 'sample_due', - 'sample_received', - 'to_be_verified', - 'attachment_due', - 'verified', - 'published'), - 'sort_on': 'Created', - 'sort_order': 'reverse'}, - 'transitions': [{'id': 'reinstate'}], - 'custom_transitions': [], - 'columns': ['getId', - 'getSample', - 'BatchID', - # 'SubGroup', - 'Client', - 'Province', - 'District', - 'getProfilesTitle', - 'getTemplateTitle', - 'Creator', - 'Created', - 'getClientOrderNumber', - 'getClientReference', - 'getClientSampleID', - 'ClientContact', - 'getSampleTypeTitle', - 'getSamplePointTitle', - 'getStorageLocation', - 'SamplingDeviation', - # 'AdHoc', - 'getDateSampled', - 'getSampler', - 'getDatePreserved', - 'getPreserver', - 'getDateReceived', - 'getDatePublished', - 'getAnalysesNum', - 'getDateVerified', - 'state_title']}, - {'id': 'invalid', - 'title': _('Invalid'), - 'contentFilter': {'review_state': 'invalid', - 'sort_on': 'Created', - 'sort_order': 'reverse'}, - 'transitions': [], - 'custom_transitions': [{ - 'id': 'print_stickers', - 'title': _('Print stickers'), - 'url': 'workflow_action?action=print_stickers'}], - 'columns': ['getId', - 'getSample', - 'BatchID', - # 'SubGroup', - 'Client', - 'Province', - 'District', - 'getProfilesTitle', - 'getTemplateTitle', - 'Creator', - 'Created', - 'getClientOrderNumber', - 'getClientReference', - 'getClientSampleID', - 'ClientContact', - 'getSampleTypeTitle', - 'getSamplePointTitle', - 'getStorageLocation', - 'SamplingDeviation', - # 'AdHoc', - 'getDateSampled', - 'getSampler', - 'getDatePreserved', - 'getPreserver', - 'getDateReceived', - 'getAnalysesNum', - 'getDateVerified', - 'getDatePublished']}, - {'id': 'assigned', - 'title': "" \ - % (t(_("Assigned")), self.portal_url), - 'contentFilter': {'assigned_state': 'assigned', - 'cancellation_state': 'active', - 'review_state': ('sample_received', - 'attachment_due',), - 'sort_on': 'Created', - 'sort_order': 'reverse'}, - 'transitions': [{'id': 'receive'}, - {'id': 'retract'}, - {'id': 'prepublish'}, - {'id': 'cancel'},], - 'custom_transitions': [{ - 'id': 'print_stickers', - 'title': _('Print stickers'), - 'url': 'workflow_action?action=print_stickers'}], - 'columns': ['Priority', - 'getId', - 'getSample', - 'BatchID', - # 'SubGroup', - 'Client', - 'Province', - 'District', - 'getProfilesTitle', - 'getTemplateTitle', - 'Creator', - 'Created', - 'getClientOrderNumber', - 'getClientReference', - 'getClientSampleID', - 'ClientContact', - 'getSampleTypeTitle', - 'getSamplePointTitle', - 'getStorageLocation', - 'SamplingDeviation', - # 'AdHoc', - 'getDateSampled', - 'getSampler', - 'getDatePreserved', - 'getPreserver', - 'getDateReceived', - 'getAnalysesNum', - 'getDateVerified', - 'state_title']}, - {'id': 'unassigned', - 'title': ""\ - % (t(_("Unassigned")), self.portal_url), - 'contentFilter': {'assigned_state': 'unassigned', - 'cancellation_state': 'active', - 'review_state': ('sample_received', - 'attachment_due',), - 'sort_on': 'Created', - 'sort_order': 'reverse'}, - 'transitions': [{'id': 'receive'}, - {'id': 'retract'}, - {'id': 'prepublish'}, - {'id': 'cancel'},], - 'custom_transitions': [{ - 'id': 'print_stickers', - 'title': _('Print stickers'), - 'url': 'workflow_action?action=print_stickers'}], - 'columns': ['Priority', - 'getId', - 'getSample', - 'BatchID', - # 'SubGroup', - 'Client', - 'Province', - 'District', - 'getProfilesTitle', - 'getTemplateTitle', - 'Creator', - 'Created', - 'getClientOrderNumber', - 'getClientReference', - 'getClientSampleID', - 'ClientContact', - 'getSampleTypeTitle', - 'getSamplePointTitle', - 'getStorageLocation', - 'SamplingDeviation', - # 'AdHoc', - 'SamplingDate', - 'getDateSampled', - 'getSampler', - 'getDatePreserved', - 'getPreserver', - 'getDateReceived', - 'getAnalysesNum', - 'getDateVerified', - 'state_title']}, - {'id': 'rejected', - 'title': _('Rejected'), - 'contentFilter': {'review_state': 'rejected', - 'sort_on': 'Created', - 'sort_order': 'reverse'}, - 'transitions': [], - 'custom_transitions': [{ - 'id': 'print_stickers', - 'title': _('Print stickers'), - 'url': 'workflow_action?action=print_stickers'}], - 'columns': ['getId', - 'getSample', - 'BatchID', - # 'SubGroup', - 'Client', - 'Province', - 'District', - 'getProfilesTitle', - 'getTemplateTitle', - 'Creator', - 'Created', - 'getClientOrderNumber', - 'getClientReference', - 'getClientSampleID', - 'ClientContact', - 'getSampleTypeTitle', - 'getSamplePointTitle', - 'getStorageLocation', - 'SamplingDeviation', - # 'AdHoc', - 'getDateSampled', - 'getSampler', - 'getDatePreserved', - 'getPreserver', - 'getDateReceived', - 'getDatePublished', - 'getAnalysesNum', - 'state_title']}, - ] + { + "id": "default", + "title": _("Active"), + "contentFilter": { + "sort_on": "created", + "sort_order": "descending", + }, + "transitions": [ + {"id": "sample"}, + {"id": "preserve"}, + {"id": "receive"}, + {"id": "retract"}, + {"id": "verify"}, + {"id": "prepublish"}, + {"id": "publish"}, + {"id": "republish"}, + {"id": "cancel"}, + {"id": "reinstate"}, + ], + "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"}, + "transitions": [ + {"id": "sample"}, + {"id": "submit"}, + {"id": "cancel"}, + ], + "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", + }, + "transitions": [ + {"id": "preserve"}, + {"id": "cancel"}, + ], + "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", + }, + "transitions": [ + {"id": "sample"}, + {"id": "cancel"}, + ], + "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"}, + "transitions": [ + {"id": "sample"}, + {"id": "preserve"}, + {"id": "receive"}, + {"id": "cancel"}, + {"id": "reinstate"}, + ], + "custom_transitions": [print_stickers], + "columns": self.columns.keys(), + }, { + "id": "sample_received", + "title": _("Received"), + "contentFilter": { + "review_state": "sample_received", + "sort_on": "created", + "sort_order": "descending", + }, + "transitions": [ + {"id": "prepublish"}, + {"id": "cancel"}, + {"id": "reinstate"}, + ], + "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", + }, + "transitions": [ + {"id": "retract"}, + {"id": "verify"}, + {"id": "prepublish"}, + {"id": "cancel"}, + {"id": "reinstate"}, + ], + "custom_transitions": [print_stickers], + "columns": self.columns.keys(), + }, { + "id": "verified", + "title": _("Verified"), + "contentFilter": { + "review_state": "verified", + "sort_on": "created", + "sort_order": "descending", + }, + "transitions": [ + {"id": "publish"}, + {"id": "cancel"}, + ], + "custom_transitions": [print_stickers], + "columns": self.columns.keys(), + }, { + "id": "published", + "title": _("Published"), + "contentFilter": { + "review_state": ("published", "invalid"), + "sort_on": "created", + "sort_order": "descending", + }, + "transitions": [ + {"id": "republish"}, + ], + "custom_transitions": [], + "columns": self.columns.keys(), + }, { + "id": "unpublished", + "title": _("Unpublished"), + "contentFilter": { + "cancellation_state": "active", + "review_state": ( + "sample_registered", + "to_be_sampled", + "to_be_preserved", + "sample_due", + "sample_received", + "to_be_verified", + "attachment_due", + "verified", + ), + "sort_on": "created", + "sort_order": "descending", + }, + "transitions": [ + {"id": "sample"}, + {"id": "preserve"}, + {"id": "receive"}, + {"id": "retract"}, + {"id": "verify"}, + {"id": "prepublish"}, + {"id": "publish"}, + {"id": "republish"}, + {"id": "cancel"}, + {"id": "reinstate"}, + ], + "custom_transitions": [print_stickers], + "columns": self.columns.keys(), + }, { + "id": "cancelled", + "title": _("Cancelled"), + "contentFilter": { + "cancellation_state": "cancelled", + "review_state": ( + "sample_registered", + "to_be_sampled", + "to_be_preserved", + "sample_due", + "sample_received", + "to_be_verified", + "attachment_due", + "verified", + "published", + ), + "sort_on": "created", + "sort_order": "descending", + }, + "transitions": [ + {"id": "reinstate"}, + ], + "custom_transitions": [], + "columns": self.columns.keys(), + }, { + "id": "invalid", + "title": _("Invalid"), + "contentFilter": { + "review_state": "invalid", + "sort_on": "created", + "sort_order": "descending", + }, + "transitions": [], + "custom_transitions": [print_stickers], + "columns": self.columns.keys(), + }, { + "id": "rejected", + "title": _("Rejected"), + "contentFilter": { + "review_state": "rejected", + "sort_on": "created", + "sort_order": "descending", + }, + "transitions": [], + "custom_transitions": [ + { + "id": "print_stickers", + "title": _("Print stickers"), + "url": "workflow_action?action=print_stickers"}, + ], + "columns": self.columns.keys(), + }, { + "id": "assigned", + "title": "" % ( + t(_("Assigned")), self.portal_url), + "contentFilter": { + "assigned_state": "assigned", + "cancellation_state": "active", + "review_state": ("sample_received", + "attachment_due",), + "sort_on": "created", + "sort_order": "descending", + }, + "transitions": [ + {"id": "receive"}, + {"id": "retract"}, + {"id": "prepublish"}, + {"id": "cancel"}, + ], + "custom_transitions": [print_stickers], + "columns": self.columns.keys(), + }, { + "id": "unassigned", + "title": "" % ( + t(_("Unassigned")), self.portal_url), + "contentFilter": { + "assigned_state": "unassigned", + "cancellation_state": "active", + "review_state": ( + "sample_received", + "attachment_due", + ), + "sort_on": "created", + "sort_order": "descending", + }, + "transitions": [ + {"id": "receive"}, + {"id": "retract"}, + {"id": "prepublish"}, + {"id": "cancel"}, + ], + "custom_transitions": [print_stickers], + "columns": self.columns.keys(), + }, + ] + + def update(self): + """Called before the listing renders + """ + super(AnalysisRequestsView, self).update() + + self.workflow = api.get_tool("portal_workflow") + self.member = self.mtool.getAuthenticatedMember() + self.roles = self.member.getRoles() + + setup = api.get_bika_setup() + + # remove `to_be_sampled` filter + if not setup.getSamplingWorkflowEnabled(): + self.review_states = filter( + lambda x: x.get("id") != "to_be_sampled", self.review_states) + + # remove `scheduled_sampling` filter + if not setup.getScheduleSamplingEnabled(): + self.review_states = filter( + lambda x: x.get("id") != "scheduled_sampling", self.review_states) + + # remove `to_be_preserved` filter + if not setup.getSamplePreservationEnabled(): + self.review_states = filter( + lambda x: x.get("id") != "to_be_preserved", self.review_states) + + # remove `rejected` filter + if not setup.getRejectionReasons(): + self.review_states = filter( + lambda x: x.get("id") != "rejected", self.review_states) + + self.hideclientlink = "RegulatoryInspector" in self.roles \ + and "Manager" not in self.roles \ + and "LabManager" not in self.roles \ + and "LabClerk" not in self.roles + + if self.context.portal_type == "AnalysisRequestsFolder" and \ + (self.mtool.checkPermission(AddAnalysisRequest, self.context)): + self.context_actions[_("Add")] = \ + {"url": "ar_add?ar_count=1", + "icon": "++resource++bika.lims.images/add.png"} + + self.editresults = -1 + self.clients = {} + # self.user_is_preserver = "Preserver" in self.roles + # Printing workflow enabled? + # If not, remove the Column + self.printwfenabled = \ + self.context.bika_setup.getPrintingWorkflowEnabled() + printed_colname = "Printed" + if not self.printwfenabled and printed_colname in self.columns: + # Remove "Printed" columns + del self.columns[printed_colname] + tmprvs = [] + for rs in self.review_states: + tmprs = rs + tmprs["columns"] = [c for c in rs.get("columns", []) if + c != printed_colname] + tmprvs.append(tmprs) + self.review_states = tmprvs + elif self.printwfenabled: + # Print button to choose multiple ARs and print them. + review_states = [] + for review_state in self.review_states: + review_state.get("custom_transitions", []).extend( + [{"id": "print", + "title": _("Print"), + "url": "workflow_action?action=print"}, ]) + review_states.append(review_state) + self.review_states = review_states + + # Only "BIKA: ManageAnalysisRequests" may see the copy to new button. + # elsewhere it is hacked in where required. + if self.copy_to_new_allowed: + review_states = [] + for review_state in self.review_states: + review_state.get("custom_transitions", []).extend( + [{"id": "copy_to_new", + "title": _("Copy to new"), + "url": "workflow_action?action=copy_to_new"}, ]) + review_states.append(review_state) + self.review_states = review_states + + # Hide Preservation/Sampling workflow actions if the edit columns + # are not displayed. + toggle_cols = self.get_toggle_cols() + new_states = [] + for i, state in enumerate(self.review_states): + if state["id"] == self.review_state: + if "getSampler" not in toggle_cols \ + or "getDateSampled" not in toggle_cols: + if "hide_transitions" in state: + state["hide_transitions"].append("sample") + else: + state["hide_transitions"] = ["sample", ] + if "getPreserver" not in toggle_cols \ + or "getDatePreserved" not in toggle_cols: + if "hide_transitions" in state: + state["hide_transitions"].append("preserve") + else: + state["hide_transitions"] = ["preserve", ] + new_states.append(state) + self.review_states = new_states def isItemAllowed(self, obj): """ @@ -833,15 +626,15 @@ def isItemAllowed(self, obj): if not self.context.bika_setup.getAllowDepartmentFiltering(): return True # Getting the department from analysis service - deps = obj.getDepartmentUIDs if hasattr(obj, 'getDepartmentUIDs')\ + deps = obj.getDepartmentUIDs if hasattr(obj, "getDepartmentUIDs")\ else [] result = True if deps: # Getting the cookie value - cookie_dep_uid = self.request.get('filter_by_department_info', '') - # Comparing departments' UIDs + cookie_dep_uid = self.request.get("filter_by_department_info", "") + # Comparing departments" UIDs deps_uids = set(deps) - filter_uids = set(cookie_dep_uid.split(',')) + filter_uids = set(cookie_dep_uid.split(",")) matches = deps_uids & filter_uids result = len(matches) > 0 return result @@ -849,7 +642,7 @@ def isItemAllowed(self, obj): def folderitems(self, full_objects=False, classic=False): # We need to get the portal catalog here in roder to save process # while iterating over folderitems - self.portal_catalog = getToolByName(self.context, 'portal_catalog') + self.portal_catalog = api.get_tool("portal_catalog") return BikaListingView.folderitems(self, full_objects, classic) def folderitem(self, obj, item, index): @@ -862,29 +655,29 @@ def folderitem(self, obj, item, index): # This variable will contain the full analysis request if there is # need to work with the full object instead of the brain full_object = None - item['Creator'] = self.user_fullname(obj.Creator) + 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_sort_key = '3.%s' % obj.created.ISO8601() - priority = priority_sort_key.split('.')[0] + priority_sort_key = "3.%s" % obj.created.ISO8601() + priority = priority_sort_key.split(".")[0] priority_text = PRIORITIES.getValue(priority) priority_div = """
%s
""" - item['replace']['Priority'] = priority_div % (priority, priority_text) - item['replace']['getProfilesTitle'] = obj.getProfilesTitleStr + 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) + item["getAnalysesNum"] = "{0}/{1}".format(num_verified, num_total) else: - item['getAnalysesNum'] = '' + item["getAnalysesNum"] = "" # Progress num_verified = 0 @@ -905,9 +698,9 @@ def folderitem(self, obj, item, index): progress = '
' + \ '
' + \ '
{0}%
' - item['replace']['Progress'] = progress.format(progress_perc) + item["replace"]["Progress"] = progress.format(progress_perc) - item['BatchID'] = obj.getBatchID + item["BatchID"] = obj.getBatchID if obj.getBatchID: item['replace']['BatchID'] = "%s" % \ (obj.getBatchURL, obj.getBatchID) @@ -916,22 +709,22 @@ def folderitem(self, obj, item, index): # item['SubGroup'] = val.Title() if val else '' date = obj.getSamplingDate - item['SamplingDate'] = \ - self.ulocalized_time(date, long_format=1) if date else '' + item["SamplingDate"] = \ + self.ulocalized_time(date, long_format=1) if date else "" date = obj.getDateReceived - item['getDateReceived'] = \ - self.ulocalized_time(date, long_format=1) if date else '' + item["getDateReceived"] = \ + self.ulocalized_time(date, long_format=1) if date else "" date = obj.getDatePublished - item['getDatePublished'] = \ - self.ulocalized_time(date, long_format=1) if date else '' + item["getDatePublished"] = \ + self.ulocalized_time(date, long_format=1) if date else "" date = obj.getDateVerified - item['getDateVerified'] = \ - self.ulocalized_time(date, long_format=1) if date else '' + item["getDateVerified"] = \ + self.ulocalized_time(date, long_format=1) if date else "" if self.printwfenabled: - item['Printed'] = '' - printed = obj.getPrinted if hasattr(obj, 'getPrinted') else "0" - print_icon = '' + item["Printed"] = "" + printed = obj.getPrinted if hasattr(obj, "getPrinted") else "0" + print_icon = "" if printed == "0": print_icon = \ """ """ \ % (self.portal_url, t(_("Republished after last print"))) - item['after']['Printed'] = print_icon - item['SamplingDeviation'] = obj.getSamplingDeviationTitle + item["after"]["Printed"] = print_icon + item["SamplingDeviation"] = obj.getSamplingDeviationTitle - item['getStorageLocation'] = obj.getStorageLocationTitle + item["getStorageLocation"] = obj.getStorageLocationTitle after_icons = "" # Getting a dictionary with each workflow id and current state in it @@ -974,9 +767,9 @@ def folderitem(self, obj, item, index): """ % (self.portal_url, t(_("Late Analyses"))) if obj.getSamplingDate and obj.getSamplingDate > DateTime(): after_icons += \ - """ - """ % (self.portal_url, t(_("Future dated sample"))) + """ + """ % (self.portal_url, t(_("Future dated sample"))) if obj.getInvoiceExclude: after_icons += \ """ - """ % t(_("Cannot verify: Submitted by current user")) + item["after"]["state_title"] = \ + """ + """ % t(_("Cannot verify: Submitted by current user")) return item def pending_tasks(self): @@ -1110,92 +902,12 @@ def pending_tasks(self): @property def copy_to_new_allowed(self): - mtool = getToolByName(self.context, 'portal_membership') + mtool = api.get_tool("portal_membership") if mtool.checkPermission(ManageAnalysisRequests, self.context) \ or mtool.checkPermission(ModifyPortalContent, self.context): return True return False - def __call__(self): - self.workflow = getToolByName(self.context, "portal_workflow") - self.mtool = getToolByName(self.context, 'portal_membership') - self.member = self.mtool.getAuthenticatedMember() - self.roles = self.member.getRoles() - self.hideclientlink = 'RegulatoryInspector' in self.roles \ - and 'Manager' not in self.roles \ - and 'LabManager' not in self.roles \ - and 'LabClerk' not in self.roles - - if self.context.portal_type == "AnalysisRequestsFolder" and \ - (self.mtool.checkPermission(AddAnalysisRequest, self.context)): - self.context_actions[_('Add')] = \ - {'url': "ar_add?ar_count=1", - 'icon': '++resource++bika.lims.images/add.png'} - - self.editresults = -1 - self.clients = {} - # self.user_is_preserver = 'Preserver' in self.roles - # Printing workflow enabled? - # If not, remove the Column - self.printwfenabled = \ - self.context.bika_setup.getPrintingWorkflowEnabled() - printed_colname = 'Printed' - if not self.printwfenabled and printed_colname in self.columns: - # Remove "Printed" columns - del self.columns[printed_colname] - tmprvs = [] - for rs in self.review_states: - tmprs = rs - tmprs['columns'] = [c for c in rs.get('columns', []) if - c != printed_colname] - tmprvs.append(tmprs) - self.review_states = tmprvs - elif self.printwfenabled: - # Print button to choose multiple ARs and print them. - review_states = [] - for review_state in self.review_states: - review_state.get('custom_transitions', []).extend( - [{'id': 'print', - 'title': _('Print'), - 'url': 'workflow_action?action=print'}, ]) - review_states.append(review_state) - self.review_states = review_states - - # Only "BIKA: ManageAnalysisRequests" may see the copy to new button. - # elsewhere it is hacked in where required. - if self.copy_to_new_allowed: - review_states = [] - for review_state in self.review_states: - review_state.get('custom_transitions', []).extend( - [{'id': 'copy_to_new', - 'title': _('Copy to new'), - 'url': 'workflow_action?action=copy_to_new'}, ]) - review_states.append(review_state) - self.review_states = review_states - - # Hide Preservation/Sampling workflow actions if the edit columns - # are not displayed. - toggle_cols = self.get_toggle_cols() - new_states = [] - for i, state in enumerate(self.review_states): - if state['id'] == self.review_state: - if 'getSampler' not in toggle_cols \ - or 'getDateSampled' not in toggle_cols: - if 'hide_transitions' in state: - state['hide_transitions'].append('sample') - else: - state['hide_transitions'] = ['sample', ] - if 'getPreserver' not in toggle_cols \ - or 'getDatePreserved' not in toggle_cols: - if 'hide_transitions' in state: - state['hide_transitions'].append('preserve') - else: - state['hide_transitions'] = ['preserve', ] - new_states.append(state) - self.review_states = new_states - - return super(AnalysisRequestsView, self).__call__() - def getFilterBar(self): """ This function creates an instance of BikaListingFilterBar if the @@ -1220,12 +932,12 @@ def __call__(self): PostOnly(self.context.REQUEST) except: logger.error(traceback.format_exc()) - return json.dumps({'count': 0}) + return json.dumps({"count": 0}) try: CheckAuthenticator(self.request.form) except: logger.error(traceback.format_exc()) - return json.dumps({'count': 0}) - task_queue = queryUtility(ITaskQueue, name='ar-create') + return json.dumps({"count": 0}) + task_queue = queryUtility(ITaskQueue, name="ar-create") count = len(task_queue) if task_queue is not None else 0 - return json.dumps({'count': count}) + return json.dumps({"count": count}) diff --git a/bika/lims/browser/bika_listing.py b/bika/lims/browser/bika_listing.py index a09f949a01..51076ce899 100644 --- a/bika/lims/browser/bika_listing.py +++ b/bika/lims/browser/bika_listing.py @@ -644,9 +644,11 @@ def review_state(self): # get state_id from (request or default_review_states) key = "%s_review_state" % self.form_id state_id = self.request.form.get(key, self.default_review_state) + if not state_id: + state_id = self.default_review_state states = [r for r in self.review_states if r['id'] == state_id] if not states: - logger.error("%s.review_states does not contains id='%s'." % + logger.error("%s.review_states does not contain id='%s'." % (self, state_id)) return None review_state = states[0] if states else self.review_states[0] diff --git a/bika/lims/browser/js/bika.lims.bikalisting.js b/bika/lims/browser/js/bika.lims.bikalisting.js index 75365b6991..2884c12c9a 100644 --- a/bika/lims/browser/js/bika.lims.bikalisting.js +++ b/bika/lims/browser/js/bika.lims.bikalisting.js @@ -361,7 +361,7 @@ input_name = form_id + "_review_state"; input = $("input[name=" + input_name + "]", form); if (input.length === 0) { - input = form.append(""); + input = form.append(""); } input.val(state_id); form_data = new FormData(form[0]); diff --git a/bika/lims/browser/js/coffee/bika.lims.bikalisting.coffee b/bika/lims/browser/js/coffee/bika.lims.bikalisting.coffee index f902bcd12c..1c02499f0b 100644 --- a/bika/lims/browser/js/coffee/bika.lims.bikalisting.coffee +++ b/bika/lims/browser/js/coffee/bika.lims.bikalisting.coffee @@ -367,7 +367,7 @@ class window.BikaListingTableView input_name = "#{form_id}_review_state" input = $("input[name=#{input_name}]", form) if input.length == 0 - input = form.append "" + input = form.append "" input.val state_id # prepare the form data