From 0313705f0f40befd632477c96e2599c7210859c5 Mon Sep 17 00:00:00 2001 From: Ramon Bartl Date: Fri, 16 Feb 2018 18:14:54 +0100 Subject: [PATCH 01/15] Fixed content filter for AR listings --- .../browser/analysisrequest/analysisrequests.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/bika/lims/browser/analysisrequest/analysisrequests.py b/bika/lims/browser/analysisrequest/analysisrequests.py index a45518f0fc..bc1612498a 100644 --- a/bika/lims/browser/analysisrequest/analysisrequests.py +++ b/bika/lims/browser/analysisrequest/analysisrequests.py @@ -47,11 +47,14 @@ def __init__(self, context, request): request.set('disable_plone.rightcolumn', 1) # Setting up the catalog and query dictionary self.catalog = CATALOG_ANALYSIS_REQUEST_LISTING - self.contentFilter = {'sort_on': 'Created', - 'sort_order': 'reverse', - 'path': {"query": "/", "level": 0}, - 'cancellation_state': 'active', - } + + # 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", + } self.context_actions = {} From 92035d221b236ac5f01f38b188d1d0c5ddf77f64 Mon Sep 17 00:00:00 2001 From: Ramon Bartl Date: Fri, 16 Feb 2018 18:15:51 +0100 Subject: [PATCH 02/15] Use ordered dict for columns and columns.keys for state columns --- .../analysisrequest/analysisrequests.py | 1025 ++++++----------- 1 file changed, 367 insertions(+), 658 deletions(-) diff --git a/bika/lims/browser/analysisrequest/analysisrequests.py b/bika/lims/browser/analysisrequest/analysisrequests.py index bc1612498a..631868c4bc 100644 --- a/bika/lims/browser/analysisrequest/analysisrequests.py +++ b/bika/lims/browser/analysisrequest/analysisrequests.py @@ -83,744 +83,453 @@ def __init__(self, context, request): self.context.bika_setup.\ getDisplayAdvancedFilterBarForAnalysisRequests() - self.columns = { - 'Priority': { + self.columns = collections.OrderedDict(( + ('Priority', { 'title': '', 'index': 'getPrioritySortkey', - 'sortable': True, }, - 'Progress': { + 'sortable': True, }), + ('Progress', { 'title': 'Progress', 'sortable': False, - 'toggle': True}, - 'getId': { + 'toggle': True}), + ('getId', { 'title': _('Request ID'), 'attr': 'getId', 'replace_url': 'getURL', - 'index': 'getId'}, - 'getClientOrderNumber': { + 'index': 'getId'}), + ('getClientOrderNumber', { 'title': _('Client Order'), 'sortable': True, - 'toggle': True}, - 'Creator': { + 'toggle': True}), + ('Creator', { 'title': PMF('Creator'), 'index': 'getCreatorFullName', 'sortable': True, - 'toggle': True}, - 'Created': { + 'toggle': True}), + ('Created', { 'title': PMF('Date Created'), 'index': 'created', - 'toggle': False}, - 'getSample': { + 'toggle': False}), + ('getSample', { 'title': _("Sample"), 'attr': 'getSampleID', 'index': 'getSampleID', 'replace_url': 'getSampleURL', - 'toggle': True, }, - 'BatchID': { + 'toggle': True, }), + ('BatchID', { 'title': _("Batch ID"), 'index': 'getBatchID', 'sortable': True, - 'toggle': True}, - 'Client': { + 'toggle': True}), + ('Client', { 'title': _('Client'), 'index': 'getClientTitle', 'attr': 'getClientTitle', 'replace_url': 'getClientURL', - 'toggle': True}, - 'Province': { + 'toggle': True}), + ('Province', { 'title': _('Province'), 'sortable': True, 'index': 'getProvince', 'attr': 'getProvince', - 'toggle': True}, - 'District': { + 'toggle': True}), + ('District', { 'title': _('District'), 'sortable': True, 'index': 'getDistrict', 'attr': 'getDistrict', - 'toggle': True}, - 'getClientReference': { + 'toggle': True}), + ('getClientReference', { 'title': _('Client Ref'), 'sortable': True, 'index': 'getClientReference', - 'toggle': True}, - 'getClientSampleID': { + 'toggle': True}), + ('getClientSampleID', { 'title': _('Client SID'), - 'toggle': True}, - 'ClientContact': { + 'toggle': True}), + ('ClientContact', { 'title': _('Contact'), 'sortable': True, 'index': 'getContactFullName', - 'toggle': False}, - 'getSampleTypeTitle': { + 'toggle': False}), + ('getSampleTypeTitle', { 'title': _('Sample Type'), 'sortable': True, - 'toggle': True}, - 'getSamplePointTitle': { + 'toggle': True}), + ('getSamplePointTitle', { 'title': _('Sample Point'), 'sortable': True, 'index': 'getSamplePointTitle', - 'toggle': False}, - 'getStorageLocation': { + 'toggle': False}), + ('getStorageLocation', { 'title': _('Storage Location'), 'sortable': True, 'index': 'getStorageLocationTitle', - 'toggle': False}, - 'SamplingDeviation': { + 'toggle': False}), + ('SamplingDeviation', { 'title': _('Sampling Deviation'), 'sortable': True, 'index': 'getSamplingDeviationTitle', - 'toggle': False}, - # 'AdHoc': {'title': _('Ad-Hoc'), - # 'toggle': False}, - 'SamplingDate': { + 'toggle': False}), + ('SamplingDate', { 'title': _('Expected Sampling Date'), 'index': 'getSamplingDate', - 'toggle': SamplingWorkflowEnabled}, - 'getDateSampled': { + 'toggle': SamplingWorkflowEnabled}), + ('getDateSampled', { 'title': _('Date Sampled'), 'toggle': True, 'input_class': 'datetimepicker_nofuture', - 'input_width': '10'}, - 'getDateVerified': { + 'input_width': '10'}), + ('getDateVerified', { 'title': _('Date Verified'), - 'input_width': '10'}, - 'getSampler': { + 'input_width': '10'}), + ('getSampler', { 'title': _('Sampler'), - 'toggle': SamplingWorkflowEnabled}, - 'getDatePreserved': { + 'toggle': SamplingWorkflowEnabled}), + ('getDatePreserved', { 'title': _('Date Preserved'), 'toggle': False, 'input_class': 'datetimepicker_nofuture', 'input_width': '10', - 'sortable': False}, # no datesort without index - 'getPreserver': { + 'sortable': False}), # no datesort without index + ('getPreserver', { 'title': _('Preserver'), 'sortable': False, - 'toggle': False}, - 'getDateReceived': { + 'toggle': False}), + ('getDateReceived', { 'title': _('Date Received'), - 'toggle': False}, - 'getDatePublished': { + 'toggle': False}), + ('getDatePublished', { 'title': _('Date Published'), - 'toggle': False}, - 'state_title': { - 'title': _('State'), - 'sortable': True, - 'index': 'review_state'}, - 'getProfilesTitle': { + 'toggle': False}), + ('getProfilesTitle', { 'title': _('Profile'), 'sortable': True, 'index': 'getProfilesTitle', - 'toggle': False}, - 'getAnalysesNum': { + 'toggle': False}), + ('getAnalysesNum', { 'title': _('Number of Analyses'), 'sortable': True, 'index': 'getAnalysesNum', - 'toggle': False}, - 'getTemplateTitle': { + 'toggle': False}), + ('getTemplateTitle', { 'title': _('Template'), 'sortable': True, 'index': 'getTemplateTitle', - 'toggle': False}, - 'Printed': { + 'toggle': False}), + ('Printed', { 'title': _('Printed'), 'sortable': False, 'index': 'getPrinted', - 'toggle': False}, - } + 'toggle': False}), + ('state_title', { + 'title': _('State'), + 'sortable': True, + 'index': 'review_state'}), + )) 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': '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': self.columns.keys(), + }, { + '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': self.columns.keys() + }, { + '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': self.columns.keys(), + }, { + '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': self.columns.keys(), + }, { + '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': self.columns.keys(), + }, { + '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': self.columns.keys(), + }, { + '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': self.columns.keys(), + }, { + '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': self.columns.keys(), + }, { + 'id': 'published', + 'title': _('Published'), + 'contentFilter': { + 'review_state': ('published', 'invalid'), + 'sort_on': 'Created', + 'sort_order': 'reverse', + }, + 'transitions': [ + {'id': 'republish'}, + ], + 'custom_transitions': [], + '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': 'reverse', + }, + 'transitions': [ + {'id': 'reinstate'}, + ], + 'custom_transitions': [], + 'columns': self.columns.keys(), + }, { + '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': 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': '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': 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': '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': self.columns.keys(), + }, { + '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': self.columns.keys(), + }, + ] + + # simple index to access the dictionaries by id + self.review_state_ids = map(lambda rs: rs["id"], self.review_states) + + def update(self): + """Called before the listing renders + """ + super(AnalysisRequestsView, self).update() def isItemAllowed(self, obj): """ From 88894161085a5b719a4b7ad9af061619f4074092 Mon Sep 17 00:00:00 2001 From: Ramon Bartl Date: Fri, 16 Feb 2018 18:16:15 +0100 Subject: [PATCH 03/15] imports only --- .../analysisrequest/analysisrequests.py | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/bika/lims/browser/analysisrequest/analysisrequests.py b/bika/lims/browser/analysisrequest/analysisrequests.py index 631868c4bc..013c83930c 100644 --- a/bika/lims/browser/analysisrequest/analysisrequests.py +++ b/bika/lims/browser/analysisrequest/analysisrequests.py @@ -5,31 +5,30 @@ # 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 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.CMFCore.utils import getToolByName +from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile from zope.component import queryUtility from zope.interface import implements From 9144b23240388f0e2933895e6e86b40919158821 Mon Sep 17 00:00:00 2001 From: Ramon Bartl Date: Fri, 16 Feb 2018 18:29:34 +0100 Subject: [PATCH 04/15] Remove unneeded filters --- .../analysisrequest/analysisrequests.py | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/bika/lims/browser/analysisrequest/analysisrequests.py b/bika/lims/browser/analysisrequest/analysisrequests.py index 013c83930c..faff761d96 100644 --- a/bika/lims/browser/analysisrequest/analysisrequests.py +++ b/bika/lims/browser/analysisrequest/analysisrequests.py @@ -11,6 +11,7 @@ from DateTime import DateTime 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 @@ -522,13 +523,26 @@ def __init__(self, context, request): }, ] - # simple index to access the dictionaries by id - self.review_state_ids = map(lambda rs: rs["id"], self.review_states) - def update(self): """Called before the listing renders """ super(AnalysisRequestsView, self).update() + setup = api.get_bika_setup() + + # remove `to_be_sampled` filter + if not setup.getSamplingWorkflowEnabled(): + self.review_states = filter( + lambda x: x["id"] != "to_be_sampled", self.review_states) + + # remove `scheduled_sampling` filter + if not setup.getScheduleSamplingEnabled(): + self.review_states = filter( + lambda x: x["id"] != "scheduled_sampling", self.review_states) + + # remove `to_be_preserved` filter + if not setup.getSamplePreservationEnabled(): + self.review_states = filter( + lambda x: x["id"] != "to_be_preserved", self.review_states) def isItemAllowed(self, obj): """ From 23a720538e9c4e13d7194b58a7e88a869887801e Mon Sep 17 00:00:00 2001 From: Ramon Bartl Date: Fri, 16 Feb 2018 18:31:05 +0100 Subject: [PATCH 05/15] PEP8 only --- .../browser/analysisrequest/analysisrequests.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/bika/lims/browser/analysisrequest/analysisrequests.py b/bika/lims/browser/analysisrequest/analysisrequests.py index faff761d96..c239ec9af7 100644 --- a/bika/lims/browser/analysisrequest/analysisrequests.py +++ b/bika/lims/browser/analysisrequest/analysisrequests.py @@ -699,9 +699,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")) + """ + """ % t(_("Cannot verify: Submitted by current user")) return item def pending_tasks(self): From 239f5ed59b43b11ec38be5dc0405857b2d0a1fda Mon Sep 17 00:00:00 2001 From: Ramon Bartl Date: Fri, 16 Feb 2018 19:24:34 +0100 Subject: [PATCH 06/15] Added unpublished filter + refactoring --- .../analysisrequest/analysisrequests.py | 190 ++++++++---------- 1 file changed, 86 insertions(+), 104 deletions(-) diff --git a/bika/lims/browser/analysisrequest/analysisrequests.py b/bika/lims/browser/analysisrequest/analysisrequests.py index c239ec9af7..cfb9fda7c7 100644 --- a/bika/lims/browser/analysisrequest/analysisrequests.py +++ b/bika/lims/browser/analysisrequest/analysisrequests.py @@ -228,13 +228,20 @@ def __init__(self, context, request): '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', + 'sort_on': 'created', + 'sort_order': 'descending', }, 'transitions': [ {'id': 'sample'}, @@ -248,72 +255,49 @@ def __init__(self, context, request): {'id': 'cancel'}, {'id': 'reinstate'}, ], - 'custom_transitions': [ - { - 'id': 'print_stickers', - 'title': _('Print stickers'), - 'url': 'workflow_action?action=print_stickers' - } - ], + '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': 'reverse'}, + 'sort_on': 'created', + 'sort_order': 'descending'}, 'transitions': [ {'id': 'sample'}, {'id': 'submit'}, {'id': 'cancel'}, ], - 'custom_transitions': [ - { - 'id': 'print_stickers', - 'title': _('Print stickers'), - 'url': 'workflow_action?action=print_stickers', - } - ], + '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': 'reverse', + 'sort_on': 'created', + 'sort_order': 'descending', }, 'transitions': [ {'id': 'preserve'}, {'id': 'cancel'}, ], - 'custom_transitions': [ - { - 'id': 'print_stickers', - 'title': _('Print stickers'), - 'url': 'workflow_action?action=print_stickers'}, - ], + 'custom_transitions': [print_stickers], 'columns': self.columns.keys(), }, { 'id': 'scheduled_sampling', 'title': _('Scheduled sampling'), 'contentFilter': { 'review_state': ('scheduled_sampling',), - 'sort_on': 'Created', - 'sort_order': 'reverse', + 'sort_on': 'created', + 'sort_order': 'descending', }, 'transitions': [ {'id': 'sample'}, {'id': 'cancel'}, ], - 'custom_transitions': [ - { - 'id': 'print_stickers', - 'title': _('Print stickers'), - 'url': 'workflow_action?action=print_stickers', - } - ], + 'custom_transitions': [print_stickers], 'columns': self.columns.keys(), }, { 'id': 'sample_due', @@ -323,8 +307,8 @@ def __init__(self, context, request): 'to_be_sampled', 'to_be_preserved', 'sample_due'), - 'sort_on': 'Created', - 'sort_order': 'reverse'}, + 'sort_on': 'created', + 'sort_order': 'descending'}, 'transitions': [ {'id': 'sample'}, {'id': 'preserve'}, @@ -332,40 +316,30 @@ def __init__(self, context, request): {'id': 'cancel'}, {'id': 'reinstate'}, ], - 'custom_transitions': [ - { - 'id': 'print_stickers', - 'title': _('Print stickers'), - 'url': 'workflow_action?action=print_stickers'}, - ], + 'custom_transitions': [print_stickers], 'columns': self.columns.keys(), }, { 'id': 'sample_received', 'title': _('Received'), 'contentFilter': { 'review_state': 'sample_received', - 'sort_on': 'Created', - 'sort_order': 'reverse', + 'sort_on': 'created', + 'sort_order': 'descending', }, 'transitions': [ {'id': 'prepublish'}, {'id': 'cancel'}, {'id': 'reinstate'}, ], - 'custom_transitions': [ - { - 'id': 'print_stickers', - 'title': _('Print stickers'), - 'url': 'workflow_action?action=print_stickers'}, - ], + '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': 'reverse', + 'sort_on': 'created', + 'sort_order': 'descending', }, 'transitions': [ {'id': 'retract'}, @@ -374,43 +348,67 @@ def __init__(self, context, request): {'id': 'cancel'}, {'id': 'reinstate'}, ], - 'custom_transitions': [ - { - 'id': 'print_stickers', - 'title': _('Print stickers'), - 'url': 'workflow_action?action=print_stickers'}, - ], + 'custom_transitions': [print_stickers], 'columns': self.columns.keys(), }, { 'id': 'verified', 'title': _('Verified'), 'contentFilter': { 'review_state': 'verified', - 'sort_on': 'Created', - 'sort_order': 'reverse', + 'sort_on': 'created', + 'sort_order': 'descending', }, 'transitions': [ {'id': 'publish'}, {'id': 'cancel'}, ], - 'custom_transitions': [{ - 'id': 'print_stickers', - 'title': _('Print stickers'), - 'url': 'workflow_action?action=print_stickers'}], + 'custom_transitions': [print_stickers], 'columns': self.columns.keys(), }, { 'id': 'published', 'title': _('Published'), 'contentFilter': { 'review_state': ('published', 'invalid'), - 'sort_on': 'Created', - 'sort_order': 'reverse', + 'sort_on': 'created', + 'sort_order': 'descending', }, 'transitions': [ {'id': 'republish'}, ], 'custom_transitions': [], 'columns': self.columns.keys(), + }, { + 'id': 'unpublished', + 'title': t(_("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'), @@ -427,8 +425,8 @@ def __init__(self, context, request): 'verified', 'published', ), - 'sort_on': 'Created', - 'sort_order': 'reverse', + 'sort_on': 'created', + 'sort_order': 'descending', }, 'transitions': [ {'id': 'reinstate'}, @@ -440,8 +438,19 @@ def __init__(self, context, request): 'title': _('Invalid'), 'contentFilter': { 'review_state': 'invalid', - 'sort_on': 'Created', - 'sort_order': 'reverse' + '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': [ @@ -460,8 +469,8 @@ def __init__(self, context, request): 'cancellation_state': 'active', 'review_state': ('sample_received', 'attachment_due',), - 'sort_on': 'Created', - 'sort_order': 'reverse', + 'sort_on': 'created', + 'sort_order': 'descending', }, 'transitions': [ {'id': 'receive'}, @@ -469,12 +478,7 @@ def __init__(self, context, request): {'id': 'prepublish'}, {'id': 'cancel'}, ], - 'custom_transitions': [ - { - 'id': 'print_stickers', - 'title': _('Print stickers'), - 'url': 'workflow_action?action=print_stickers'}, - ], + 'custom_transitions': [print_stickers], 'columns': self.columns.keys(), }, { 'id': 'unassigned', @@ -487,8 +491,8 @@ def __init__(self, context, request): 'sample_received', 'attachment_due', ), - 'sort_on': 'Created', - 'sort_order': 'reverse', + 'sort_on': 'created', + 'sort_order': 'descending', }, 'transitions': [ {'id': 'receive'}, @@ -496,29 +500,7 @@ def __init__(self, context, request): {'id': 'prepublish'}, {'id': 'cancel'}, ], - 'custom_transitions': [ - { - 'id': 'print_stickers', - 'title': _('Print stickers'), - 'url': 'workflow_action?action=print_stickers', - } - ], - 'columns': self.columns.keys(), - }, { - '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'}, - ], + 'custom_transitions': [print_stickers], 'columns': self.columns.keys(), }, ] From bba85904bb4f964275b0915ce425f2ed26a1b13b Mon Sep 17 00:00:00 2001 From: Ramon Bartl Date: Fri, 16 Feb 2018 19:25:41 +0100 Subject: [PATCH 07/15] Handle None review_state attribute --- bika/lims/browser/bika_listing.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bika/lims/browser/bika_listing.py b/bika/lims/browser/bika_listing.py index a09f949a01..35d8c47138 100644 --- a/bika/lims/browser/bika_listing.py +++ b/bika/lims/browser/bika_listing.py @@ -1145,7 +1145,8 @@ def get_catalog_query(self, searchterm=None): query = copy.deepcopy(self.contentFilter) # contentFilter is allowed in every self.review_state. - for k, v in self.review_state.get("contentFilter", {}).items(): + review_state = getattr(self, "review_state", {}) + for k, v in review_state.get("contentFilter", {}).items(): query[k] = v # set the sort_on criteria From 92d98fc3ee3cc787e64a2c1bf1272f85444b07e0 Mon Sep 17 00:00:00 2001 From: Ramon Bartl Date: Fri, 16 Feb 2018 19:39:25 +0100 Subject: [PATCH 08/15] Return empty list instead of None --- bika/lims/browser/bika_listing.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/bika/lims/browser/bika_listing.py b/bika/lims/browser/bika_listing.py index 35d8c47138..1894f69c27 100644 --- a/bika/lims/browser/bika_listing.py +++ b/bika/lims/browser/bika_listing.py @@ -646,9 +646,9 @@ def review_state(self): state_id = self.request.form.get(key, 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 + return [] review_state = states[0] if states else self.review_states[0] # set selected state into the request self.request['%s_review_state' % self.form_id] = review_state['id'] @@ -1145,8 +1145,7 @@ def get_catalog_query(self, searchterm=None): query = copy.deepcopy(self.contentFilter) # contentFilter is allowed in every self.review_state. - review_state = getattr(self, "review_state", {}) - for k, v in review_state.get("contentFilter", {}).items(): + for k, v in self.review_state.get("contentFilter", {}).items(): query[k] = v # set the sort_on criteria From 53682e240e20eafd2b7001f67cfc1c6154eee141 Mon Sep 17 00:00:00 2001 From: Ramon Bartl Date: Fri, 16 Feb 2018 20:59:49 +0100 Subject: [PATCH 09/15] Return i18n message id --- bika/lims/browser/analysisrequest/analysisrequests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bika/lims/browser/analysisrequest/analysisrequests.py b/bika/lims/browser/analysisrequest/analysisrequests.py index cfb9fda7c7..847b6c11da 100644 --- a/bika/lims/browser/analysisrequest/analysisrequests.py +++ b/bika/lims/browser/analysisrequest/analysisrequests.py @@ -379,7 +379,7 @@ def __init__(self, context, request): 'columns': self.columns.keys(), }, { 'id': 'unpublished', - 'title': t(_("Unpublished")), + 'title': _('Unpublished'), 'contentFilter': { 'cancellation_state': 'active', 'review_state': ( From f095102cef7e34777133214b9816575b781ca5ad Mon Sep 17 00:00:00 2001 From: Ramon Bartl Date: Fri, 16 Feb 2018 21:40:51 +0100 Subject: [PATCH 10/15] Handle empty state_id --- bika/lims/browser/bika_listing.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bika/lims/browser/bika_listing.py b/bika/lims/browser/bika_listing.py index 1894f69c27..51076ce899 100644 --- a/bika/lims/browser/bika_listing.py +++ b/bika/lims/browser/bika_listing.py @@ -644,11 +644,13 @@ 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 contain id='%s'." % (self, state_id)) - return [] + return None review_state = states[0] if states else self.review_states[0] # set selected state into the request self.request['%s_review_state' % self.form_id] = review_state['id'] From 9ff4cdceea7f00c4efd8e3e1efc435c073156324 Mon Sep 17 00:00:00 2001 From: Ramon Bartl Date: Fri, 16 Feb 2018 21:41:29 +0100 Subject: [PATCH 11/15] Refactored --- .../analysisrequest/analysisrequests.py | 186 +++++++++--------- 1 file changed, 97 insertions(+), 89 deletions(-) diff --git a/bika/lims/browser/analysisrequest/analysisrequests.py b/bika/lims/browser/analysisrequest/analysisrequests.py index 847b6c11da..7103cb200a 100644 --- a/bika/lims/browser/analysisrequest/analysisrequests.py +++ b/bika/lims/browser/analysisrequest/analysisrequests.py @@ -35,17 +35,24 @@ 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) + # hide the right column request.set('disable_plone.rightcolumn', 1) - # Setting up the catalog and query dictionary + + # 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 # see: https://docs.plone.org/develop/plone/searching_and_indexing/query.html#searching-for-content-within-a-folder @@ -58,9 +65,6 @@ def __init__(self, context, request): self.context_actions = {} - if self.context.portal_type == "AnalysisRequestsFolder": - self.request.set('disable_border', 1) - if self.view_url.find("analysisrequests") == -1: self.view_url = self.view_url + "/analysisrequests" @@ -509,22 +513,106 @@ def update(self): """Called before the listing renders """ super(AnalysisRequestsView, self).update() + + self.workflow = getToolByName(self.context, "portal_workflow") + self.mtool = getToolByName(self.context, 'portal_membership') + 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["id"] != "to_be_sampled", self.review_states) + 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["id"] != "scheduled_sampling", self.review_states) + 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["id"] != "to_be_preserved", self.review_states) + 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): """ @@ -822,86 +910,6 @@ def copy_to_new_allowed(self): 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 From c4e9b45c5a9f6ea7b0e8ac88afa8d71fbefbbdc8 Mon Sep 17 00:00:00 2001 From: Ramon Bartl Date: Fri, 16 Feb 2018 21:53:13 +0100 Subject: [PATCH 12/15] Unified quotation marks --- .../analysisrequest/analysisrequests.py | 892 +++++++++--------- 1 file changed, 445 insertions(+), 447 deletions(-) diff --git a/bika/lims/browser/analysisrequest/analysisrequests.py b/bika/lims/browser/analysisrequest/analysisrequests.py index 7103cb200a..d6607127e9 100644 --- a/bika/lims/browser/analysisrequest/analysisrequests.py +++ b/bika/lims/browser/analysisrequest/analysisrequests.py @@ -28,7 +28,6 @@ from plone.protect import CheckAuthenticator, PostOnly 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 zope.component import queryUtility from zope.interface import implements @@ -46,11 +45,11 @@ def __init__(self, context, request): super(AnalysisRequestsView, self).__init__(context, request) # hide the right column - request.set('disable_plone.rightcolumn', 1) + request.set("disable_plone.rightcolumn", 1) # hide the editable border if self.context.portal_type == "AnalysisRequestsFolder": - self.request.set('disable_border', 1) + self.request.set("disable_border", 1) # catalog used for the query self.catalog = CATALOG_ANALYSIS_REQUEST_LISTING @@ -88,424 +87,424 @@ def __init__(self, context, request): getDisplayAdvancedFilterBarForAnalysisRequests() 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'}), + ("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' + "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': 'descending', + "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'}, + "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(), + "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'}, + "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() + "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', + "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'}, + "transitions": [ + {"id": "preserve"}, + {"id": "cancel"}, ], - 'custom_transitions': [print_stickers], - 'columns': self.columns.keys(), + "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', + "id": "scheduled_sampling", + "title": _("Scheduled sampling"), + "contentFilter": { + "review_state": ("scheduled_sampling",), + "sort_on": "created", + "sort_order": "descending", }, - 'transitions': [ - {'id': 'sample'}, - {'id': 'cancel'}, + "transitions": [ + {"id": "sample"}, + {"id": "cancel"}, ], - 'custom_transitions': [print_stickers], - 'columns': self.columns.keys(), + "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'}, + "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(), + "custom_transitions": [print_stickers], + "columns": self.columns.keys(), }, { - 'id': 'sample_received', - 'title': _('Received'), - 'contentFilter': { - 'review_state': 'sample_received', - 'sort_on': 'created', - 'sort_order': 'descending', + "id": "sample_received", + "title": _("Received"), + "contentFilter": { + "review_state": "sample_received", + "sort_on": "created", + "sort_order": "descending", }, - 'transitions': [ - {'id': 'prepublish'}, - {'id': 'cancel'}, - {'id': 'reinstate'}, + "transitions": [ + {"id": "prepublish"}, + {"id": "cancel"}, + {"id": "reinstate"}, ], - 'custom_transitions': [print_stickers], - 'columns': self.columns.keys(), + "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', + "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'}, + "transitions": [ + {"id": "retract"}, + {"id": "verify"}, + {"id": "prepublish"}, + {"id": "cancel"}, + {"id": "reinstate"}, ], - 'custom_transitions': [print_stickers], - 'columns': self.columns.keys(), + "custom_transitions": [print_stickers], + "columns": self.columns.keys(), }, { - 'id': 'verified', - 'title': _('Verified'), - 'contentFilter': { - 'review_state': 'verified', - 'sort_on': 'created', - 'sort_order': 'descending', + "id": "verified", + "title": _("Verified"), + "contentFilter": { + "review_state": "verified", + "sort_on": "created", + "sort_order": "descending", }, - 'transitions': [ - {'id': 'publish'}, - {'id': 'cancel'}, + "transitions": [ + {"id": "publish"}, + {"id": "cancel"}, ], - 'custom_transitions': [print_stickers], - 'columns': self.columns.keys(), + "custom_transitions": [print_stickers], + "columns": self.columns.keys(), }, { - 'id': 'published', - 'title': _('Published'), - 'contentFilter': { - 'review_state': ('published', 'invalid'), - 'sort_on': 'created', - 'sort_order': 'descending', + "id": "published", + "title": _("Published"), + "contentFilter": { + "review_state": ("published", "invalid"), + "sort_on": "created", + "sort_order": "descending", }, - 'transitions': [ - {'id': 'republish'}, + "transitions": [ + {"id": "republish"}, ], - 'custom_transitions': [], - 'columns': self.columns.keys(), + "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', + "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', + "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'}, + "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(), + "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', + "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', + "sort_on": "created", + "sort_order": "descending", }, - 'transitions': [ - {'id': 'reinstate'}, + "transitions": [ + {"id": "reinstate"}, ], - 'custom_transitions': [], - 'columns': self.columns.keys(), + "custom_transitions": [], + "columns": self.columns.keys(), }, { - 'id': 'invalid', - 'title': _('Invalid'), - 'contentFilter': { - 'review_state': 'invalid', - 'sort_on': 'created', - 'sort_order': 'descending', + "id": "invalid", + "title": _("Invalid"), + "contentFilter": { + "review_state": "invalid", + "sort_on": "created", + "sort_order": "descending", }, - 'transitions': [], - 'custom_transitions': [print_stickers], - 'columns': self.columns.keys(), + "transitions": [], + "custom_transitions": [print_stickers], + "columns": self.columns.keys(), }, { - 'id': 'rejected', - 'title': _('Rejected'), - 'contentFilter': { - 'review_state': 'rejected', - 'sort_on': 'created', - 'sort_order': 'descending', + "id": "rejected", + "title": _("Rejected"), + "contentFilter": { + "review_state": "rejected", + "sort_on": "created", + "sort_order": "descending", }, - 'transitions': [], - 'custom_transitions': [ + "transitions": [], + "custom_transitions": [ { - 'id': 'print_stickers', - 'title': _('Print stickers'), - 'url': 'workflow_action?action=print_stickers'}, + "id": "print_stickers", + "title": _("Print stickers"), + "url": "workflow_action?action=print_stickers"}, ], - 'columns': self.columns.keys(), + "columns": self.columns.keys(), }, { - 'id': 'assigned', - 'title': "" % ( + "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', + "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'}, + "transitions": [ + {"id": "receive"}, + {"id": "retract"}, + {"id": "prepublish"}, + {"id": "cancel"}, ], - 'custom_transitions': [print_stickers], - 'columns': self.columns.keys(), + "custom_transitions": [print_stickers], + "columns": self.columns.keys(), }, { - 'id': 'unassigned', - 'title': "" % ( + "id": "unassigned", + "title": "" % ( t(_("Unassigned")), self.portal_url), - 'contentFilter': { - 'assigned_state': 'unassigned', - 'cancellation_state': 'active', - 'review_state': ( - 'sample_received', - 'attachment_due', + "contentFilter": { + "assigned_state": "unassigned", + "cancellation_state": "active", + "review_state": ( + "sample_received", + "attachment_due", ), - 'sort_on': 'created', - 'sort_order': 'descending', + "sort_on": "created", + "sort_order": "descending", }, - 'transitions': [ - {'id': 'receive'}, - {'id': 'retract'}, - {'id': 'prepublish'}, - {'id': 'cancel'}, + "transitions": [ + {"id": "receive"}, + {"id": "retract"}, + {"id": "prepublish"}, + {"id": "cancel"}, ], - 'custom_transitions': [print_stickers], - 'columns': self.columns.keys(), + "custom_transitions": [print_stickers], + "columns": self.columns.keys(), }, ] @@ -514,8 +513,7 @@ def update(self): """ super(AnalysisRequestsView, self).update() - self.workflow = getToolByName(self.context, "portal_workflow") - self.mtool = getToolByName(self.context, 'portal_membership') + self.workflow = api.get_tool("portal_workflow") self.member = self.mtool.getAuthenticatedMember() self.roles = self.member.getRoles() @@ -541,32 +539,32 @@ def update(self): 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 + 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.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 + # 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' + 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 + tmprs["columns"] = [c for c in rs.get("columns", []) if c != printed_colname] tmprvs.append(tmprs) self.review_states = tmprvs @@ -574,10 +572,10 @@ def update(self): # 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_state.get("custom_transitions", []).extend( + [{"id": "print", + "title": _("Print"), + "url": "workflow_action?action=print"}, ]) review_states.append(review_state) self.review_states = review_states @@ -586,10 +584,10 @@ def update(self): 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_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 @@ -598,19 +596,19 @@ def update(self): 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') + 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') + 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', ] + state["hide_transitions"] = ["preserve", ] new_states.append(state) self.review_states = new_states @@ -628,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 @@ -644,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): @@ -657,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 @@ -700,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) @@ -711,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 @@ -792,7 +790,7 @@ def folderitem(self, obj, item, index): item['replace']['ClientContact'] = "%s" % \ (obj.getContactURL, obj.getContactFullName) else: - item['ClientContact'] = "" + 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. @@ -805,17 +803,17 @@ def folderitem(self, obj, item, index): if not obj.getDateSampled: datesampled = self.ulocalized_time( DateTime(), long_format=True) - item['class']['getDateSampled'] = 'provisional' + 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: + item["replace"]["getSampler"] = obj.getSamplerFullName + if "Sampler" in self.roles and not sampler: sampler = self.member.id - item['class']['getSampler'] = 'provisional' + item["class"]["getSampler"] = "provisional" # sampling workflow - inline edits for Sampler and Date Sampled if states_dict.get('review_state', '') == 'to_be_sampled': # We need to get the full object in order to check @@ -824,18 +822,18 @@ def folderitem(self, obj, item, index): checkPermission =\ self.context.portal_membership.checkPermission if checkPermission(SampleSample, full_object): - item['required'] = ['getSampler', 'getDateSampled'] - item['allow_edit'] = ['getSampler', 'getDateSampled'] + 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.getSample(), - ['Sampler', ]) + ["Sampler", ]) username = self.member.getUserName() users = [({ - 'ResultValue': u, - 'ResultText': samplers.getValue(u)}) for u in samplers] + "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 '' @@ -847,14 +845,14 @@ def folderitem(self, obj, item, index): else: datesampled = self.ulocalized_time(obj.getDateSampled, long_format=True) - sampler = '' - item['getDateSampled'] = datesampled - item['getSampler'] = sampler + 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'] = '' + item["getPreserver"] = "" + item["getDatePreserved"] = "" # TODO-performance: If inline preservation wants to be used, we # have to get the full object to check the user permissions, so # far this is a performance hit. @@ -880,7 +878,7 @@ def folderitem(self, obj, item, index): # Submitting user may not verify results # Thee conditions to improve performance, some functions to check # the condition need to get the full analysis request. - if states_dict.get('review_state', '') == 'to_be_verified': + if states_dict.get("review_state", "") == "to_be_verified": allowed = user.has_permission( VerifyPermission, username=self.member.getUserName()) @@ -890,7 +888,7 @@ def folderitem(self, obj, item, index): # Gettin the full object if not get before full_object = full_object if full_object else obj.getObject() if not full_object.isUserAllowedToVerify(self.member): - item['after']['state_title'] = \ + item["after"]["state_title"] = \ """ """ % t(_("Cannot verify: Submitted by current user")) @@ -904,7 +902,7 @@ 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 @@ -934,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}) From 5d3facf22ec58fd76bc72b6360c5e736ea2062dc Mon Sep 17 00:00:00 2001 From: Ramon Bartl Date: Fri, 16 Feb 2018 22:12:41 +0100 Subject: [PATCH 13/15] Set the state of the input field immediately --- bika/lims/browser/js/bika.lims.bikalisting.js | 2 +- bika/lims/browser/js/coffee/bika.lims.bikalisting.coffee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 From 914dbd956c6f41dbef0f385399ee2ed57ae19d38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Fri, 16 Feb 2018 23:36:48 +0100 Subject: [PATCH 14/15] Add #666 entry in CHANGES.rst --- CHANGES.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index c1fd570a30..0fe3a1b88a 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,9 @@ Changelog **Fixed** +- #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 From c8ada5f0541187859a3e5803838787b2751bcb42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Sat, 17 Feb 2018 00:12:07 +0100 Subject: [PATCH 15/15] Added removal of rejected filter in CHANGES.rst --- CHANGES.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.rst b/CHANGES.rst index 0fe3a1b88a..129a08c2d2 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -24,6 +24,7 @@ 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